Embed the install manifests in flux binary

- add make target for generating the install manifests using kustomize
- embed the generated manifests in flux binary
- the install and bootstrap commands default to using the embedded manifests
- download the install manifests from GitHub only if the install/bootstrap version arg is set

Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
pull/987/head
Stefan Prodan 4 years ago
parent 1f16b6d639
commit 6003d11156
No known key found for this signature in database
GPG Key ID: 3299AEB0E4085BAF

@ -17,23 +17,27 @@ jobs:
uses: actions/cache@v1 uses: actions/cache@v1
with: with:
path: ~/go/pkg/mod path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go1.16-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go- ${{ runner.os }}-go1.16-
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
go-version: 1.16.x go-version: 1.16.x
- name: Setup Kubernetes - name: Setup Kubernetes
uses: engineerd/setup-kind@v0.5.0 uses: engineerd/setup-kind@v0.5.0
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Build
run: |
make build-manifests
go build -o /tmp/flux ./cmd/flux
- name: Set outputs - name: Set outputs
id: vars id: vars
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)" run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
- name: Build
run: sudo go build -o ./bin/flux ./cmd/flux
- name: bootstrap init - name: bootstrap init
run: | run: |
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \ --repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \ --branch=main \
@ -42,7 +46,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: bootstrap no-op - name: bootstrap no-op
run: | run: |
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \ --repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \ --branch=main \
@ -51,11 +55,11 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: uninstall - name: uninstall
run: | run: |
./bin/flux uninstall -s --keep-namespace /tmp/flux uninstall -s --keep-namespace
kubectl delete ns flux-system --timeout=10m --wait=true kubectl delete ns flux-system --timeout=10m --wait=true
- name: bootstrap reinstall - name: bootstrap reinstall
run: | run: |
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \ --repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \ --branch=main \
@ -64,7 +68,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: delete repository - name: delete repository
run: | run: |
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \ --repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \ --branch=main \

