mirror of
				https://github.com/fluxcd/flux2.git
				synced 2025-10-31 08:17:19 +08:00 
			
		
		
		
	Allow pre-bootstrap customisation of Flux components
Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
This commit is contained in:
		 Stefan Prodan
					Stefan Prodan
				
			
				
					committed by
					
						 Hidde Beydals
						Hidde Beydals
					
				
			
			
				
	
			
			
			 Hidde Beydals
						Hidde Beydals
					
				
			
						parent
						
							baa54fb84a
						
					
				
				
					commit
					4a4af94d6c
				
			| @ -19,6 +19,8 @@ package bootstrap | |||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io/ioutil" | ||||||
|  | 	"os" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| @ -29,6 +31,7 @@ import ( | |||||||
| 	"sigs.k8s.io/cli-utils/pkg/object" | 	"sigs.k8s.io/cli-utils/pkg/object" | ||||||
| 	"sigs.k8s.io/controller-runtime/pkg/client" | 	"sigs.k8s.io/controller-runtime/pkg/client" | ||||||
| 	"sigs.k8s.io/kustomize/api/filesys" | 	"sigs.k8s.io/kustomize/api/filesys" | ||||||
|  | 	"sigs.k8s.io/kustomize/api/konfig" | ||||||
| 	"sigs.k8s.io/yaml" | 	"sigs.k8s.io/yaml" | ||||||
|  |  | ||||||
| 	kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" | 	kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" | ||||||
| @ -152,11 +155,49 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest | |||||||
|  |  | ||||||
| 	// Conditionally install manifests | 	// Conditionally install manifests | ||||||
| 	if mustInstallManifests(ctx, b.kube, options.Namespace) { | 	if mustInstallManifests(ctx, b.kube, options.Namespace) { | ||||||
| 		b.logger.Actionf("installing components in %q namespace", options.Namespace) | 		componentsYAML := filepath.Join(b.git.Path(), manifests.Path) | ||||||
| 		kubectlArgs := []string{"apply", "-f", filepath.Join(b.git.Path(), manifests.Path)} |  | ||||||
|  | 		// Apply components using any existing customisations | ||||||
|  | 		kfile := filepath.Join(filepath.Dir(componentsYAML), konfig.DefaultKustomizationFileName()) | ||||||
|  | 		if _, err := os.Stat(kfile); err == nil { | ||||||
|  | 			tmpDir, err := ioutil.TempDir("", "gotk-crds") | ||||||
|  | 			defer os.RemoveAll(tmpDir) | ||||||
|  |  | ||||||
|  | 			// Extract the CRDs from the components manifest | ||||||
|  | 			crdsYAML := filepath.Join(tmpDir, "gotk-crds.yaml") | ||||||
|  | 			if err := utils.ExtractCRDs(componentsYAML, crdsYAML); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			// Apply the CRDs | ||||||
|  | 			b.logger.Actionf("installing toolkit.fluxcd.io CRDs") | ||||||
|  | 			kubectlArgs := []string{"apply", "-f", crdsYAML} | ||||||
| 			if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil { | 			if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil { | ||||||
| 				return err | 				return err | ||||||
| 			} | 			} | ||||||
|  |  | ||||||
|  | 			// Wait for CRDs to be established | ||||||
|  | 			b.logger.Waitingf("waiting for CRDs to be reconciled") | ||||||
|  | 			kubectlArgs = []string{"wait", "--for", "condition=established", "-f", crdsYAML} | ||||||
|  | 			if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			b.logger.Successf("CRDs reconciled successfully") | ||||||
|  |  | ||||||
|  | 			// Apply the components and their patches | ||||||
|  | 			b.logger.Actionf("installing components in %q namespace", options.Namespace) | ||||||
|  | 			kubectlArgs = []string{"apply", "-k", filepath.Dir(componentsYAML)} | ||||||
|  | 			if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			// Apply the CRDs and controllers | ||||||
|  | 			b.logger.Actionf("installing components in %q namespace", options.Namespace) | ||||||
|  | 			kubectlArgs := []string{"apply", "-f", componentsYAML} | ||||||
|  | 			if _, err = utils.ExecKubectlCommand(ctx, utils.ModeStderrOS, b.kubeconfig, b.kubecontext, kubectlArgs...); err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		b.logger.Successf("installed components") | 		b.logger.Successf("installed components") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | |||||||
| @ -22,6 +22,7 @@ import ( | |||||||
| 	"context" | 	"context" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" | 	"io" | ||||||
|  | 	"io/ioutil" | ||||||
| 	"os" | 	"os" | ||||||
| 	"os/exec" | 	"os/exec" | ||||||
| 	"path/filepath" | 	"path/filepath" | ||||||
| @ -47,6 +48,16 @@ import ( | |||||||
| 	"k8s.io/client-go/rest" | 	"k8s.io/client-go/rest" | ||||||
| 	"k8s.io/client-go/tools/clientcmd" | 	"k8s.io/client-go/tools/clientcmd" | ||||||
| 	"sigs.k8s.io/controller-runtime/pkg/client" | 	"sigs.k8s.io/controller-runtime/pkg/client" | ||||||
|  | 	"sigs.k8s.io/yaml" | ||||||
|  |  | ||||||
|  | 	helmv2 "github.com/fluxcd/helm-controller/api/v2beta1" | ||||||
|  | 	imageautov1 "github.com/fluxcd/image-automation-controller/api/v1alpha1" | ||||||
|  | 	imagereflectv1 "github.com/fluxcd/image-reflector-controller/api/v1alpha1" | ||||||
|  | 	kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1" | ||||||
|  | 	notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1" | ||||||
|  | 	"github.com/fluxcd/pkg/runtime/dependency" | ||||||
|  | 	"github.com/fluxcd/pkg/version" | ||||||
|  | 	sourcev1 "github.com/fluxcd/source-controller/api/v1beta1" | ||||||
|  |  | ||||||
| 	"github.com/fluxcd/flux2/pkg/manifestgen/install" | 	"github.com/fluxcd/flux2/pkg/manifestgen/install" | ||||||
| ) | ) | ||||||
| @ -313,3 +324,41 @@ func CompatibleVersion(binary, target string) bool { | |||||||
| 	} | 	} | ||||||
| 	return binSv.Major() == targetSv.Major() && binSv.Minor() == targetSv.Minor() | 	return binSv.Major() == targetSv.Major() && binSv.Minor() == targetSv.Minor() | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func ExtractCRDs(inManifestPath, outManifestPath string) error { | ||||||
|  | 	manifests, err := ioutil.ReadFile(inManifestPath) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	crds := "" | ||||||
|  | 	reader := sigyaml.NewYAMLOrJSONDecoder(bytes.NewReader(manifests), 2048) | ||||||
|  |  | ||||||
|  | 	for { | ||||||
|  | 		var obj unstructured.Unstructured | ||||||
|  | 		err := reader.Decode(&obj) | ||||||
|  | 		if err == io.EOF { | ||||||
|  | 			break | ||||||
|  | 		} else if err != nil { | ||||||
|  | 			return err | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if obj.GetKind() == "CustomResourceDefinition" { | ||||||
|  | 			b, err := obj.MarshalJSON() | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			y, err := yaml.JSONToYAML(b) | ||||||
|  | 			if err != nil { | ||||||
|  | 				return err | ||||||
|  | 			} | ||||||
|  | 			crds += "---\n" + string(y) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if crds == "" { | ||||||
|  | 		return fmt.Errorf("no CRDs found in %s", inManifestPath) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return ioutil.WriteFile(outManifestPath, []byte(crds), os.ModePerm) | ||||||
|  | } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user