mirror of https://github.com/fluxcd/flux2.git
				
				
				
			
			You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			140 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.4 KiB
		
	
	
	
		
			Go
		
	
| /*
 | |
| Copyright 2020 The Flux authors
 | |
| 
 | |
| Licensed under the Apache License, Version 2.0 (the "License");
 | |
| you may not use this file except in compliance with the License.
 | |
| You may obtain a copy of the License at
 | |
| 
 | |
|     http://www.apache.org/licenses/LICENSE-2.0
 | |
| 
 | |
| Unless required by applicable law or agreed to in writing, software
 | |
| distributed under the License is distributed on an "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | |
| See the License for the specific language governing permissions and
 | |
| limitations under the License.
 | |
| */
 | |
| 
 | |
| package install
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"net/http"
 | |
| 	"os"
 | |
| 	"path"
 | |
| 	"path/filepath"
 | |
| 	"strings"
 | |
| 
 | |
| 	"github.com/fluxcd/pkg/kustomize/filesys"
 | |
| 	"github.com/fluxcd/pkg/untar"
 | |
| 
 | |
| 	"github.com/fluxcd/flux2/pkg/manifestgen/kustomization"
 | |
| )
 | |
| 
 | |
| func fetch(ctx context.Context, url, version, dir string) error {
 | |
| 	ghURL := fmt.Sprintf("%s/latest/download/manifests.tar.gz", url)
 | |
| 	if strings.HasPrefix(version, "v") {
 | |
| 		ghURL = fmt.Sprintf("%s/download/%s/manifests.tar.gz", url, version)
 | |
| 	}
 | |
| 
 | |
| 	req, err := http.NewRequest("GET", ghURL, nil)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to create HTTP request for %s, error: %w", ghURL, err)
 | |
| 	}
 | |
| 
 | |
| 	// download
 | |
| 	resp, err := http.DefaultClient.Do(req.WithContext(ctx))
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to download manifests.tar.gz from %s, error: %w", ghURL, err)
 | |
| 	}
 | |
| 	defer resp.Body.Close()
 | |
| 
 | |
| 	// check response
 | |
| 	if resp.StatusCode != http.StatusOK {
 | |
| 		return fmt.Errorf("failed to download manifests.tar.gz from %s, status: %s", ghURL, resp.Status)
 | |
| 	}
 | |
| 
 | |
| 	// extract
 | |
| 	if _, err = untar.Untar(resp.Body, dir); err != nil {
 | |
| 		return fmt.Errorf("failed to untar manifests.tar.gz from %s, error: %w", ghURL, err)
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func generate(base string, options Options) error {
 | |
| 	if containsItemString(options.Components, options.NotificationController) {
 | |
| 		// We need to use full domain name here, as some users may deploy flux
 | |
| 		// in environments that use http proxy.
 | |
| 		//
 | |
| 		// In such environments they normally add `.cluster.local` and `.local`
 | |
| 		// suffixes to `no_proxy` variable in order to prevent cluster-local
 | |
| 		// traffic from going through http proxy. Without fully specified
 | |
| 		// domain they need to mention `notifications-controller` explicitly in
 | |
| 		// `no_proxy` variable after debugging http proxy logs.
 | |
| 		options.EventsAddr = fmt.Sprintf("http://%s.%s.svc.%s./", options.NotificationController, options.Namespace, options.ClusterDomain)
 | |
| 	}
 | |
| 
 | |
| 	if err := execTemplate(options, namespaceTmpl, path.Join(base, "namespace.yaml")); err != nil {
 | |
| 		return fmt.Errorf("generate namespace failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if err := execTemplate(options, labelsTmpl, path.Join(base, "labels.yaml")); err != nil {
 | |
| 		return fmt.Errorf("generate labels failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if err := execTemplate(options, nodeSelectorTmpl, path.Join(base, "node-selector.yaml")); err != nil {
 | |
| 		return fmt.Errorf("generate node selector failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if err := execTemplate(options, kustomizationTmpl, path.Join(base, "kustomization.yaml")); err != nil {
 | |
| 		return fmt.Errorf("generate kustomization failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if err := os.MkdirAll(path.Join(base, "roles"), os.ModePerm); err != nil {
 | |
| 		return fmt.Errorf("generate roles failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	if err := execTemplate(options, kustomizationRolesTmpl, path.Join(base, "roles/kustomization.yaml")); err != nil {
 | |
| 		return fmt.Errorf("generate roles kustomization failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	rbacFile := filepath.Join(base, "roles/rbac.yaml")
 | |
| 	if err := copyFile(filepath.Join(base, "rbac.yaml"), rbacFile); err != nil {
 | |
| 		return fmt.Errorf("generate rbac failed: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	// workaround for kustomize not being able to patch the SA in ClusterRoleBindings
 | |
| 	defaultNS := MakeDefaultOptions().Namespace
 | |
| 	if defaultNS != options.Namespace {
 | |
| 		rbac, err := os.ReadFile(rbacFile)
 | |
| 		if err != nil {
 | |
| 			return fmt.Errorf("reading rbac file failed: %w", err)
 | |
| 		}
 | |
| 		rbac = bytes.ReplaceAll(rbac, []byte(defaultNS), []byte(options.Namespace))
 | |
| 		if err := os.WriteFile(rbacFile, rbac, os.ModePerm); err != nil {
 | |
| 			return fmt.Errorf("replacing service account namespace in rbac failed: %w", err)
 | |
| 		}
 | |
| 	}
 | |
| 	return nil
 | |
| }
 | |
| 
 | |
| func build(base, output string) error {
 | |
| 	resources, err := kustomization.Build(base)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	outputBase := filepath.Dir(strings.TrimSuffix(output, string(filepath.Separator)))
 | |
| 	fs, err := filesys.MakeFsOnDiskSecure(outputBase)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	if err = fs.WriteFile(output, resources); err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	return nil
 | |
| }
 |