@ -16,9 +16,9 @@ jobs:
uses: actions/cache@v1 uses: actions/cache@v1
with: with:
path: ~/go/pkg/mod path: ~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} key: ${{ runner.os }}-go1.16-${{ hashFiles('**/go.sum') }}
restore-keys: | restore-keys: |
${{ runner.os }}-go- ${{ runner.os }}-go1.16-
- name: Setup Go - name: Setup Go
uses: actions/setup-go@v2 uses: actions/setup-go@v2
with: with:
@ -33,6 +33,8 @@ jobs:
run: | run: |
kubectl apply -f https://docs.projectcalico.org/v3.16/manifests/calico.yaml kubectl apply -f https://docs.projectcalico.org/v3.16/manifests/calico.yaml
kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Run test - name: Run test
run: make test run: make test
- name: Check if working tree is dirty - name: Check if working tree is dirty
@ -43,43 +45,44 @@ jobs:
exit 1 exit 1
fi fi
- name: Build - name: Build
run: sudo go build -o ./bin/flux ./cmd/flux run: |
go build -o /tmp/flux ./cmd/flux
- name: flux check --pre - name: flux check --pre
run: | run: |
./bin/flux check --pre /tmp/flux check --pre
- name: flux install --manifests - name: flux install --manifests
run: | run: |
./bin/flux install --manifests ./manifests/install/ /tmp/flux install --manifests ./manifests/install/
- name: flux create secret - name: flux create secret
run: | run: |
./bin/flux create secret git git-ssh-test \ /tmp/flux create secret git git-ssh-test \
--url ssh://git@github.com/stefanprodan/podinfo --url ssh://git@github.com/stefanprodan/podinfo
./bin/flux create secret git git-https-test \ /tmp/flux create secret git git-https-test \
--url https://github.com/stefanprodan/podinfo \ --url https://github.com/stefanprodan/podinfo \
--username=test --password=test --username=test --password=test
./bin/flux create secret helm helm-test \ /tmp/flux create secret helm helm-test \
--username=test --password=test --username=test --password=test
- name: flux create source git - name: flux create source git
run: | run: |
./bin/flux create source git podinfo \ /tmp/flux create source git podinfo \
--url https://github.com/stefanprodan/podinfo \ --url https://github.com/stefanprodan/podinfo \
--tag-semver=">=3.2.3" --tag-semver=">=3.2.3"
- name: flux create source git export apply - name: flux create source git export apply
run: | run: |
./bin/flux create source git podinfo-export \ /tmp/flux create source git podinfo-export \
--url https://github.com/stefanprodan/podinfo \ --url https://github.com/stefanprodan/podinfo \
--tag-semver=">=3.2.3" \ --tag-semver=">=3.2.3" \
--export | kubectl apply -f - --export | kubectl apply -f -
./bin/flux delete source git podinfo-export --silent /tmp/flux delete source git podinfo-export --silent
- name: flux get sources git - name: flux get sources git
run: | run: |
./bin/flux get sources git /tmp/flux get sources git
- name: flux get sources git --all-namespaces - name: flux get sources git --all-namespaces
run: | run: |
./bin/flux get sources git --all-namespaces /tmp/flux get sources git --all-namespaces
- name: flux create kustomization - name: flux create kustomization
run: | run: |
./bin/flux create kustomization podinfo \ /tmp/flux create kustomization podinfo \
--source=podinfo \ --source=podinfo \
--path="./deploy/overlays/dev" \ --path="./deploy/overlays/dev" \
--prune=true \ --prune=true \
@ -90,112 +93,112 @@ jobs:
--health-check-timeout=3m --health-check-timeout=3m
- name: flux reconcile kustomization --with-source - name: flux reconcile kustomization --with-source
run: | run: |
./bin/flux reconcile kustomization podinfo --with-source /tmp/flux reconcile kustomization podinfo --with-source
- name: flux get kustomizations - name: flux get kustomizations
run: | run: |
./bin/flux get kustomizations /tmp/flux get kustomizations
- name: flux get kustomizations --all-namespaces - name: flux get kustomizations --all-namespaces
run: | run: |
./bin/flux get kustomizations --all-namespaces /tmp/flux get kustomizations --all-namespaces
- name: flux suspend kustomization - name: flux suspend kustomization
run: | run: |
./bin/flux suspend kustomization podinfo /tmp/flux suspend kustomization podinfo
- name: flux resume kustomization - name: flux resume kustomization
run: | run: |
./bin/flux resume kustomization podinfo /tmp/flux resume kustomization podinfo
- name: flux export - name: flux export
run: | run: |
./bin/flux export source git --all /tmp/flux export source git --all
./bin/flux export kustomization --all /tmp/flux export kustomization --all
- name: flux delete kustomization - name: flux delete kustomization
run: | run: |
./bin/flux delete kustomization podinfo --silent /tmp/flux delete kustomization podinfo --silent
- name: flux create source helm - name: flux create source helm
run: | run: |
./bin/flux create source helm podinfo \ /tmp/flux create source helm podinfo \
--url https://stefanprodan.github.io/podinfo --url https://stefanprodan.github.io/podinfo
- name: flux create helmrelease --source=HelmRepository/podinfo - name: flux create helmrelease --source=HelmRepository/podinfo
run: | run: |
./bin/flux create hr podinfo-helm \ /tmp/flux create hr podinfo-helm \
--target-namespace=default \ --target-namespace=default \
--source=HelmRepository/podinfo \ --source=HelmRepository/podinfo \
--chart=podinfo \ --chart=podinfo \
--chart-version=">4.0.0 <5.0.0" --chart-version=">4.0.0 <5.0.0"
- name: flux create helmrelease --source=GitRepository/podinfo - name: flux create helmrelease --source=GitRepository/podinfo
run: | run: |
./bin/flux create hr podinfo-git \ /tmp/flux create hr podinfo-git \
--target-namespace=default \ --target-namespace=default \
--source=GitRepository/podinfo \ --source=GitRepository/podinfo \
--chart=./charts/podinfo --chart=./charts/podinfo
- name: flux reconcile helmrelease --with-source - name: flux reconcile helmrelease --with-source
run: | run: |
./bin/flux reconcile helmrelease podinfo-git --with-source /tmp/flux reconcile helmrelease podinfo-git --with-source
- name: flux get helmreleases - name: flux get helmreleases
run: | run: |
./bin/flux get helmreleases /tmp/flux get helmreleases
- name: flux get helmreleases --all-namespaces - name: flux get helmreleases --all-namespaces
run: | run: |
./bin/flux get helmreleases --all-namespaces /tmp/flux get helmreleases --all-namespaces
- name: flux export helmrelease - name: flux export helmrelease
run: | run: |
./bin/flux export hr --all /tmp/flux export hr --all
- name: flux delete helmrelease podinfo-helm - name: flux delete helmrelease podinfo-helm
run: | run: |
./bin/flux delete hr podinfo-helm --silent /tmp/flux delete hr podinfo-helm --silent
- name: flux delete helmrelease podinfo-git - name: flux delete helmrelease podinfo-git
run: | run: |
./bin/flux delete hr podinfo-git --silent /tmp/flux delete hr podinfo-git --silent
- name: flux delete source helm - name: flux delete source helm
run: | run: |
./bin/flux delete source helm podinfo --silent /tmp/flux delete source helm podinfo --silent
- name: flux delete source git - name: flux delete source git
run: | run: |
./bin/flux delete source git podinfo --silent /tmp/flux delete source git podinfo --silent
- name: flux create tenant - name: flux create tenant
run: | run: |
./bin/flux create tenant dev-team --with-namespace=apps /tmp/flux create tenant dev-team --with-namespace=apps
./bin/flux -n apps create source helm podinfo \ /tmp/flux -n apps create source helm podinfo \
--url https://stefanprodan.github.io/podinfo --url https://stefanprodan.github.io/podinfo
./bin/flux -n apps create hr podinfo-helm \ /tmp/flux -n apps create hr podinfo-helm \
--source=HelmRepository/podinfo \ --source=HelmRepository/podinfo \
--chart=podinfo \ --chart=podinfo \
--chart-version="5.0.x" \ --chart-version="5.0.x" \
--service-account=dev-team --service-account=dev-team
- name: flux create image repository - name: flux create image repository
run: | run: |
./bin/flux create image repository podinfo \ /tmp/flux create image repository podinfo \
--image=ghcr.io/stefanprodan/podinfo \ --image=ghcr.io/stefanprodan/podinfo \
--interval=1m --interval=1m
- name: flux create image policy - name: flux create image policy
run: | run: |
./bin/flux create image policy podinfo \ /tmp/flux create image policy podinfo \
--image-ref=podinfo \ --image-ref=podinfo \
--interval=1m \ --interval=1m \
--select-semver=5.0.x --select-semver=5.0.x
- name: flux create image policy podinfo-select-alpha - name: flux create image policy podinfo-select-alpha
run: | run: |
./bin/flux create image policy podinfo-alpha \ /tmp/flux create image policy podinfo-alpha \
--image-ref=podinfo \ --image-ref=podinfo \
--interval=1m \ --interval=1m \
--select-alpha=desc --select-alpha=desc
- name: flux get image policy - name: flux get image policy
run: | run: |
./bin/flux get image policy podinfo | grep '5.0.3' /tmp/flux get image policy podinfo | grep '5.0.3'
- name: flux2-kustomize-helm-example - name: flux2-kustomize-helm-example
run: | run: |
./bin/flux create source git flux-system \ /tmp/flux create source git flux-system \
--url=https://github.com/fluxcd/flux2-kustomize-helm-example \ --url=https://github.com/fluxcd/flux2-kustomize-helm-example \
--branch=main --branch=main
./bin/flux create kustomization flux-system \ /tmp/flux create kustomization flux-system \
--source=flux-system \ --source=flux-system \
--path=./clusters/staging --path=./clusters/staging
kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=2m kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=2m
- name: flux check - name: flux check
run: | run: |
./bin/flux check /tmp/flux check
- name: flux uninstall - name: flux uninstall
run: | run: |
./bin/flux uninstall --silent /tmp/flux uninstall --silent
- name: Debug failure - name: Debug failure
if: failure() if: failure()
run: | run: |

@ -2,7 +2,7 @@ name: release
on: on:
push: push:
tags: [ '*' ] tags: [ 'v*' ]
jobs: jobs:
goreleaser: goreleaser:
@ -28,38 +28,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Kustomize - name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main uses: fluxcd/pkg//actions/kustomize@main
- name: Generate manifests tarball - name: Generate manifests
run: |
mkdir -p ./output
files=""
# build controllers
for controller in ./manifests/bases/*/; do
output_path="./output/$(basename $controller).yaml"
echo "building $controller to $output_path"
kustomize build $controller > $output_path
files+=" $(basename $output_path)"
done
# build rbac
rbac_path="./manifests/rbac"
rbac_output_path="./output/rbac.yaml"
echo "building $rbac_path to $rbac_output_path"
kustomize build $rbac_path > $rbac_output_path
files+=" $(basename $rbac_output_path)"
# build policies
policies_path="./manifests/policies"
policies_output_path="./output/policies.yaml"
echo "building $policies_path to $policies_output_path"
kustomize build $policies_path > $policies_output_path
files+=" $(basename $policies_output_path)"
# create tarball
cd ./output && tar -cvzf manifests.tar.gz $files
- name: Generate install manifest
run: | run: |
make build-manifests
./manifests/scripts/bundle.sh ./output manifests.tar.gz
kustomize build ./manifests/install > ./output/install.yaml kustomize build ./manifests/install > ./output/install.yaml
- name: Run GoReleaser - name: Run GoReleaser
uses: goreleaser/goreleaser-action@v1 uses: goreleaser/goreleaser-action@v1

@ -27,6 +27,11 @@ jobs:
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Build manifests
run: |
make build-manifests
- name: Run Snyk to check for vulnerabilities - name: Run Snyk to check for vulnerabilities
uses: snyk/actions/golang@master uses: snyk/actions/golang@master
continue-on-error: true continue-on-error: true

1
.gitignore vendored

@ -15,3 +15,4 @@
# vendor/ # vendor/
bin/ bin/
output/ output/
cmd/flux/manifests/

@ -11,9 +11,12 @@ fmt:
vet: vet:
go vet ./... go vet ./...
test: tidy fmt vet docs test: build-manifests tidy fmt vet docs
go test ./... -coverprofile cover.out go test ./... -coverprofile cover.out
build-manifests:
./manifests/scripts/bundle.sh
build: build:
CGO_ENABLED=0 go build -o ./bin/flux ./cmd/flux CGO_ENABLED=0 go build -o ./bin/flux ./cmd/flux

@ -70,8 +70,8 @@ const (
var bootstrapArgs = NewBootstrapFlags() var bootstrapArgs = NewBootstrapFlags()
func init() { func init() {
bootstrapCmd.PersistentFlags().StringVarP(&bootstrapArgs.version, "version", "v", rootArgs.defaults.Version, bootstrapCmd.PersistentFlags().StringVarP(&bootstrapArgs.version, "version", "v", "",
"toolkit version") "toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases")
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.defaultComponents, "components", rootArgs.defaults.Components, bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.defaultComponents, "components", rootArgs.defaults.Components,
"list of components, accepts comma-separated values") "list of components, accepts comma-separated values")
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.extraComponents, "components-extra", nil, bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.extraComponents, "components-extra", nil,
@ -126,23 +126,18 @@ func bootstrapValidate() error {
} }
func generateInstallManifests(targetPath, namespace, tmpDir string, localManifests string) (string, error) { func generateInstallManifests(targetPath, namespace, tmpDir string, localManifests string) (string, error) {
if bootstrapArgs.version == install.MakeDefaultOptions().Version { if ver, err := getVersion(bootstrapArgs.version); err != nil {
version, err := install.GetLatestVersion()
if err != nil {
return "", err return "", err
}
bootstrapArgs.version = version
} else { } else {
if ok, err := install.ExistingVersion(bootstrapArgs.version); err != nil || !ok { bootstrapArgs.version = ver
if err == nil {
err = fmt.Errorf("targeted version '%s' does not exist", bootstrapArgs.version)
} }
manifestsBase := ""
if isEmbeddedVersion(bootstrapArgs.version) {
if err := writeEmbeddedManifests(tmpDir); err != nil {
return "", err return "", err
} }
} manifestsBase = tmpDir
if !utils.CompatibleVersion(VERSION, bootstrapArgs.version) {
return "", fmt.Errorf("targeted version '%s' is not compatible with your current version of flux (%s)", bootstrapArgs.version, VERSION)
} }
opts := install.Options{ opts := install.Options{
@ -167,7 +162,7 @@ func generateInstallManifests(targetPath, namespace, tmpDir string, localManifes
opts.BaseURL = rootArgs.defaults.BaseURL opts.BaseURL = rootArgs.defaults.BaseURL
} }
output, err := install.Generate(opts) output, err := install.Generate(opts, manifestsBase)
if err != nil { if err != nil {
return "", fmt.Errorf("generating install manifests failed: %w", err) return "", fmt.Errorf("generating install manifests failed: %w", err)
} }

@ -0,0 +1,31 @@
package main
import (
"embed"
"fmt"
"io/fs"
"os"
"path"
)
//go:embed manifests/*.yaml
var embeddedManifests embed.FS
func writeEmbeddedManifests(dir string) error {
manifests, err := fs.ReadDir(embeddedManifests, "manifests")
if err != nil {
return err
}
for _, manifest := range manifests {
data, err := fs.ReadFile(embeddedManifests, path.Join("manifests", manifest.Name()))
if err != nil {
return fmt.Errorf("reading file failed: %w", err)
}
err = os.WriteFile(path.Join(dir, manifest.Name()), data, 0666)
if err != nil {
return fmt.Errorf("writing file failed: %w", err)
}
}
return nil
}

@ -55,79 +55,81 @@ If a previous version is installed, then an in-place upgrade will be performed.`
RunE: installCmdRun, RunE: installCmdRun,
} }
var ( type installFlags struct {
installExport bool export bool
installDryRun bool dryRun bool
installManifestsPath string version string
installVersion string defaultComponents []string
installDefaultComponents []string extraComponents []string
installExtraComponents []string registry string
installRegistry string imagePullSecret string
installImagePullSecret string branch string
installWatchAllNamespaces bool watchAllNamespaces bool
installNetworkPolicy bool networkPolicy bool
installArch flags.Arch manifestsPath string
installLogLevel = flags.LogLevel(rootArgs.defaults.LogLevel) arch flags.Arch
installClusterDomain string logLevel flags.LogLevel
installTolerationKeys []string tokenAuth bool
) clusterDomain string
tolerationKeys []string
}
var installArgs = NewInstallFlags()
func init() { func init() {
installCmd.Flags().BoolVar(&installExport, "export", false, installCmd.Flags().BoolVar(&installArgs.export, "export", false,
"write the install manifests to stdout and exit") "write the install manifests to stdout and exit")
installCmd.Flags().BoolVarP(&installDryRun, "dry-run", "", false, installCmd.Flags().BoolVarP(&installArgs.dryRun, "dry-run", "", false,
"only print the object that would be applied") "only print the object that would be applied")
installCmd.Flags().StringVarP(&installVersion, "version", "v", rootArgs.defaults.Version, installCmd.Flags().StringVarP(&installArgs.version, "version", "v", "",
"toolkit version") "toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases")
installCmd.Flags().StringSliceVar(&installDefaultComponents, "components", rootArgs.defaults.Components, installCmd.Flags().StringSliceVar(&installArgs.defaultComponents, "components", rootArgs.defaults.Components,
"list of components, accepts comma-separated values") "list of components, accepts comma-separated values")
installCmd.Flags().StringSliceVar(&installExtraComponents, "components-extra", nil, installCmd.Flags().StringSliceVar(&installArgs.extraComponents, "components-extra", nil,
"list of components in addition to those supplied or defaulted, accepts comma-separated values") "list of components in addition to those supplied or defaulted, accepts comma-separated values")
installCmd.Flags().StringVar(&installManifestsPath, "manifests", "", "path to the manifest directory") installCmd.Flags().StringVar(&installArgs.manifestsPath, "manifests", "", "path to the manifest directory")
installCmd.Flags().StringVar(&installRegistry, "registry", rootArgs.defaults.Registry, installCmd.Flags().StringVar(&installArgs.registry, "registry", rootArgs.defaults.Registry,
"container registry where the toolkit images are published") "container registry where the toolkit images are published")
installCmd.Flags().StringVar(&installImagePullSecret, "image-pull-secret", "", installCmd.Flags().StringVar(&installArgs.imagePullSecret, "image-pull-secret", "",
"Kubernetes secret name used for pulling the toolkit images from a private registry") "Kubernetes secret name used for pulling the toolkit images from a private registry")
installCmd.Flags().Var(&installArch, "arch", installArch.Description()) installCmd.Flags().Var(&installArgs.arch, "arch", installArgs.arch.Description())
installCmd.Flags().BoolVar(&installWatchAllNamespaces, "watch-all-namespaces", rootArgs.defaults.WatchAllNamespaces, installCmd.Flags().BoolVar(&installArgs.watchAllNamespaces, "watch-all-namespaces", rootArgs.defaults.WatchAllNamespaces,
"watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed") "watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed")
installCmd.Flags().Var(&installLogLevel, "log-level", installLogLevel.Description()) installCmd.Flags().Var(&installArgs.logLevel, "log-level", installArgs.logLevel.Description())
installCmd.Flags().BoolVar(&installNetworkPolicy, "network-policy", rootArgs.defaults.NetworkPolicy, installCmd.Flags().BoolVar(&installArgs.networkPolicy, "network-policy", rootArgs.defaults.NetworkPolicy,
"deny ingress access to the toolkit controllers from other namespaces using network policies") "deny ingress access to the toolkit controllers from other namespaces using network policies")
installCmd.Flags().StringVar(&installClusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain") installCmd.Flags().StringVar(&installArgs.clusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain")
installCmd.Flags().StringSliceVar(&installTolerationKeys, "toleration-keys", nil, installCmd.Flags().StringSliceVar(&installArgs.tolerationKeys, "toleration-keys", nil,
"list of toleration keys used to schedule the components pods onto nodes with matching taints") "list of toleration keys used to schedule the components pods onto nodes with matching taints")
installCmd.Flags().MarkHidden("manifests") installCmd.Flags().MarkHidden("manifests")
installCmd.Flags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64") installCmd.Flags().MarkDeprecated("arch", "multi-arch container image is now available for AMD64, ARMv7 and ARM64")
rootCmd.AddCommand(installCmd) rootCmd.AddCommand(installCmd)
} }
func NewInstallFlags() installFlags {
return installFlags{
logLevel: flags.LogLevel(rootArgs.defaults.LogLevel),
}
}
func installCmdRun(cmd *cobra.Command, args []string) error { func installCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()
components := append(installDefaultComponents, installExtraComponents...) components := append(installArgs.defaultComponents, installArgs.extraComponents...)
err := utils.ValidateComponents(components) err := utils.ValidateComponents(components)
if err != nil { if err != nil {
return err return err
} }
if installVersion == install.MakeDefaultOptions().Version { if ver, err := getVersion(installArgs.version); err != nil {
installVersion, err = install.GetLatestVersion()
if err != nil {
return err return err
}
} else { } else {
if ok, err := install.ExistingVersion(installVersion); err != nil || !ok { installArgs.version = ver
if err == nil {
err = fmt.Errorf("targeted version '%s' does not exist", installVersion)
}
return err
}
} }
if !utils.CompatibleVersion(VERSION, installVersion) { if !installArgs.export {
return fmt.Errorf("targeted version '%s' is not compatible with your current version of flux (%s)", installVersion, VERSION) logger.Generatef("generating manifests")
} }
tmpDir, err := ioutil.TempDir("", rootArgs.namespace) tmpDir, err := ioutil.TempDir("", rootArgs.namespace)
@ -136,32 +138,36 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
} }
defer os.RemoveAll(tmpDir) defer os.RemoveAll(tmpDir)
if !installExport { manifestsBase := ""
logger.Generatef("generating manifests") if isEmbeddedVersion(installArgs.version) {
if err := writeEmbeddedManifests(tmpDir); err != nil {
return err
}
manifestsBase = tmpDir
} }
opts := install.Options{ opts := install.Options{
BaseURL: installManifestsPath, BaseURL: installArgs.manifestsPath,
Version: installVersion, Version: installArgs.version,
Namespace: rootArgs.namespace, Namespace: rootArgs.namespace,
Components: components, Components: components,
Registry: installRegistry, Registry: installArgs.registry,
ImagePullSecret: installImagePullSecret, ImagePullSecret: installArgs.imagePullSecret,
WatchAllNamespaces: installWatchAllNamespaces, WatchAllNamespaces: installArgs.watchAllNamespaces,
NetworkPolicy: installNetworkPolicy, NetworkPolicy: installArgs.networkPolicy,
LogLevel: installLogLevel.String(), LogLevel: installArgs.logLevel.String(),
NotificationController: rootArgs.defaults.NotificationController, NotificationController: rootArgs.defaults.NotificationController,
ManifestFile: fmt.Sprintf("%s.yaml", rootArgs.namespace), ManifestFile: fmt.Sprintf("%s.yaml", rootArgs.namespace),
Timeout: rootArgs.timeout, Timeout: rootArgs.timeout,
ClusterDomain: installClusterDomain, ClusterDomain: installArgs.clusterDomain,
TolerationKeys: installTolerationKeys, TolerationKeys: installArgs.tolerationKeys,
} }
if installManifestsPath == "" { if installArgs.manifestsPath == "" {
opts.BaseURL = install.MakeDefaultOptions().BaseURL opts.BaseURL = install.MakeDefaultOptions().BaseURL
} }
manifest, err := install.Generate(opts) manifest, err := install.Generate(opts, manifestsBase)
if err != nil { if err != nil {
return fmt.Errorf("install failed: %w", err) return fmt.Errorf("install failed: %w", err)
} }
@ -172,9 +178,9 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
if rootArgs.verbose { if rootArgs.verbose {
fmt.Print(manifest.Content) fmt.Print(manifest.Content)
} else if installExport { } else if installArgs.export {
fmt.Println("---") fmt.Println("---")
fmt.Println("# Flux version:", installVersion) fmt.Println("# Flux version:", installArgs.version)
fmt.Println("# Components:", strings.Join(components, ",")) fmt.Println("# Components:", strings.Join(components, ","))
fmt.Print(manifest.Content) fmt.Print(manifest.Content)
fmt.Println("---") fmt.Println("---")
@ -189,7 +195,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
} }
kubectlArgs := []string{"apply", "-f", filepath.Join(tmpDir, manifest.Path)} kubectlArgs := []string{"apply", "-f", filepath.Join(tmpDir, manifest.Path)}
if installDryRun { if installArgs.dryRun {
kubectlArgs = append(kubectlArgs, "--dry-run=client") kubectlArgs = append(kubectlArgs, "--dry-run=client")
applyOutput = utils.ModeOS applyOutput = utils.ModeOS
} }
@ -197,7 +203,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
if installDryRun { if installArgs.dryRun {
logger.Successf("install dry-run finished") logger.Successf("install dry-run finished")
return nil return nil
} }

@ -115,10 +115,12 @@ func init() {
} }
func NewRootFlags() rootFlags { func NewRootFlags() rootFlags {
return rootFlags{ rf := rootFlags{
pollInterval: 2 * time.Second, pollInterval: 2 * time.Second,
defaults: install.MakeDefaultOptions(), defaults: install.MakeDefaultOptions(),
} }
rf.defaults.Version = "v" + VERSION
return rf
} }
func main() { func main() {

@ -0,0 +1,42 @@
package main
import (
"fmt"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/flux2/pkg/manifestgen/install"
)
func getVersion(input string) (string, error) {
if input == "" {
return rootArgs.defaults.Version, nil
}
if isEmbeddedVersion(input) {
return input, nil
}
var err error
if input == install.MakeDefaultOptions().Version {
input, err = install.GetLatestVersion()
if err != nil {
return "", err
}
} else {
if ok, err := install.ExistingVersion(input); err != nil || !ok {
if err == nil {
err = fmt.Errorf("targeted version '%s' does not exist", input)
}
return "", err
}
}
if !utils.CompatibleVersion(VERSION, input) {
return "", fmt.Errorf("targeted version '%s' is not compatible with your current version of flux (%s)", input, VERSION)
}
return input, nil
}
func isEmbeddedVersion(input string) bool {
return input == rootArgs.defaults.Version
}

@ -20,7 +20,7 @@ The bootstrap sub-commands bootstrap the toolkit components on the targeted Git
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
--token-auth when enabled, the personal access token will be used instead of SSH deploy key --token-auth when enabled, the personal access token will be used instead of SSH deploy key
--toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints --toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints
-v, --version string toolkit version (default "latest") -v, --version string toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
``` ```

@ -76,7 +76,7 @@ flux bootstrap github [flags]
--token-auth when enabled, the personal access token will be used instead of SSH deploy key --token-auth when enabled, the personal access token will be used instead of SSH deploy key
--toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints --toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints
--verbose print generated objects --verbose print generated objects
-v, --version string toolkit version (default "latest") -v, --version string toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
``` ```

@ -72,7 +72,7 @@ flux bootstrap gitlab [flags]
--token-auth when enabled, the personal access token will be used instead of SSH deploy key --token-auth when enabled, the personal access token will be used instead of SSH deploy key
--toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints --toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints
--verbose print generated objects --verbose print generated objects
-v, --version string toolkit version (default "latest") -v, --version string toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
``` ```

@ -45,7 +45,7 @@ flux install [flags]
--network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true) --network-policy deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
--registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd") --registry string container registry where the toolkit images are published (default "ghcr.io/fluxcd")
--toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints --toleration-keys strings list of toleration keys used to schedule the components pods onto nodes with matching taints
-v, --version string toolkit version (default "latest") -v, --version string toolkit version, when specified the manifests are downloaded from https://github.com/fluxcd/flux2/releases
--watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true) --watch-all-namespaces watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
``` ```

@ -0,0 +1,70 @@
#!/usr/bin/env bash
# Copyright 2020 The Flux authors. All rights reserved.
#
# 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.
set -e
REPO_ROOT=$(git rev-parse --show-toplevel)
OUT_PATH=${1:-"${REPO_ROOT}/cmd/flux/manifests"}
TAR=${2}
info() {
echo '[INFO] ' "$@"
}
fatal() {
echo '[ERROR] ' "$@" >&2
exit 1
}
build() {
info "building $(basename $2)"
kustomize build "$1" > "$2"
}
if ! [ -x "$(command -v kustomize)" ]; then
fatal 'kustomize is not installed'
fi
rm -rf $OUT_PATH
mkdir -p $OUT_PATH
files=""
info using "$(kustomize version --short)"
# build controllers
for controller in ${REPO_ROOT}/manifests/bases/*/; do
output_path="${OUT_PATH}/$(basename $controller).yaml"
build $controller $output_path
files+=" $(basename $output_path)"
done
# build rbac
rbac_path="${REPO_ROOT}/manifests/rbac"
rbac_output_path="${OUT_PATH}/rbac.yaml"
build $rbac_path $rbac_output_path
files+=" $(basename $rbac_output_path)"
# build policies
policies_path="${REPO_ROOT}/manifests/policies"
policies_output_path="${OUT_PATH}/policies.yaml"
build $policies_path $policies_output_path
files+=" $(basename $policies_output_path)"
# create tarball
if [[ -n $TAR ]];then
info "archiving $TAR"
cd ${OUT_PATH} && tar -czf $TAR $files
fi

@ -35,17 +35,15 @@ import (
// Generate returns the install manifests as a multi-doc YAML. // Generate returns the install manifests as a multi-doc YAML.
// The manifests are built from a GitHub release or from a // The manifests are built from a GitHub release or from a
// Kustomize overlay if the supplied Options.BaseURL is a local path. // Kustomize overlay if the supplied Options.BaseURL is a local path.
func Generate(options Options) (*manifestgen.Manifest, error) { // The manifestsBase should be set to an empty string when Generate is
// called by consumers that don't embed the manifests.
func Generate(options Options, manifestsBase string) (*manifestgen.Manifest, error) {
ctx, cancel := context.WithTimeout(context.Background(), options.Timeout) ctx, cancel := context.WithTimeout(context.Background(), options.Timeout)
defer cancel() defer cancel()
tmpDir, err := ioutil.TempDir("", options.Namespace) var err error
if err != nil {
return nil, fmt.Errorf("temp dir error: %w", err)
}
defer os.RemoveAll(tmpDir)
output, err := securejoin.SecureJoin(tmpDir, options.ManifestFile) output, err := securejoin.SecureJoin(manifestsBase, options.ManifestFile)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -55,15 +53,27 @@ func Generate(options Options) (*manifestgen.Manifest, error) {
return nil, err return nil, err
} }
} else { } else {
if err := fetch(ctx, options.BaseURL, options.Version, tmpDir); err != nil { // download the manifests base from GitHub
if manifestsBase == "" {
manifestsBase, err = ioutil.TempDir("", options.Namespace)
if err != nil {
return nil, fmt.Errorf("temp dir error: %w", err)
}
defer os.RemoveAll(manifestsBase)
output, err = securejoin.SecureJoin(manifestsBase, options.ManifestFile)
if err != nil {
return nil, err return nil, err
} }
if err := fetch(ctx, options.BaseURL, options.Version, manifestsBase); err != nil {
return nil, err
}
}
if err := generate(tmpDir, options); err != nil { if err := generate(manifestsBase, options); err != nil {
return nil, err return nil, err
} }
if err := build(tmpDir, output); err != nil { if err := build(manifestsBase, output); err != nil {
return nil, err return nil, err
} }
} }

@ -25,7 +25,7 @@ import (
func TestGenerate(t *testing.T) { func TestGenerate(t *testing.T) {
opts := MakeDefaultOptions() opts := MakeDefaultOptions()
opts.TolerationKeys = []string{"node.kubernetes.io/controllers"} opts.TolerationKeys = []string{"node.kubernetes.io/controllers"}
output, err := Generate(opts) output, err := Generate(opts, "")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

Loading…
Cancel
Save