1
0
mirror of synced 2026-03-01 19:26:55 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Joel Bennett
2d3f3a4be5 Correct "sync" to "component" in log lines
Signed-off-by: Joel Bennett <Jaykul@HuddledMasses.org>
2023-12-12 09:08:10 +02:00
210 changed files with 7354 additions and 3683 deletions

View File

@@ -1,9 +1,5 @@
kind: Cluster kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4 apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
networking: networking:
disableDefaultCNI: true # disable kindnet disableDefaultCNI: true # disable kindnet
podSubnet: 192.168.0.0/16 # set to Calico's default subnet podSubnet: 192.168.0.0/16 # set to Calico's default subnet

6
.github/labels.yaml vendored
View File

@@ -50,9 +50,3 @@
- name: backport:release/v2.1.x - name: backport:release/v2.1.x
description: To be backported to release/v2.1.x description: To be backported to release/v2.1.x
color: '#ffd700' color: '#ffd700'
- name: backport:release/v2.2.x
description: To be backported to release/v2.2.x
color: '#ffd700'
- name: backport:release/v2.3.x
description: To be backported to release/v2.3.x
color: '#ffd700'

View File

@@ -5,17 +5,15 @@ The Flux ARM64 end-to-end tests run on Equinix Metal instances provisioned with
## Current instances ## Current instances
| Repository | Runner | Instance | Location | | Repository | Runner | Instance | Location |
|-----------------------------|------------------|----------------|---------------| |-----------------------------|------------------|------------------------|---------------|
| flux2 | equinix-arm-dc-1 | flux-arm-dc-01 | Washington DC | | flux2 | equinix-arm-dc-1 | flux-equinix-arm-dc-01 | Washington DC |
| flux2 | equinix-arm-dc-2 | flux-arm-dc-01 | Washington DC | | flux2 | equinix-arm-dc-2 | flux-equinix-arm-dc-01 | Washington DC |
| flux2 | equinix-arm-da-1 | flux-arm-da-01 | Dallas | | flux2 | equinix-arm-da-1 | flux-equinix-arm-da-01 | Dallas |
| flux2 | equinix-arm-da-2 | flux-arm-da-01 | Dallas | | flux2 | equinix-arm-da-2 | flux-equinix-arm-da-01 | Dallas |
| flux-benchmark | equinix-arm-dc-1 | flux-arm-dc-01 | Washington DC | | source-controller | equinix-arm-dc-1 | flux-equinix-arm-dc-01 | Washington DC |
| flux-benchmark | equinix-arm-da-1 | flux-arm-da-01 | Dallas | | source-controller | equinix-arm-da-1 | flux-equinix-arm-da-01 | Dallas |
| source-controller | equinix-arm-dc-1 | flux-arm-dc-01 | Washington DC | | image-automation-controller | equinix-arm-dc-1 | flux-equinix-arm-dc-01 | Washington DC |
| source-controller | equinix-arm-da-1 | flux-arm-da-01 | Dallas | | image-automation-controller | equinix-arm-da-1 | flux-equinix-arm-da-01 | Dallas |
| image-automation-controller | equinix-arm-dc-1 | flux-arm-dc-01 | Washington DC |
| image-automation-controller | equinix-arm-da-1 | flux-arm-da-01 | Dallas |
Instance spec: Instance spec:
- Ampere Altra Q80-30 80-core processor @ 2.8GHz - Ampere Altra Q80-30 80-core processor @ 2.8GHz

View File

@@ -18,11 +18,11 @@
set -eu set -eu
KIND_VERSION=0.22.0 KIND_VERSION=0.17.0
KUBECTL_VERSION=1.29.0 KUBECTL_VERSION=1.24.0
KUSTOMIZE_VERSION=5.3.0 KUSTOMIZE_VERSION=4.5.7
HELM_VERSION=3.14.1 HELM_VERSION=3.10.1
GITHUB_RUNNER_VERSION=2.313.0 GITHUB_RUNNER_VERSION=2.298.2
PACKAGES="apt-transport-https ca-certificates software-properties-common build-essential libssl-dev gnupg lsb-release jq pkg-config" PACKAGES="apt-transport-https ca-certificates software-properties-common build-essential libssl-dev gnupg lsb-release jq pkg-config"
# install prerequisites # install prerequisites

View File

@@ -22,7 +22,7 @@ RUNNER_NAME=$1
REPOSITORY_TOKEN=$2 REPOSITORY_TOKEN=$2
REPOSITORY_URL=${3:-https://github.com/fluxcd/flux2} REPOSITORY_URL=${3:-https://github.com/fluxcd/flux2}
GITHUB_RUNNER_VERSION=2.313.0 GITHUB_RUNNER_VERSION=2.298.2
# download runner # download runner
curl -o actions-runner-linux-arm64.tar.gz -L https://github.com/actions/runner/releases/download/v${GITHUB_RUNNER_VERSION}/actions-runner-linux-arm64-${GITHUB_RUNNER_VERSION}.tar.gz \ curl -o actions-runner-linux-arm64.tar.gz -L https://github.com/actions/runner/releases/download/v${GITHUB_RUNNER_VERSION}/actions-runner-linux-arm64-${GITHUB_RUNNER_VERSION}.tar.gz \

View File

@@ -24,6 +24,6 @@ jobs:
name: action on ${{ matrix.version }} name: action on ${{ matrix.version }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup flux - name: Setup flux
uses: ./action uses: ./action

View File

@@ -13,11 +13,11 @@ jobs:
if: github.event.pull_request.state == 'closed' && github.event.pull_request.merged && (github.event_name != 'labeled' || startsWith('backport:', github.event.label.name)) if: github.event.pull_request.state == 'closed' && github.event.pull_request.merged && (github.event_name != 'labeled' || startsWith('backport:', github.event.label.name))
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
- name: Create backport PRs - name: Create backport PRs
uses: korthout/backport-action@ef20d86abccbac3ee3a73cb2efbdc06344c390e5 # v2.5.0 uses: korthout/backport-action@b982d297e31f500652b2246cf26714796312bd23 # v2.2.0
# xref: https://github.com/korthout/backport-action#inputs # xref: https://github.com/korthout/backport-action#inputs
with: with:
# Use token to allow workflows to be triggered for the created PR # Use token to allow workflows to be triggered for the created PR

View File

@@ -1,267 +0,0 @@
name: conformance
on:
workflow_dispatch:
push:
branches: [ 'main', 'update-components', 'release/**', 'conform*' ]
permissions:
contents: read
env:
GO_VERSION: 1.22.x
jobs:
conform-kubernetes:
# Hosted on Equinix
# Docs: https://github.com/fluxcd/flux2/tree/main/.github/runners
runs-on: [self-hosted, Linux, ARM64, equinix]
strategy:
matrix:
# Keep this list up-to-date with https://endoflife.date/kubernetes
# Build images with https://github.com/fluxcd/flux-benchmark/actions/workflows/build-kind.yaml
KUBERNETES_VERSION: [ 1.28.9, 1.29.4, 1.30.0 ]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Prepare
id: prep
run: |
ID=${GITHUB_SHA:0:7}-${{ matrix.KUBERNETES_VERSION }}-$(date +%s)
echo "CLUSTER=arm64-${ID}" >> $GITHUB_OUTPUT
- name: Build
run: |
make build
- name: Setup Kubernetes Kind
run: |
kind create cluster \
--wait 5m \
--name ${{ steps.prep.outputs.CLUSTER }} \
--kubeconfig=/tmp/${{ steps.prep.outputs.CLUSTER }} \
--image=ghcr.io/fluxcd/kindest/node:v${{ matrix.KUBERNETES_VERSION }}-arm64
- name: Run e2e tests
run: TEST_KUBECONFIG=/tmp/${{ steps.prep.outputs.CLUSTER }} make e2e
- name: Run multi-tenancy tests
env:
KUBECONFIG: /tmp/${{ steps.prep.outputs.CLUSTER }}
run: |
./bin/flux install
./bin/flux create source git flux-system \
--interval=15m \
--url=https://github.com/fluxcd/flux2-multi-tenancy \
--branch=main \
--ignore-paths="./clusters/**/flux-system/"
./bin/flux create kustomization flux-system \
--interval=15m \
--source=flux-system \
--path=./clusters/staging
kubectl -n flux-system wait kustomization/tenants --for=condition=ready --timeout=5m
kubectl -n apps wait kustomization/dev-team --for=condition=ready --timeout=1m
kubectl -n apps wait helmrelease/podinfo --for=condition=ready --timeout=1m
- name: Debug failure
if: failure()
env:
KUBECONFIG: /tmp/${{ steps.prep.outputs.CLUSTER }}
run: |
kubectl -n flux-system get all
kubectl -n flux-system describe po
kubectl -n flux-system logs deploy/source-controller
kubectl -n flux-system logs deploy/kustomize-controller
- name: Cleanup
if: always()
run: |
kind delete cluster --name ${{ steps.prep.outputs.CLUSTER }}
rm /tmp/${{ steps.prep.outputs.CLUSTER }}
conform-k3s:
runs-on: ubuntu-latest
strategy:
matrix:
# Keep this list up-to-date with https://endoflife.date/kubernetes
# Available versions can be found with "replicated cluster versions"
K3S_VERSION: [ 1.28.7, 1.29.2 ]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Prepare
id: prep
run: |
ID=${GITHUB_SHA:0:7}-${{ matrix.K3S_VERSION }}-$(date +%s)
PSEUDO_RAND_SUFFIX=$(echo "${ID}" | shasum | awk '{print $1}')
echo "cluster=flux2-k3s-${PSEUDO_RAND_SUFFIX}" >> $GITHUB_OUTPUT
KUBECONFIG_PATH="$(git rev-parse --show-toplevel)/bin/kubeconfig.yaml"
echo "kubeconfig-path=${KUBECONFIG_PATH}" >> $GITHUB_OUTPUT
- name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main
- name: Build
run: make build-dev
- name: Create repository
run: |
gh repo create --private --add-readme fluxcd-testing/${{ steps.prep.outputs.cluster }}
env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: Create cluster
id: create-cluster
uses: replicatedhq/compatibility-actions/create-cluster@v1
with:
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
kubernetes-distribution: "k3s"
kubernetes-version: ${{ matrix.K3S_VERSION }}
ttl: 20m
cluster-name: "${{ steps.prep.outputs.cluster }}"
kubeconfig-path: ${{ steps.prep.outputs.kubeconfig-path }}
export-kubeconfig: true
- name: Run e2e tests
run: TEST_KUBECONFIG=${{ steps.prep.outputs.kubeconfig-path }} make e2e
- name: Run flux bootstrap
run: |
./bin/flux bootstrap git --manifests ./manifests/install/ \
--components-extra=image-reflector-controller,image-automation-controller \
--url=https://github.com/fluxcd-testing/${{ steps.prep.outputs.cluster }} \
--branch=main \
--path=clusters/k3s \
--token-auth
env:
GIT_PASSWORD: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: Run flux check
run: |
./bin/flux check
- name: Run flux reconcile
run: |
./bin/flux reconcile ks flux-system --with-source
./bin/flux get all
./bin/flux events
- name: Collect reconcile logs
if: ${{ always() }}
continue-on-error: true
run: |
kubectl -n flux-system get all
kubectl -n flux-system describe pods
kubectl -n flux-system logs deploy/source-controller
kubectl -n flux-system logs deploy/kustomize-controller
kubectl -n flux-system logs deploy/notification-controller
- name: Delete flux
run: |
./bin/flux uninstall -s --keep-namespace
kubectl delete ns flux-system --wait
- name: Delete cluster
if: ${{ always() }}
uses: replicatedhq/replicated-actions/remove-cluster@v1
continue-on-error: true
with:
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
- name: Delete repository
if: ${{ always() }}
continue-on-error: true
run: |
gh repo delete fluxcd-testing/${{ steps.prep.outputs.cluster }} --yes
env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
conform-openshift:
runs-on: ubuntu-latest
strategy:
matrix:
# Keep this list up-to-date with https://endoflife.date/red-hat-openshift
OPENSHIFT_VERSION: [ 4.15.0-okd ]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5
- name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1
with:
go-version: ${{ env.GO_VERSION }}
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Prepare
id: prep
run: |
ID=${GITHUB_SHA:0:7}-${{ matrix.OPENSHIFT_VERSION }}-$(date +%s)
PSEUDO_RAND_SUFFIX=$(echo "${ID}" | shasum | awk '{print $1}')
echo "cluster=flux2-openshift-${PSEUDO_RAND_SUFFIX}" >> $GITHUB_OUTPUT
KUBECONFIG_PATH="$(git rev-parse --show-toplevel)/bin/kubeconfig.yaml"
echo "kubeconfig-path=${KUBECONFIG_PATH}" >> $GITHUB_OUTPUT
- name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main
- name: Build
run: make build-dev
- name: Create repository
run: |
gh repo create --private --add-readme fluxcd-testing/${{ steps.prep.outputs.cluster }}
env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: Create cluster
id: create-cluster
uses: replicatedhq/compatibility-actions/create-cluster@v1
with:
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
kubernetes-distribution: "openshift"
kubernetes-version: ${{ matrix.OPENSHIFT_VERSION }}
ttl: 20m
cluster-name: "${{ steps.prep.outputs.cluster }}"
kubeconfig-path: ${{ steps.prep.outputs.kubeconfig-path }}
export-kubeconfig: true
- name: Run flux bootstrap
run: |
./bin/flux bootstrap git --manifests ./manifests/openshift/ \
--components-extra=image-reflector-controller,image-automation-controller \
--url=https://github.com/fluxcd-testing/${{ steps.prep.outputs.cluster }} \
--branch=main \
--path=clusters/openshift \
--token-auth
env:
GIT_PASSWORD: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: Run flux check
run: |
./bin/flux check
- name: Run flux reconcile
run: |
./bin/flux reconcile ks flux-system --with-source
./bin/flux get all
./bin/flux events
- name: Collect reconcile logs
if: ${{ always() }}
continue-on-error: true
run: |
kubectl -n flux-system get all
kubectl -n flux-system describe pods
kubectl -n flux-system logs deploy/source-controller
kubectl -n flux-system logs deploy/kustomize-controller
kubectl -n flux-system logs deploy/notification-controller
- name: Delete flux
run: |
./bin/flux uninstall -s --keep-namespace
kubectl delete ns flux-system --wait
- name: Delete cluster
if: ${{ always() }}
uses: replicatedhq/replicated-actions/remove-cluster@v1
continue-on-error: true
with:
api-token: ${{ secrets.REPLICATED_API_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
- name: Delete repository
if: ${{ always() }}
continue-on-error: true
run: |
gh repo delete fluxcd-testing/${{ steps.prep.outputs.cluster }} --yes
env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}

106
.github/workflows/e2e-arm64.yaml vendored Normal file
View File

@@ -0,0 +1,106 @@
name: e2e-arm64
on:
workflow_dispatch:
push:
branches: [ 'main', 'update-components', 'e2e-*', 'release/**' ]
permissions:
contents: read
jobs:
e2e-arm64-kubernetes:
# Hosted on Equinix
# Docs: https://github.com/fluxcd/flux2/tree/main/.github/runners
runs-on: [self-hosted, Linux, ARM64, equinix]
strategy:
matrix:
# Keep this list up-to-date with https://endoflife.date/kubernetes
# Check which versions are available on DockerHub with 'crane ls kindest/node'
KUBERNETES_VERSION: [ 1.25.11, 1.26.6, 1.27.3, 1.28.0 ]
fail-fast: false
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: 1.20.x
cache-dependency-path: |
**/go.sum
**/go.mod
- name: Prepare
id: prep
run: |
ID=${GITHUB_SHA:0:7}-${{ matrix.KUBERNETES_VERSION }}-$(date +%s)
echo "CLUSTER=arm64-${ID}" >> $GITHUB_OUTPUT
- name: Build
run: |
make build
- name: Setup Kubernetes Kind
run: |
kind create cluster \
--wait 5m \
--name ${{ steps.prep.outputs.CLUSTER }} \
--kubeconfig=/tmp/${{ steps.prep.outputs.CLUSTER }} \
--image=kindest/node:v${{ matrix.KUBERNETES_VERSION }}
- name: Run e2e tests
run: TEST_KUBECONFIG=/tmp/${{ steps.prep.outputs.CLUSTER }} make e2e
- name: Run multi-tenancy tests
env:
KUBECONFIG: /tmp/${{ steps.prep.outputs.CLUSTER }}
run: |
./bin/flux install
./bin/flux create source git flux-system \
--interval=15m \
--url=https://github.com/fluxcd/flux2-multi-tenancy \
--branch=main \
--ignore-paths="./clusters/**/flux-system/"
./bin/flux create kustomization flux-system \
--interval=15m \
--source=flux-system \
--path=./clusters/staging
kubectl -n flux-system wait kustomization/tenants --for=condition=ready --timeout=5m
kubectl -n apps wait kustomization/dev-team --for=condition=ready --timeout=1m
kubectl -n apps wait helmrelease/podinfo --for=condition=ready --timeout=1m
- name: Run monitoring tests
# Keep this test in sync with https://fluxcd.io/flux/guides/monitoring/
env:
KUBECONFIG: /tmp/${{ steps.prep.outputs.CLUSTER }}
run: |
./bin/flux create source git flux-monitoring \
--interval=30m \
--url=https://github.com/fluxcd/flux2 \
--branch=${GITHUB_REF#refs/heads/}
./bin/flux create kustomization kube-prometheus-stack \
--interval=1h \
--prune \
--source=flux-monitoring \
--path="./manifests/monitoring/kube-prometheus-stack" \
--health-check-timeout=5m \
--wait
./bin/flux create kustomization monitoring-config \
--depends-on=kube-prometheus-stack \
--interval=1h \
--prune=true \
--source=flux-monitoring \
--path="./manifests/monitoring/monitoring-config" \
--health-check-timeout=1m \
--wait
kubectl -n flux-system wait kustomization/kube-prometheus-stack --for=condition=ready --timeout=5m
kubectl -n flux-system wait kustomization/monitoring-config --for=condition=ready --timeout=5m
kubectl -n monitoring wait helmrelease/kube-prometheus-stack --for=condition=ready --timeout=1m
- name: Debug failure
if: failure()
env:
KUBECONFIG: /tmp/${{ steps.prep.outputs.CLUSTER }}
run: |
kubectl -n flux-system get all
kubectl -n flux-system describe po
kubectl -n flux-system logs deploy/source-controller
kubectl -n flux-system logs deploy/kustomize-controller
- name: Cleanup
if: always()
run: |
kind delete cluster --name ${{ steps.prep.outputs.CLUSTER }}
rm /tmp/${{ steps.prep.outputs.CLUSTER }}

View File

@@ -21,7 +21,52 @@ permissions:
contents: read contents: read
jobs: jobs:
e2e-aks: e2e-amd64-aks:
runs-on: ubuntu-22.04
defaults:
run:
working-directory: ./tests/azure
# This job is currently disabled. Remove the false check when Azure subscription is enabled.
if: false && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go
uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with:
go-version: 1.20.x
cache-dependency-path: tests/azure/go.sum
- name: Setup Flux CLI
run: |
make build
mkdir -p $HOME/.local/bin
mv ./bin/flux $HOME/.local/bin
working-directory: ./
- name: Setup SOPS
run: |
mkdir -p $HOME/.local/bin
wget https://github.com/mozilla/sops/releases/download/v3.7.1/sops-v3.7.1.linux -O $HOME/.local/bin/sops
chmod +x $HOME/.local/bin/sops
- name: Setup Terraform
uses: hashicorp/setup-terraform@a1502cd9e758c50496cc9ac5308c4843bcd56d36 # v2
with:
terraform_version: 1.2.8
terraform_wrapper: false
- name: Setup Azure CLI
run: |
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
- name: Run Azure e2e tests
env:
ARM_CLIENT_ID: ${{ secrets.ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.ARM_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.ARM_TENANT_ID }}
run: |
ls $HOME/.local/bin
az login --service-principal -u ${ARM_CLIENT_ID} -p ${ARM_CLIENT_SECRET} -t ${ARM_TENANT_ID}
go test -v -coverprofile cover.out -timeout 60m .
refactored-e2e-amd64-aks:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
defaults: defaults:
run: run:
@@ -30,11 +75,11 @@ jobs:
if: false && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]' if: false && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
steps: steps:
- name: CheckoutD - name: CheckoutD
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go - name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with: with:
go-version: 1.22.x go-version: 1.20.x
cache-dependency-path: tests/integration/go.sum cache-dependency-path: tests/integration/go.sum
- name: Setup Flux CLI - name: Setup Flux CLI
run: make build run: make build
@@ -47,7 +92,7 @@ jobs:
env: env:
SOPS_VER: 3.7.1 SOPS_VER: 3.7.1
- name: Authenticate to Azure - name: Authenticate to Azure
uses: Azure/login@6b2456866fc08b011acb422a92a4aa20e2c4de32 # v1.4.6 uses: Azure/login@de95379fe4dadc2defb305917eaa7e5dde727294 # v1.4.6
with: with:
creds: '{"clientId":"${{ secrets.AZ_ARM_CLIENT_ID }}","clientSecret":"${{ secrets.AZ_ARM_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZ_ARM_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZ_ARM_TENANT_ID }}"}' creds: '{"clientId":"${{ secrets.AZ_ARM_CLIENT_ID }}","clientSecret":"${{ secrets.AZ_ARM_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZ_ARM_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZ_ARM_TENANT_ID }}"}'
- name: Set dynamic variables in .env - name: Set dynamic variables in .env
@@ -78,14 +123,3 @@ jobs:
echo $GITREPO_SSH_PUB_CONTENTS | base64 -d > ./build/ssh/key.pub echo $GITREPO_SSH_PUB_CONTENTS | base64 -d > ./build/ssh/key.pub
export GITREPO_SSH_PUB_PATH=build/ssh/key.pub export GITREPO_SSH_PUB_PATH=build/ssh/key.pub
make test-azure make test-azure
- name: Ensure resource cleanup
if: ${{ always() }}
env:
ARM_CLIENT_ID: ${{ secrets.AZ_ARM_CLIENT_ID }}
ARM_CLIENT_SECRET: ${{ secrets.AZ_ARM_CLIENT_SECRET }}
ARM_SUBSCRIPTION_ID: ${{ secrets.AZ_ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.AZ_ARM_TENANT_ID }}
TF_VAR_azuredevops_org: ${{ secrets.TF_VAR_azuredevops_org }}
TF_VAR_azuredevops_pat: ${{ secrets.TF_VAR_azuredevops_pat }}
TF_VAR_location: ${{ vars.TF_VAR_azure_location }}
run: source .env && make destroy-azure

View File

@@ -17,29 +17,29 @@ jobs:
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]' if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go - name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with: with:
go-version: 1.22.x go-version: 1.20.x
cache-dependency-path: | cache-dependency-path: |
**/go.sum **/go.sum
**/go.mod **/go.mod
- name: Setup Kubernetes - name: Setup Kubernetes
uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0 uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0
with: with:
version: v0.22.0 version: v0.20.0
cluster_name: kind cluster_name: kind
# The versions below should target the newest Kubernetes version # The versions below should target the newest Kubernetes version
# Keep this up-to-date with https://endoflife.date/kubernetes # Keep this up-to-date with https://endoflife.date/kubernetes
node_image: ghcr.io/fluxcd/kindest/node:v1.30.0-amd64 node_image: kindest/node:v1.28.0@sha256:9f3ff58f19dcf1a0611d11e8ac989fdb30a28f40f236f59f0bea31fb956ccf5c
kubectl_version: v1.30.0 kubectl_version: v1.28.0
- name: Setup Kustomize - name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main uses: fluxcd/pkg/actions/kustomize@main
- name: Setup yq
uses: fluxcd/pkg/actions/yq@main
- name: Build - name: Build
run: make build-dev run: |
make cmd/flux/.manifests.done
go build -o /tmp/flux ./cmd/flux
- name: Set outputs - name: Set outputs
id: vars id: vars
run: | run: |
@@ -51,24 +51,18 @@ jobs:
echo "test_repo_name=$TEST_REPO_NAME" >> $GITHUB_OUTPUT echo "test_repo_name=$TEST_REPO_NAME" >> $GITHUB_OUTPUT
- 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 \
--image-pull-secret=ghcr-auth \
--registry-creds=fluxcd:$GITHUB_TOKEN \
--repository=${{ steps.vars.outputs.test_repo_name }} \ --repository=${{ steps.vars.outputs.test_repo_name }} \
--branch=main \ --branch=main \
--path=test-cluster \ --path=test-cluster \
--team=team-z --team=team-z
env: env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: verify image pull secret
run: |
kubectl -n flux-system get secret ghcr-auth | grep dockerconfigjson
- 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 \
--image-pull-secret=ghcr-auth \
--repository=${{ steps.vars.outputs.test_repo_name }} \ --repository=${{ steps.vars.outputs.test_repo_name }} \
--branch=main \ --branch=main \
--path=test-cluster \ --path=test-cluster \
@@ -78,7 +72,7 @@ jobs:
- name: bootstrap customize - name: bootstrap customize
run: | run: |
make setup-bootstrap-patch make setup-bootstrap-patch
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=${{ steps.vars.outputs.test_repo_name }} \ --repository=${{ steps.vars.outputs.test_repo_name }} \
--branch=main \ --branch=main \
@@ -93,31 +87,46 @@ jobs:
GITHUB_ORG_NAME: fluxcd-testing GITHUB_ORG_NAME: fluxcd-testing
- 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: test image automation - name: test image automation
run: | run: |
make setup-image-automation make setup-image-automation
./bin/flux bootstrap github --manifests ./manifests/install/ \ /tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \ --owner=fluxcd-testing \
--repository=${{ steps.vars.outputs.test_repo_name }} \ --repository=${{ steps.vars.outputs.test_repo_name }} \
--branch=main \ --branch=main \
--path=test-cluster \ --path=test-cluster \
--read-write-key --read-write-key
./bin/flux reconcile image repository podinfo /tmp/flux reconcile image repository podinfo
./bin/flux reconcile image update flux-system /tmp/flux get images all
./bin/flux get images all
kubectl -n flux-system get -o yaml ImageUpdateAutomation flux-system | \ retries=10
yq '.status.lastPushCommit | length > 1' | grep 'true' count=0
ok=false
until ${ok}; do
/tmp/flux get image update flux-system | grep 'commit' && ok=true || ok=false
count=$(($count + 1))
if [[ ${count} -eq ${retries} ]]; then
echo "No more retries left"
exit 1
fi
sleep 6
/tmp/flux reconcile image update flux-system
done
env: env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
GITHUB_REPO_NAME: ${{ steps.vars.outputs.test_repo_name }} GITHUB_REPO_NAME: ${{ steps.vars.outputs.test_repo_name }}
GITHUB_ORG_NAME: fluxcd-testing GITHUB_ORG_NAME: fluxcd-testing
- name: delete repository - name: delete repository
if: ${{ always() }} if: ${{ always() }}
continue-on-error: true
run: | run: |
gh repo delete fluxcd-testing/${{ steps.vars.outputs.test_repo_name }} --yes curl \
-X DELETE \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${GITHUB_TOKEN}" \
--fail --silent \
https://api.github.com/repos/fluxcd-testing/${{ steps.vars.outputs.test_repo_name }}
env: env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: Debug failure - name: Debug failure

View File

@@ -29,11 +29,11 @@ jobs:
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]' if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go - name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with: with:
go-version: 1.22.x go-version: 1.20.x
cache-dependency-path: tests/integration/go.sum cache-dependency-path: tests/integration/go.sum
- name: Setup Flux CLI - name: Setup Flux CLI
run: make build run: make build
@@ -46,19 +46,19 @@ jobs:
env: env:
SOPS_VER: 3.7.1 SOPS_VER: 3.7.1
- name: Authenticate to Google Cloud - name: Authenticate to Google Cloud
uses: google-github-actions/auth@55bd3a7c6e2ae7cf1877fd1ccb9d54c0503c457c # v2.1.2 uses: google-github-actions/auth@67e9c72af6e0492df856527b474995862b7b6591 # v2.0.0
id: 'auth' id: 'auth'
with: with:
credentials_json: '${{ secrets.FLUX2_E2E_GOOGLE_CREDENTIALS }}' credentials_json: '${{ secrets.FLUX2_E2E_GOOGLE_CREDENTIALS }}'
token_format: 'access_token' token_format: 'access_token'
- name: Setup gcloud - name: Setup gcloud
uses: google-github-actions/setup-gcloud@98ddc00a17442e89a24bbf282954a3b65ce6d200 # v2.1.0 uses: google-github-actions/setup-gcloud@825196879a077b7efa50db2e88409f44de4635c2 # v2.0.0
- name: Setup QEMU - name: Setup QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
- name: Setup Docker Buildx - name: Setup Docker Buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Log into us-central1-docker.pkg.dev - name: Log into us-central1-docker.pkg.dev
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with: with:
registry: us-central1-docker.pkg.dev registry: us-central1-docker.pkg.dev
username: oauth2accesstoken username: oauth2accesstoken
@@ -90,13 +90,3 @@ jobs:
echo $GITREPO_SSH_PUB_CONTENTS | base64 -d > ./build/ssh/key.pub echo $GITREPO_SSH_PUB_CONTENTS | base64 -d > ./build/ssh/key.pub
export GITREPO_SSH_PUB_PATH=build/ssh/key.pub export GITREPO_SSH_PUB_PATH=build/ssh/key.pub
make test-gcp make test-gcp
- name: Ensure resource cleanup
if: ${{ always() }}
env:
TF_VAR_gcp_project_id: ${{ vars.TF_VAR_gcp_project_id }}
TF_VAR_gcp_region: ${{ vars.TF_VAR_gcp_region }}
TF_VAR_gcp_zone: ${{ vars.TF_VAR_gcp_zone }}
TF_VAR_gcp_email: ${{ secrets.TF_VAR_gcp_email }}
TF_VAR_gcp_keyring: ${{ secrets.TF_VAR_gcp_keyring }}
TF_VAR_gcp_crypto_key: ${{ secrets.TF_VAR_gcp_crypto_key }}
run: source .env && make destroy-gcp

View File

@@ -13,9 +13,7 @@ permissions:
jobs: jobs:
e2e-amd64-kubernetes: e2e-amd64-kubernetes:
runs-on: runs-on: ubuntu-latest
group: "Default Larger Runners"
labels: ubuntu-latest-16-cores
services: services:
registry: registry:
image: registry:2 image: registry:2
@@ -23,28 +21,28 @@ jobs:
- 5000:5000 - 5000:5000
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go - name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with: with:
go-version: 1.22.x go-version: 1.20.x
cache-dependency-path: | cache-dependency-path: |
**/go.sum **/go.sum
**/go.mod **/go.mod
- name: Setup Kubernetes - name: Setup Kubernetes
uses: helm/kind-action@0025e74a8c7512023d06dc019c617aa3cf561fde # v1.10.0 uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0
with: with:
version: v0.22.0 version: v0.20.0
cluster_name: kind cluster_name: kind
wait: 5s
config: .github/kind/config.yaml # disable KIND-net config: .github/kind/config.yaml # disable KIND-net
# The versions below should target the oldest supported Kubernetes version # The versions below should target the newest Kubernetes version
# Keep this up-to-date with https://endoflife.date/kubernetes # Keep this up-to-date with https://endoflife.date/kubernetes
node_image: ghcr.io/fluxcd/kindest/node:v1.28.9-amd64 node_image: kindest/node:v1.28.0@sha256:9f3ff58f19dcf1a0611d11e8ac989fdb30a28f40f236f59f0bea31fb956ccf5c
kubectl_version: v1.28.9 kubectl_version: v1.28.0
- name: Setup Calico for network policy - name: Setup Calico for network policy
run: | run: |
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.27.3/manifests/calico.yaml kubectl apply -f https://docs.projectcalico.org/v3.25/manifests/calico.yaml
kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true
- name: Setup Kustomize - name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main uses: fluxcd/pkg/actions/kustomize@main
- name: Run tests - name: Run tests
@@ -59,43 +57,44 @@ jobs:
exit 1 exit 1
fi fi
- name: Build - name: Build
run: make build-dev 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=">=6.3.5" --tag-semver=">=6.3.5"
- 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=">=6.3.5" \ --tag-semver=">=6.3.5" \
--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 \
@@ -105,89 +104,89 @@ jobs:
--health-check-timeout=3m --health-check-timeout=3m
- name: flux trace - name: flux trace
run: | run: |
./bin/flux trace frontend \ /tmp/flux trace frontend \
--kind=deployment \ --kind=deployment \
--api-version=apps/v1 \ --api-version=apps/v1 \
--namespace=dev --namespace=dev
- 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.flux-system \ --source=HelmRepository/podinfo.flux-system \
--chart=podinfo \ --chart=podinfo \
--chart-version=">6.0.0 <7.0.0" --chart-version=">6.0.0 <7.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 oci artifacts - name: flux oci artifacts
run: | run: |
./bin/flux push artifact oci://localhost:5000/fluxcd/flux:${{ github.sha }} \ /tmp/flux push artifact oci://localhost:5000/fluxcd/flux:${{ github.sha }} \
--path="./manifests" \ --path="./manifests" \
--source="${{ github.repositoryUrl }}" \ --source="${{ github.repositoryUrl }}" \
--revision="${{ github.ref }}@sha1:${{ github.sha }}" --revision="${{ github.ref }}@sha1:${{ github.sha }}"
./bin/flux tag artifact oci://localhost:5000/fluxcd/flux:${{ github.sha }} \ /tmp/flux tag artifact oci://localhost:5000/fluxcd/flux:${{ github.sha }} \
--tag latest --tag latest
./bin/flux list artifacts oci://localhost:5000/fluxcd/flux /tmp/flux list artifacts oci://localhost:5000/fluxcd/flux
- name: flux oci repositories - name: flux oci repositories
run: | run: |
./bin/flux create source oci podinfo-oci \ /tmp/flux create source oci podinfo-oci \
--url oci://ghcr.io/stefanprodan/manifests/podinfo \ --url oci://ghcr.io/stefanprodan/manifests/podinfo \
--tag-semver 6.3.x \ --tag-semver 6.3.x \
--interval 10m --interval 10m
./bin/flux create kustomization podinfo-oci \ /tmp/flux create kustomization podinfo-oci \
--source=OCIRepository/podinfo-oci \ --source=OCIRepository/podinfo-oci \
--path="./" \ --path="./" \
--prune=true \ --prune=true \
@@ -195,31 +194,31 @@ jobs:
--target-namespace=default \ --target-namespace=default \
--wait=true \ --wait=true \
--health-check-timeout=3m --health-check-timeout=3m
./bin/flux reconcile source oci podinfo-oci /tmp/flux reconcile source oci podinfo-oci
./bin/flux suspend source oci podinfo-oci /tmp/flux suspend source oci podinfo-oci
./bin/flux get sources oci /tmp/flux get sources oci
./bin/flux resume source oci podinfo-oci /tmp/flux resume source oci podinfo-oci
./bin/flux export source oci podinfo-oci /tmp/flux export source oci podinfo-oci
./bin/flux delete ks podinfo-oci --silent /tmp/flux delete ks podinfo-oci --silent
./bin/flux delete source oci podinfo-oci --silent /tmp/flux delete source oci podinfo-oci --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="6.3.x" \ --chart-version="6.3.x" \
--service-account=dev-team --service-account=dev-team
- 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 \
--ignore-paths="./clusters/**/flux-system/" \ --ignore-paths="./clusters/**/flux-system/" \
--recurse-submodules --recurse-submodules
./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/infra-controllers --for=condition=ready --timeout=5m kubectl -n flux-system wait kustomization/infra-controllers --for=condition=ready --timeout=5m
@@ -227,23 +226,13 @@ jobs:
kubectl -n podinfo wait helmrelease/podinfo --for=condition=ready --timeout=5m kubectl -n podinfo wait helmrelease/podinfo --for=condition=ready --timeout=5m
- name: flux tree - name: flux tree
run: | run: |
./bin/flux tree kustomization flux-system | grep Service/podinfo /tmp/flux tree kustomization flux-system | grep Service/podinfo
- name: flux events
run: |
./bin/flux -n flux-system events --for Kustomization/apps | grep 'HelmRelease/podinfo'
./bin/flux -n podinfo events --for HelmRelease/podinfo | grep 'podinfo.v1'
- name: flux stats
run: |
./bin/flux stats -A
- name: flux check - name: flux check
run: | run: |
./bin/flux check /tmp/flux check
- name: flux version
run: |
./bin/flux version
- 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: |

View File

@@ -19,16 +19,16 @@ jobs:
actions: read actions: read
contents: read contents: read
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run analysis - name: Run analysis
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3 uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
with: with:
results_file: results.sarif results_file: results.sarif
results_format: sarif results_format: sarif
repo_token: ${{ secrets.GITHUB_TOKEN }} repo_token: ${{ secrets.GITHUB_TOKEN }}
publish_results: true publish_results: true
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@65462800fd760344b1a7b4382951275a0abb4808 # v4.3.3 uses: actions/upload-artifact@a8a3f3ad30e3422c9c7b888a15615d19a852ae32 # v3.1.3
with: with:
name: SARIF file name: SARIF file
path: results.sarif path: results.sarif

View File

@@ -20,33 +20,33 @@ jobs:
packages: write # needed for ghcr access packages: write # needed for ghcr access
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Unshallow - name: Unshallow
run: git fetch --prune --unshallow run: git fetch --prune --unshallow
- name: Setup Go - name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with: with:
go-version: 1.22.x go-version: 1.20.x
cache: false cache: false
- name: Setup QEMU - name: Setup QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0 uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3.0.0
- name: Setup Docker Buildx - name: Setup Docker Buildx
id: buildx id: buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3.3.0 uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3.0.0
- name: Setup Syft - name: Setup Syft
uses: anchore/sbom-action/download-syft@7ccf588e3cf3cc2611714c2eeae48550fbc17552 # v0.15.11 uses: anchore/sbom-action/download-syft@5ecf649a417b8ae17dc8383dc32d46c03f2312df # v0.15.1
- name: Setup Cosign - name: Setup Cosign
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 uses: sigstore/cosign-installer@1fc5bd396d372bee37d608f955b336615edf79c8 # v3.2.0
- name: Setup Kustomize - name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main uses: fluxcd/pkg/actions/kustomize@main
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with: with:
registry: ghcr.io registry: ghcr.io
username: fluxcdbot username: fluxcdbot
password: ${{ secrets.GHCR_TOKEN }} password: ${{ secrets.GHCR_TOKEN }}
- name: Login to Docker Hub - name: Login to Docker Hub
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with: with:
username: fluxcdbot username: fluxcdbot
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }} password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
@@ -79,7 +79,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Run GoReleaser - name: Run GoReleaser
id: run-goreleaser id: run-goreleaser
uses: goreleaser/goreleaser-action@5742e2a039330cbb23ebf35f046f814d4c6ff811 # v5.1.0 uses: goreleaser/goreleaser-action@7ec5c2b0c6cdda6e8bbb49444bc797dd33d74dd8 # v5.0.0
with: with:
version: latest version: latest
args: release --release-notes=output/notes.md --skip-validate args: release --release-notes=output/notes.md --skip-validate
@@ -110,7 +110,7 @@ jobs:
id-token: write id-token: write
packages: write packages: write
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Kustomize - name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main uses: fluxcd/pkg/actions/kustomize@main
- name: Setup Flux CLI - name: Setup Flux CLI
@@ -121,13 +121,13 @@ jobs:
VERSION=$(flux version --client | awk '{ print $NF }') VERSION=$(flux version --client | awk '{ print $NF }')
echo "version=${VERSION}" >> $GITHUB_OUTPUT echo "version=${VERSION}" >> $GITHUB_OUTPUT
- name: Login to GHCR - name: Login to GHCR
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with: with:
registry: ghcr.io registry: ghcr.io
username: fluxcdbot username: fluxcdbot
password: ${{ secrets.GHCR_TOKEN }} password: ${{ secrets.GHCR_TOKEN }}
- name: Login to DockerHub - name: Login to DockerHub
uses: docker/login-action@e92390c5fb421da1463c202d546fed0ec5c39f20 # v3.1.0 uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3.0.0
with: with:
username: fluxcdbot username: fluxcdbot
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }} password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
@@ -155,7 +155,7 @@ jobs:
--path="./flux-system" \ --path="./flux-system" \
--source=${{ github.repositoryUrl }} \ --source=${{ github.repositoryUrl }} \
--revision="${{ github.ref_name }}@sha1:${{ github.sha }}" --revision="${{ github.ref_name }}@sha1:${{ github.sha }}"
- uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 - uses: sigstore/cosign-installer@1fc5bd396d372bee37d608f955b336615edf79c8 # v3.2.0
- name: Sign manifests - name: Sign manifests
env: env:
COSIGN_EXPERIMENTAL: 1 COSIGN_EXPERIMENTAL: 1
@@ -176,7 +176,7 @@ jobs:
actions: read # for detecting the Github Actions environment. actions: read # for detecting the Github Actions environment.
id-token: write # for creating OIDC tokens for signing. id-token: write # for creating OIDC tokens for signing.
contents: write # for uploading attestations to GitHub releases. contents: write # for uploading attestations to GitHub releases.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0 uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
with: with:
provenance-name: "provenance.intoto.jsonl" provenance-name: "provenance.intoto.jsonl"
base64-subjects: "${{ needs.release-flux-cli.outputs.hashes }}" base64-subjects: "${{ needs.release-flux-cli.outputs.hashes }}"
@@ -188,7 +188,7 @@ jobs:
actions: read # for detecting the Github Actions environment. actions: read # for detecting the Github Actions environment.
id-token: write # for creating OIDC tokens for signing. id-token: write # for creating OIDC tokens for signing.
packages: write # for uploading attestations. packages: write # for uploading attestations.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0 uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
with: with:
image: ${{ needs.release-flux-cli.outputs.image_url }} image: ${{ needs.release-flux-cli.outputs.image_url }}
digest: ${{ needs.release-flux-cli.outputs.image_digest }} digest: ${{ needs.release-flux-cli.outputs.image_digest }}
@@ -202,7 +202,7 @@ jobs:
actions: read # for detecting the Github Actions environment. actions: read # for detecting the Github Actions environment.
id-token: write # for creating OIDC tokens for signing. id-token: write # for creating OIDC tokens for signing.
packages: write # for uploading attestations. packages: write # for uploading attestations.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.0.0 uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
with: with:
image: ghcr.io/${{ needs.release-flux-cli.outputs.image_url }} image: ghcr.io/${{ needs.release-flux-cli.outputs.image_url }}
digest: ${{ needs.release-flux-cli.outputs.image_digest }} digest: ${{ needs.release-flux-cli.outputs.image_digest }}

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.actor != 'dependabot[bot]' if: github.actor != 'dependabot[bot]'
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Run FOSSA scan and upload build data - name: Run FOSSA scan and upload build data
uses: fossa-contrib/fossa-action@cdc5065bcdee31a32e47d4585df72d66e8e941c2 # v3.0.0 uses: fossa-contrib/fossa-action@cdc5065bcdee31a32e47d4585df72d66e8e941c2 # v3.0.0
with: with:
@@ -31,13 +31,13 @@ jobs:
security-events: write security-events: write
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]' if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Kustomize - name: Setup Kustomize
uses: fluxcd/pkg/actions/kustomize@main uses: fluxcd/pkg/actions/kustomize@main
- name: Setup Go - name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with: with:
go-version-file: 'go.mod' go-version: 1.20.x
cache-dependency-path: | cache-dependency-path: |
**/go.sum **/go.sum
**/go.mod **/go.mod
@@ -49,11 +49,10 @@ jobs:
- name: Run Snyk to check for vulnerabilities - name: Run Snyk to check for vulnerabilities
continue-on-error: true continue-on-error: true
run: | run: |
snyk test --all-projects --sarif-file-output=snyk.sarif snyk test --sarif-file-output=snyk.sarif
env: env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }} SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
- name: Upload result to GitHub Code Scanning - name: Upload result to GitHub Code Scanning
continue-on-error: true
uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
with: with:
sarif_file: snyk.sarif sarif_file: snyk.sarif
@@ -65,11 +64,11 @@ jobs:
if: github.actor != 'dependabot[bot]' if: github.actor != 'dependabot[bot]'
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go - name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with: with:
go-version-file: 'go.mod' go-version: 1.20.x
cache-dependency-path: | cache-dependency-path: |
**/go.sum **/go.sum
**/go.mod **/go.mod

View File

@@ -17,8 +17,8 @@ jobs:
permissions: permissions:
issues: write issues: write
steps: steps:
- uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: EndBug/label-sync@52074158190acb45f3077f9099fea818aa43f97a # v2.3.3 - uses: EndBug/label-sync@da00f2c11fdb78e4fae44adac2fdd713778ea3e8 # v2.3.2
with: with:
# Configuration file # Configuration file
config-file: | config-file: |

View File

@@ -18,11 +18,11 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Check out code - name: Check out code
uses: actions/checkout@44c2b7a8a4ea60a981eaca3cf939b5f4305c123b # v4.1.5 uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Setup Go - name: Setup Go
uses: actions/setup-go@cdcb36043654635271a94b9a6d1392de5bb323a7 # v5.0.1 uses: actions/setup-go@0c52d547c9bc32b1aa3301fd7a9cb496313a4491 # v5.0.0
with: with:
go-version: 1.22.x go-version: 1.20.x
cache-dependency-path: | cache-dependency-path: |
**/go.sum **/go.sum
**/go.mod **/go.mod
@@ -84,7 +84,7 @@ jobs:
- name: Create Pull Request - name: Create Pull Request
id: cpr id: cpr
uses: peter-evans/create-pull-request@6d6857d36972b65feb161a90e484f2984215f83e # v6.0.5 uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5.0.2
with: with:
token: ${{ secrets.BOT_GITHUB_TOKEN }} token: ${{ secrets.BOT_GITHUB_TOKEN }}
commit-message: | commit-message: |

View File

@@ -1,15 +1,15 @@
FROM alpine:3.19 as builder FROM alpine:3.18 as builder
RUN apk add --no-cache ca-certificates curl RUN apk add --no-cache ca-certificates curl
ARG ARCH=linux/amd64 ARG ARCH=linux/amd64
ARG KUBECTL_VER=1.30.0 ARG KUBECTL_VER=1.27.3
RUN curl -sL https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VER}/bin/${ARCH}/kubectl \ RUN curl -sL https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VER}/bin/${ARCH}/kubectl \
-o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl && \ -o /usr/local/bin/kubectl && chmod +x /usr/local/bin/kubectl && \
kubectl version --client=true kubectl version --client=true
FROM alpine:3.19 as flux-cli FROM alpine:3.18 as flux-cli
RUN apk add --no-cache ca-certificates RUN apk add --no-cache ca-certificates

View File

@@ -17,8 +17,9 @@ rwildcard=$(foreach d,$(wildcard $(addsuffix *,$(1))),$(call rwildcard,$(d)/,$(2
all: test build all: test build
tidy: tidy:
go mod tidy -compat=1.22 go mod tidy -compat=1.20
cd tests/integration && go mod tidy -compat=1.22 cd tests/azure && go mod tidy -compat=1.20
cd tests/integration && go mod tidy -compat=1.20
fmt: fmt:
go fmt ./... go fmt ./...

View File

@@ -21,7 +21,7 @@ Flux v2 is constructed with the [GitOps Toolkit](#gitops-toolkit), a
set of composable APIs and specialized tools for building Continuous set of composable APIs and specialized tools for building Continuous
Delivery on top of Kubernetes. Delivery on top of Kubernetes.
Flux is a Cloud Native Computing Foundation ([CNCF](https://www.cncf.io/)) graduated project, used in Flux is a Cloud Native Computing Foundation ([CNCF](https://www.cncf.io/)) project, used in
production by various [organisations](https://fluxcd.io/adopters) and [cloud providers](https://fluxcd.io/ecosystem). production by various [organisations](https://fluxcd.io/adopters) and [cloud providers](https://fluxcd.io/ecosystem).
## Quickstart and documentation ## Quickstart and documentation
@@ -44,7 +44,7 @@ runtime for Flux v2. The APIs comprise Kubernetes custom resources,
which can be created and updated by a cluster user, or by other which can be created and updated by a cluster user, or by other
automation tooling. automation tooling.
![overview](https://raw.githubusercontent.com/fluxcd/flux2/main/docs/diagrams/fluxcd-controllers.png) ![overview](https://fluxcd.io/img/diagrams/gitops-toolkit.png)
You can use the toolkit to extend Flux, or to build your own systems You can use the toolkit to extend Flux, or to build your own systems
for continuous delivery -- see [the developer for continuous delivery -- see [the developer

View File

@@ -22,7 +22,6 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/fluxcd/pkg/git"
"github.com/manifoldco/promptui" "github.com/manifoldco/promptui"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
@@ -54,7 +53,6 @@ type bootstrapFlags struct {
requiredComponents []string requiredComponents []string
registry string registry string
registryCredential string
imagePullSecret string imagePullSecret string
secretName string secretName string
@@ -65,7 +63,6 @@ type bootstrapFlags struct {
sshHostname string sshHostname string
caFile string caFile string
privateKeyFile string privateKeyFile string
sshHostKeyAlgorithms []string
watchAllNamespaces bool watchAllNamespaces bool
networkPolicy bool networkPolicy bool
@@ -101,8 +98,6 @@ func init() {
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.registry, "registry", "ghcr.io/fluxcd", bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.registry, "registry", "ghcr.io/fluxcd",
"container registry where the Flux controller images are published") "container registry where the Flux controller images are published")
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.registryCredential, "registry-creds", "",
"container registry credentials in the format 'user:password', requires --image-pull-secret to be set")
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.imagePullSecret, "image-pull-secret", "", bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.imagePullSecret, "image-pull-secret", "",
"Kubernetes secret name used for pulling the controller images from a private registry") "Kubernetes secret name used for pulling the controller images from a private registry")
@@ -126,7 +121,6 @@ func init() {
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.secretName, "secret-name", rootArgs.defaults.Namespace, "name of the secret the sync credentials can be found in or stored to") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.secretName, "secret-name", rootArgs.defaults.Namespace, "name of the secret the sync credentials can be found in or stored to")
bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.keyAlgorithm, "ssh-key-algorithm", bootstrapArgs.keyAlgorithm.Description()) bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.keyAlgorithm, "ssh-key-algorithm", bootstrapArgs.keyAlgorithm.Description())
bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.keyRSABits, "ssh-rsa-bits", bootstrapArgs.keyRSABits.Description()) bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.keyRSABits, "ssh-rsa-bits", bootstrapArgs.keyRSABits.Description())
bootstrapCmd.PersistentFlags().StringSliceVar(&bootstrapArgs.sshHostKeyAlgorithms, "ssh-hostkey-algos", nil, "list of host key algorithms to be used by the CLI for SSH connections")
bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.keyECDSACurve, "ssh-ecdsa-curve", bootstrapArgs.keyECDSACurve.Description()) bootstrapCmd.PersistentFlags().Var(&bootstrapArgs.keyECDSACurve, "ssh-ecdsa-curve", bootstrapArgs.keyECDSACurve.Description())
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.sshHostname, "ssh-hostname", "", "SSH hostname, to be used when the SSH host differs from the HTTPS one") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.sshHostname, "ssh-hostname", "", "SSH hostname, to be used when the SSH host differs from the HTTPS one")
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates")
@@ -141,7 +135,7 @@ func init() {
bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.commitMessageAppendix, "commit-message-appendix", "", "string to add to the commit messages, e.g. '[ci skip]'") bootstrapCmd.PersistentFlags().StringVar(&bootstrapArgs.commitMessageAppendix, "commit-message-appendix", "", "string to add to the commit messages, e.g. '[ci skip]'")
bootstrapCmd.PersistentFlags().BoolVar(&bootstrapArgs.force, "force", false, "override existing Flux installation if it's managed by a different tool such as Helm") bootstrapCmd.PersistentFlags().BoolVar(&bootstrapArgs.force, "force", false, "override existing Flux installation if it's managed by a diffrent tool such as Helm")
bootstrapCmd.PersistentFlags().MarkHidden("manifests") bootstrapCmd.PersistentFlags().MarkHidden("manifests")
rootCmd.AddCommand(bootstrapCmd) rootCmd.AddCommand(bootstrapCmd)
@@ -187,18 +181,6 @@ func bootstrapValidate() error {
return err return err
} }
if bootstrapArgs.registryCredential != "" && bootstrapArgs.imagePullSecret == "" {
return fmt.Errorf("--registry-creds requires --image-pull-secret to be set")
}
if bootstrapArgs.registryCredential != "" && len(strings.Split(bootstrapArgs.registryCredential, ":")) != 2 {
return fmt.Errorf("invalid --registry-creds format, expected 'user:password'")
}
if len(bootstrapArgs.sshHostKeyAlgorithms) > 0 {
git.HostKeyAlgos = bootstrapArgs.sshHostKeyAlgorithms
}
return nil return nil
} }

View File

@@ -196,7 +196,6 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error {
Namespace: *kubeconfigArgs.Namespace, Namespace: *kubeconfigArgs.Namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
RegistryCredential: bootstrapArgs.registryCredential,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
WatchAllNamespaces: bootstrapArgs.watchAllNamespaces, WatchAllNamespaces: bootstrapArgs.watchAllNamespaces,
NetworkPolicy: bootstrapArgs.networkPolicy, NetworkPolicy: bootstrapArgs.networkPolicy,

View File

@@ -28,9 +28,6 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"github.com/fluxcd/pkg/git"
"github.com/fluxcd/pkg/git/gogit"
"github.com/fluxcd/flux2/v2/internal/flags" "github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/flux2/v2/pkg/bootstrap" "github.com/fluxcd/flux2/v2/pkg/bootstrap"
@@ -38,6 +35,8 @@ import (
"github.com/fluxcd/flux2/v2/pkg/manifestgen/install" "github.com/fluxcd/flux2/v2/pkg/manifestgen/install"
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret" "github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sync" "github.com/fluxcd/flux2/v2/pkg/manifestgen/sync"
"github.com/fluxcd/pkg/git"
"github.com/fluxcd/pkg/git/gogit"
) )
var bootstrapGitCmd = &cobra.Command{ var bootstrapGitCmd = &cobra.Command{
@@ -66,10 +65,7 @@ command will perform an upgrade if needed.`,
flux bootstrap git --url=ssh://<SSH-Key-ID>@git-codecommit.<region>.amazonaws.com/v1/repos/<repository> --private-key-file=<path/to/private.key> --password=<SSH-passphrase> --path=clusters/my-cluster flux bootstrap git --url=ssh://<SSH-Key-ID>@git-codecommit.<region>.amazonaws.com/v1/repos/<repository> --private-key-file=<path/to/private.key> --password=<SSH-passphrase> --path=clusters/my-cluster
# Run bootstrap for a Git repository on Azure Devops # Run bootstrap for a Git repository on Azure Devops
flux bootstrap git --url=ssh://git@ssh.dev.azure.com/v3/<org>/<project>/<repository> --private-key-file=<path/to/rsa-sha2-private.key> --ssh-hostkey-algos=rsa-sha2-512,rsa-sha2-256 --path=clusters/my-cluster flux bootstrap git --url=ssh://git@ssh.dev.azure.com/v3/<org>/<project>/<repository> --ssh-key-algorithm=rsa --ssh-rsa-bits=4096 --path=clusters/my-cluster
# Run bootstrap for a Git repository on Oracle VBS
flux bootstrap git --url=https://repository_url.git --with-bearer-token=true --password=<PAT> --path=clusters/my-cluster
`, `,
RunE: bootstrapGitCmdRun, RunE: bootstrapGitCmdRun,
} }
@@ -82,7 +78,6 @@ type gitFlags struct {
password string password string
silent bool silent bool
insecureHttpAllowed bool insecureHttpAllowed bool
withBearerToken bool
} }
const ( const (
@@ -99,16 +94,11 @@ func init() {
bootstrapGitCmd.Flags().StringVarP(&gitArgs.password, "password", "p", "", "basic authentication password") bootstrapGitCmd.Flags().StringVarP(&gitArgs.password, "password", "p", "", "basic authentication password")
bootstrapGitCmd.Flags().BoolVarP(&gitArgs.silent, "silent", "s", false, "assumes the deploy key is already setup, skips confirmation") bootstrapGitCmd.Flags().BoolVarP(&gitArgs.silent, "silent", "s", false, "assumes the deploy key is already setup, skips confirmation")
bootstrapGitCmd.Flags().BoolVar(&gitArgs.insecureHttpAllowed, "allow-insecure-http", false, "allows insecure HTTP connections") bootstrapGitCmd.Flags().BoolVar(&gitArgs.insecureHttpAllowed, "allow-insecure-http", false, "allows insecure HTTP connections")
bootstrapGitCmd.Flags().BoolVar(&gitArgs.withBearerToken, "with-bearer-token", false, "use password as bearer token for Authorization header")
bootstrapCmd.AddCommand(bootstrapGitCmd) bootstrapCmd.AddCommand(bootstrapGitCmd)
} }
func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error { func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
if gitArgs.withBearerToken {
bootstrapArgs.tokenAuth = true
}
gitPassword := os.Getenv(gitPasswordEnvVar) gitPassword := os.Getenv(gitPasswordEnvVar)
if gitPassword != "" && gitArgs.password == "" { if gitPassword != "" && gitArgs.password == "" {
gitArgs.password = gitPassword gitArgs.password = gitPassword
@@ -211,7 +201,6 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
Namespace: *kubeconfigArgs.Namespace, Namespace: *kubeconfigArgs.Namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
RegistryCredential: bootstrapArgs.registryCredential,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
WatchAllNamespaces: bootstrapArgs.watchAllNamespaces, WatchAllNamespaces: bootstrapArgs.watchAllNamespaces,
NetworkPolicy: bootstrapArgs.networkPolicy, NetworkPolicy: bootstrapArgs.networkPolicy,
@@ -234,15 +223,9 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
TargetPath: gitArgs.path.String(), TargetPath: gitArgs.path.String(),
ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile, ManifestFile: sourcesecret.MakeDefaultOptions().ManifestFile,
} }
if bootstrapArgs.tokenAuth { if bootstrapArgs.tokenAuth {
if gitArgs.withBearerToken {
secretOpts.BearerToken = gitArgs.password
} else {
secretOpts.Username = gitArgs.username secretOpts.Username = gitArgs.username
secretOpts.Password = gitArgs.password secretOpts.Password = gitArgs.password
}
secretOpts.CAFile = caBundle secretOpts.CAFile = caBundle
// Remove port of the given host when not syncing over HTTP/S to not assume port for protocol // Remove port of the given host when not syncing over HTTP/S to not assume port for protocol
@@ -335,28 +318,18 @@ func getAuthOpts(u *url.URL, caBundle []byte) (*git.AuthOptions, error) {
if !gitArgs.insecureHttpAllowed { if !gitArgs.insecureHttpAllowed {
return nil, fmt.Errorf("scheme http is insecure, pass --allow-insecure-http=true to allow it") return nil, fmt.Errorf("scheme http is insecure, pass --allow-insecure-http=true to allow it")
} }
httpAuth := git.AuthOptions{ return &git.AuthOptions{
Transport: git.HTTP, Transport: git.HTTP,
} Username: gitArgs.username,
if gitArgs.withBearerToken { Password: gitArgs.password,
httpAuth.BearerToken = gitArgs.password }, nil
} else {
httpAuth.Username = gitArgs.username
httpAuth.Password = gitArgs.password
}
return &httpAuth, nil
case "https": case "https":
httpsAuth := git.AuthOptions{ return &git.AuthOptions{
Transport: git.HTTPS, Transport: git.HTTPS,
Username: gitArgs.username,
Password: gitArgs.password,
CAFile: caBundle, CAFile: caBundle,
} }, nil
if gitArgs.withBearerToken {
httpsAuth.BearerToken = gitArgs.password
} else {
httpsAuth.Username = gitArgs.username
httpsAuth.Password = gitArgs.password
}
return &httpsAuth, nil
case "ssh": case "ssh":
authOpts := &git.AuthOptions{ authOpts := &git.AuthOptions{
Transport: git.SSH, Transport: git.SSH,

View File

@@ -184,7 +184,6 @@ func bootstrapGiteaCmdRun(cmd *cobra.Command, args []string) error {
Namespace: *kubeconfigArgs.Namespace, Namespace: *kubeconfigArgs.Namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
RegistryCredential: bootstrapArgs.registryCredential,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
WatchAllNamespaces: bootstrapArgs.watchAllNamespaces, WatchAllNamespaces: bootstrapArgs.watchAllNamespaces,
NetworkPolicy: bootstrapArgs.networkPolicy, NetworkPolicy: bootstrapArgs.networkPolicy,

View File

@@ -191,7 +191,6 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
Namespace: *kubeconfigArgs.Namespace, Namespace: *kubeconfigArgs.Namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
RegistryCredential: bootstrapArgs.registryCredential,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
WatchAllNamespaces: bootstrapArgs.watchAllNamespaces, WatchAllNamespaces: bootstrapArgs.watchAllNamespaces,
NetworkPolicy: bootstrapArgs.networkPolicy, NetworkPolicy: bootstrapArgs.networkPolicy,

View File

@@ -216,7 +216,6 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
Namespace: *kubeconfigArgs.Namespace, Namespace: *kubeconfigArgs.Namespace,
Components: bootstrapComponents(), Components: bootstrapComponents(),
Registry: bootstrapArgs.registry, Registry: bootstrapArgs.registry,
RegistryCredential: bootstrapArgs.registryCredential,
ImagePullSecret: bootstrapArgs.imagePullSecret, ImagePullSecret: bootstrapArgs.imagePullSecret,
WatchAllNamespaces: bootstrapArgs.watchAllNamespaces, WatchAllNamespaces: bootstrapArgs.watchAllNamespaces,
NetworkPolicy: bootstrapArgs.networkPolicy, NetworkPolicy: bootstrapArgs.networkPolicy,

View File

@@ -21,10 +21,10 @@ import (
"os" "os"
"os/signal" "os/signal"
"github.com/fluxcd/pkg/ssa"
"github.com/spf13/cobra" "github.com/spf13/cobra"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
ssautil "github.com/fluxcd/pkg/ssa/utils"
"github.com/fluxcd/flux2/v2/internal/build" "github.com/fluxcd/flux2/v2/internal/build"
) )
@@ -63,7 +63,6 @@ type buildKsFlags struct {
path string path string
ignorePaths []string ignorePaths []string
dryRun bool dryRun bool
strictSubst bool
} }
var buildKsArgs buildKsFlags var buildKsArgs buildKsFlags
@@ -73,8 +72,6 @@ func init() {
buildKsCmd.Flags().StringVar(&buildKsArgs.kustomizationFile, "kustomization-file", "", "Path to the Flux Kustomization YAML file.") buildKsCmd.Flags().StringVar(&buildKsArgs.kustomizationFile, "kustomization-file", "", "Path to the Flux Kustomization YAML file.")
buildKsCmd.Flags().StringSliceVar(&buildKsArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore in .gitignore format") buildKsCmd.Flags().StringSliceVar(&buildKsArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore in .gitignore format")
buildKsCmd.Flags().BoolVar(&buildKsArgs.dryRun, "dry-run", false, "Dry run mode.") buildKsCmd.Flags().BoolVar(&buildKsArgs.dryRun, "dry-run", false, "Dry run mode.")
buildKsCmd.Flags().BoolVar(&buildKsArgs.strictSubst, "strict-substitute", false,
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
buildCmd.AddCommand(buildKsCmd) buildCmd.AddCommand(buildKsCmd)
} }
@@ -110,7 +107,6 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
build.WithDryRun(buildKsArgs.dryRun), build.WithDryRun(buildKsArgs.dryRun),
build.WithNamespace(*kubeconfigArgs.Namespace), build.WithNamespace(*kubeconfigArgs.Namespace),
build.WithIgnore(buildKsArgs.ignorePaths), build.WithIgnore(buildKsArgs.ignorePaths),
build.WithStrictSubstitute(buildKsArgs.strictSubst),
) )
} else { } else {
builder, err = build.NewBuilder(name, buildKsArgs.path, builder, err = build.NewBuilder(name, buildKsArgs.path,
@@ -118,7 +114,6 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
build.WithTimeout(rootArgs.timeout), build.WithTimeout(rootArgs.timeout),
build.WithKustomizationFile(buildKsArgs.kustomizationFile), build.WithKustomizationFile(buildKsArgs.kustomizationFile),
build.WithIgnore(buildKsArgs.ignorePaths), build.WithIgnore(buildKsArgs.ignorePaths),
build.WithStrictSubstitute(buildKsArgs.strictSubst),
) )
} }
@@ -137,7 +132,7 @@ func buildKsCmdRun(cmd *cobra.Command, args []string) (err error) {
errChan <- err errChan <- err
} }
manifests, err := ssautil.ObjectsToYAML(objects) manifests, err := ssa.ObjectsToYAML(objects)
if err != nil { if err != nil {
errChan <- err errChan <- err
} }

View File

@@ -40,7 +40,6 @@ import (
var checkCmd = &cobra.Command{ var checkCmd = &cobra.Command{
Use: "check", Use: "check",
Args: cobra.NoArgs,
Short: "Check requirements and installation", Short: "Check requirements and installation",
Long: withPreviewNote(`The check command will perform a series of checks to validate that Long: withPreviewNote(`The check command will perform a series of checks to validate that
the local environment is configured correctly and if the installed components are healthy.`), the local environment is configured correctly and if the installed components are healthy.`),
@@ -60,7 +59,7 @@ type checkFlags struct {
} }
var kubernetesConstraints = []string{ var kubernetesConstraints = []string{
">=1.28.0-0", ">=1.25.0-0",
} }
var checkArgs checkFlags var checkArgs checkFlags

View File

@@ -29,7 +29,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/client/fake"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
ssautil "github.com/fluxcd/pkg/ssa/utils" "github.com/fluxcd/pkg/ssa"
) )
func Test_getFluxClusterInfo(t *testing.T) { func Test_getFluxClusterInfo(t *testing.T) {
@@ -37,7 +37,7 @@ func Test_getFluxClusterInfo(t *testing.T) {
f, err := os.Open("./testdata/cluster_info/gitrepositories.yaml") f, err := os.Open("./testdata/cluster_info/gitrepositories.yaml")
g.Expect(err).To(BeNil()) g.Expect(err).To(BeNil())
objs, err := ssautil.ReadObjects(f) objs, err := ssa.ReadObjects(f)
g.Expect(err).To(Not(HaveOccurred())) g.Expect(err).To(Not(HaveOccurred()))
gitrepo := objs[0] gitrepo := objs[0]

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2024 The Flux authors Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -24,6 +24,11 @@ import (
"strings" "strings"
"time" "time"
"github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/transform"
"github.com/spf13/cobra" "github.com/spf13/cobra"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
@@ -33,21 +38,14 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/transform"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2"
"github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils"
) )
var createHelmReleaseCmd = &cobra.Command{ var createHelmReleaseCmd = &cobra.Command{
Use: "helmrelease [name]", Use: "helmrelease [name]",
Aliases: []string{"hr"}, Aliases: []string{"hr"},
Short: "Create or update a HelmRelease resource", Short: "Create or update a HelmRelease resource",
Long: `The helmrelease create command generates a HelmRelease resource for a given HelmRepository source.`, Long: withPreviewNote(`The helmrelease create command generates a HelmRelease resource for a given HelmRepository source.`),
Example: ` # Create a HelmRelease with a chart from a HelmRepository source Example: ` # Create a HelmRelease with a chart from a HelmRepository source
flux create hr podinfo \ flux create hr podinfo \
--interval=10m \ --interval=10m \
@@ -106,17 +104,7 @@ var createHelmReleaseCmd = &cobra.Command{
--source=HelmRepository/podinfo \ --source=HelmRepository/podinfo \
--chart=podinfo \ --chart=podinfo \
--values=./values.yaml \ --values=./values.yaml \
--export > podinfo-release.yaml --export > podinfo-release.yaml`,
# Create a HelmRelease using a chart from a HelmChart resource
flux create hr podinfo \
--namespace=default \
--chart-ref=HelmChart/podinfo.flux-system \
# Create a HelmRelease using a chart from an OCIRepository resource
flux create hr podinfo \
--namespace=default \
--chart-ref=OCIRepository/podinfo.flux-system`,
RunE: createHelmReleaseCmdRun, RunE: createHelmReleaseCmdRun,
} }
@@ -126,7 +114,6 @@ type helmReleaseFlags struct {
dependsOn []string dependsOn []string
chart string chart string
chartVersion string chartVersion string
chartRef string
targetNamespace string targetNamespace string
createNamespace bool createNamespace bool
valuesFiles []string valuesFiles []string
@@ -142,8 +129,6 @@ var helmReleaseArgs helmReleaseFlags
var supportedHelmReleaseValuesFromKinds = []string{"Secret", "ConfigMap"} var supportedHelmReleaseValuesFromKinds = []string{"Secret", "ConfigMap"}
var supportedHelmReleaseReferenceKinds = []string{sourcev1b2.OCIRepositoryKind, sourcev1.HelmChartKind}
func init() { func init() {
createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.name, "release-name", "", "name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'") createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.name, "release-name", "", "name used for the Helm release, defaults to a composition of '[<target-namespace>-]<HelmRelease-name>'")
createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.source, "source", helmReleaseArgs.source.Description()) createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.source, "source", helmReleaseArgs.source.Description())
@@ -159,15 +144,14 @@ func init() {
createHelmReleaseCmd.Flags().StringSliceVar(&helmReleaseArgs.valuesFrom, "values-from", nil, "a Kubernetes object reference that contains the values.yaml data key in the format '<kind>/<name>', where kind must be one of: (Secret,ConfigMap)") createHelmReleaseCmd.Flags().StringSliceVar(&helmReleaseArgs.valuesFrom, "values-from", nil, "a Kubernetes object reference that contains the values.yaml data key in the format '<kind>/<name>', where kind must be one of: (Secret,ConfigMap)")
createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.crds, "crds", helmReleaseArgs.crds.Description()) createHelmReleaseCmd.Flags().Var(&helmReleaseArgs.crds, "crds", helmReleaseArgs.crds.Description())
createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.kubeConfigSecretRef, "kubeconfig-secret-ref", "", "the name of the Kubernetes Secret that contains a key with the kubeconfig file for connecting to a remote cluster") createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.kubeConfigSecretRef, "kubeconfig-secret-ref", "", "the name of the Kubernetes Secret that contains a key with the kubeconfig file for connecting to a remote cluster")
createHelmReleaseCmd.Flags().StringVar(&helmReleaseArgs.chartRef, "chart-ref", "", "the name of the HelmChart resource to use as source for the HelmRelease, in the format '<kind>/<name>.<namespace>', where kind must be one of: (OCIRepository,HelmChart)")
createCmd.AddCommand(createHelmReleaseCmd) createCmd.AddCommand(createHelmReleaseCmd)
} }
func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error { func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
name := args[0] name := args[0]
if helmReleaseArgs.chart == "" && helmReleaseArgs.chartRef == "" { if helmReleaseArgs.chart == "" {
return fmt.Errorf("chart or chart-ref is required") return fmt.Errorf("chart name or path is required")
} }
sourceLabels, err := parseLabels() sourceLabels, err := parseLabels()
@@ -197,13 +181,8 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
Duration: createArgs.interval, Duration: createArgs.interval,
}, },
TargetNamespace: helmReleaseArgs.targetNamespace, TargetNamespace: helmReleaseArgs.targetNamespace,
Suspend: false,
},
}
switch { Chart: helmv2.HelmChartTemplate{
case helmReleaseArgs.chart != "":
helmRelease.Spec.Chart = &helmv2.HelmChartTemplate{
Spec: helmv2.HelmChartTemplateSpec{ Spec: helmv2.HelmChartTemplateSpec{
Chart: helmReleaseArgs.chart, Chart: helmReleaseArgs.chart,
Version: helmReleaseArgs.chartVersion, Version: helmReleaseArgs.chartVersion,
@@ -214,23 +193,9 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
}, },
ReconcileStrategy: helmReleaseArgs.reconcileStrategy, ReconcileStrategy: helmReleaseArgs.reconcileStrategy,
}, },
} },
if helmReleaseArgs.chartInterval != 0 { Suspend: false,
helmRelease.Spec.Chart.Spec.Interval = &metav1.Duration{ },
Duration: helmReleaseArgs.chartInterval,
}
}
case helmReleaseArgs.chartRef != "":
kind, name, ns := utils.ParseObjectKindNameNamespace(helmReleaseArgs.chartRef)
if kind != sourcev1.HelmChartKind && kind != sourcev1b2.OCIRepositoryKind {
return fmt.Errorf("chart reference kind '%s' is not supported, must be one of: %s",
kind, strings.Join(supportedHelmReleaseReferenceKinds, ", "))
}
helmRelease.Spec.ChartRef = &helmv2.CrossNamespaceSourceReference{
Kind: kind,
Name: name,
Namespace: ns,
}
} }
if helmReleaseArgs.kubeConfigSecretRef != "" { if helmReleaseArgs.kubeConfigSecretRef != "" {
@@ -241,6 +206,12 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} }
} }
if helmReleaseArgs.chartInterval != 0 {
helmRelease.Spec.Chart.Spec.Interval = &metav1.Duration{
Duration: helmReleaseArgs.chartInterval,
}
}
if helmReleaseArgs.createNamespace { if helmReleaseArgs.createNamespace {
if helmRelease.Spec.Install == nil { if helmRelease.Spec.Install == nil {
helmRelease.Spec.Install = &helmv2.Install{} helmRelease.Spec.Install = &helmv2.Install{}
@@ -337,7 +308,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
} }
logger.Successf("HelmRelease %s is ready", name) logger.Successf("HelmRelease %s is ready", name)
logger.Successf("applied revision %s", getHelmReleaseRevision(helmRelease)) logger.Successf("applied revision %s", helmRelease.Status.LastAppliedRevision)
return nil return nil
} }

View File

@@ -1,86 +0,0 @@
//go:build unit
// +build unit
/*
Copyright 2024 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 main
import "testing"
func TestCreateHelmRelease(t *testing.T) {
tmpl := map[string]string{
"fluxns": allocateNamespace("flux-system"),
}
setupHRSource(t, tmpl)
tests := []struct {
name string
args string
assert assertFunc
}{
{
name: "missing name",
args: "create helmrelease --export",
assert: assertError("name is required"),
},
{
name: "missing chart template and chartRef",
args: "create helmrelease podinfo --export",
assert: assertError("chart or chart-ref is required"),
},
{
name: "unknown source kind",
args: "create helmrelease podinfo --source foobar/podinfo --chart podinfo --export",
assert: assertError(`invalid argument "foobar/podinfo" for "--source" flag: source kind 'foobar' is not supported, must be one of: HelmRepository, GitRepository, Bucket`),
},
{
name: "unknown chart reference kind",
args: "create helmrelease podinfo --chart-ref foobar/podinfo --export",
assert: assertError(`chart reference kind 'foobar' is not supported, must be one of: OCIRepository, HelmChart`),
},
{
name: "basic helmrelease",
args: "create helmrelease podinfo --source Helmrepository/podinfo --chart podinfo --interval=1m0s --export",
assert: assertGoldenTemplateFile("testdata/create_hr/basic.yaml", tmpl),
},
{
name: "chart with OCIRepository source",
args: "create helmrelease podinfo --chart-ref OCIRepository/podinfo --interval=1m0s --export",
assert: assertGoldenTemplateFile("testdata/create_hr/or_basic.yaml", tmpl),
},
{
name: "chart with HelmChart source",
args: "create helmrelease podinfo --chart-ref HelmChart/podinfo --interval=1m0s --export",
assert: assertGoldenTemplateFile("testdata/create_hr/hc_basic.yaml", tmpl),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := cmdTestCase{
args: tt.args + " -n " + tmpl["fluxns"],
assert: tt.assert,
}
cmd.runTestCmd(t)
})
}
}
func setupHRSource(t *testing.T, tmpl map[string]string) {
t.Helper()
testEnv.CreateObjectFile("./testdata/create_hr/setup-source.yaml", tmpl, t)
}

View File

@@ -22,7 +22,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1"
) )

View File

@@ -29,7 +29,7 @@ import (
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
"github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/apis/meta"

View File

@@ -32,7 +32,7 @@ import (
var createSecretHelmCmd = &cobra.Command{ var createSecretHelmCmd = &cobra.Command{
Use: "helm [name]", Use: "helm [name]",
Short: "Create or update a Kubernetes secret for Helm repository authentication", Short: "Create or update a Kubernetes secret for Helm repository authentication",
Long: `The create secret helm command generates a Kubernetes secret with basic authentication credentials.`, Long: withPreviewNote(`The create secret helm command generates a Kubernetes secret with basic authentication credentials.`),
Example: ` # Create a Helm authentication secret on disk and encrypt it with Mozilla SOPS Example: ` # Create a Helm authentication secret on disk and encrypt it with Mozilla SOPS
flux create secret helm repo-auth \ flux create secret helm repo-auth \
--namespace=my-namespace \ --namespace=my-namespace \

View File

@@ -1,161 +0,0 @@
/*
Copyright 2024 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 main
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"strings"
"github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
"github.com/notaryproject/notation-go/verifier/trustpolicy"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"sigs.k8s.io/yaml"
)
var createSecretNotationCmd = &cobra.Command{
Use: "notation [name]",
Short: "Create or update a Kubernetes secret for verifications of artifacts signed by Notation",
Long: withPreviewNote(`The create secret notation command generates a Kubernetes secret with root ca certificates and trust policy.`),
Example: ` # Create a Notation configuration secret on disk and encrypt it with Mozilla SOPS
flux create secret notation my-notation-cert \
--namespace=my-namespace \
--trust-policy-file=./my-trust-policy.json \
--ca-cert-file=./my-cert.crt \
--export > my-notation-cert.yaml
sops --encrypt --encrypted-regex '^(data|stringData)$' \
--in-place my-notation-cert.yaml`,
RunE: createSecretNotationCmdRun,
}
type secretNotationFlags struct {
trustPolicyFile string
caCrtFile []string
}
var secretNotationArgs secretNotationFlags
func init() {
createSecretNotationCmd.Flags().StringVar(&secretNotationArgs.trustPolicyFile, "trust-policy-file", "", "notation trust policy file path")
createSecretNotationCmd.Flags().StringSliceVar(&secretNotationArgs.caCrtFile, "ca-cert-file", []string{}, "root ca cert file path")
createSecretCmd.AddCommand(createSecretNotationCmd)
}
func createSecretNotationCmdRun(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return fmt.Errorf("name is required")
}
if secretNotationArgs.caCrtFile == nil || len(secretNotationArgs.caCrtFile) == 0 {
return fmt.Errorf("--ca-cert-file is required")
}
if secretNotationArgs.trustPolicyFile == "" {
return fmt.Errorf("--trust-policy-file is required")
}
name := args[0]
labels, err := parseLabels()
if err != nil {
return err
}
policy, err := os.ReadFile(secretNotationArgs.trustPolicyFile)
if err != nil {
return fmt.Errorf("unable to read trust policy file: %w", err)
}
var doc trustpolicy.Document
if err := json.Unmarshal(policy, &doc); err != nil {
return fmt.Errorf("failed to unmarshal trust policy %s: %w", secretNotationArgs.trustPolicyFile, err)
}
if err := doc.Validate(); err != nil {
return fmt.Errorf("invalid trust policy: %w", err)
}
var (
caCerts []sourcesecret.VerificationCrt
fileErr error
)
for _, caCrtFile := range secretNotationArgs.caCrtFile {
fileName := filepath.Base(caCrtFile)
if !strings.HasSuffix(fileName, ".crt") && !strings.HasSuffix(fileName, ".pem") {
fileErr = errors.Join(fileErr, fmt.Errorf("%s must end with either .crt or .pem", fileName))
continue
}
caBundle, err := os.ReadFile(caCrtFile)
if err != nil {
fileErr = errors.Join(fileErr, fmt.Errorf("unable to read TLS CA file: %w", err))
continue
}
caCerts = append(caCerts, sourcesecret.VerificationCrt{Name: fileName, CACrt: caBundle})
}
if fileErr != nil {
return fileErr
}
if len(caCerts) == 0 {
return fmt.Errorf("no CA certs found")
}
opts := sourcesecret.Options{
Name: name,
Namespace: *kubeconfigArgs.Namespace,
Labels: labels,
VerificationCrts: caCerts,
TrustPolicy: policy,
}
secret, err := sourcesecret.Generate(opts)
if err != nil {
return err
}
if createArgs.export {
rootCmd.Println(secret.Content)
return nil
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
if err != nil {
return err
}
var s corev1.Secret
if err := yaml.Unmarshal([]byte(secret.Content), &s); err != nil {
return err
}
if err := upsertSecret(ctx, kubeClient, s); err != nil {
return err
}
logger.Actionf("notation configuration secret '%s' created in '%s' namespace", name, *kubeconfigArgs.Namespace)
return nil
}

View File

@@ -1,124 +0,0 @@
/*
Copyright 2024 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 main
import (
"fmt"
"os"
"path/filepath"
"testing"
)
const (
trustPolicy = "./testdata/create_secret/notation/test-trust-policy.json"
invalidTrustPolicy = "./testdata/create_secret/notation/invalid-trust-policy.json"
invalidJson = "./testdata/create_secret/notation/invalid.json"
testCertFolder = "./testdata/create_secret/notation"
)
func TestCreateNotationSecret(t *testing.T) {
crt, err := os.Create(filepath.Join(t.TempDir(), "ca.crt"))
if err != nil {
t.Fatal("could not create ca.crt file")
}
pem, err := os.Create(filepath.Join(t.TempDir(), "ca.pem"))
if err != nil {
t.Fatal("could not create ca.pem file")
}
invalidCert, err := os.Create(filepath.Join(t.TempDir(), "ca.p12"))
if err != nil {
t.Fatal("could not create ca.p12 file")
}
_, err = crt.Write([]byte("ca-data-crt"))
if err != nil {
t.Fatal("could not write to crt certificate file")
}
_, err = pem.Write([]byte("ca-data-pem"))
if err != nil {
t.Fatal("could not write to pem certificate file")
}
tests := []struct {
name string
args string
assert assertFunc
}{
{
name: "no args",
args: "create secret notation",
assert: assertError("name is required"),
},
{
name: "no trust policy",
args: fmt.Sprintf("create secret notation notation-config --ca-cert-file=%s", testCertFolder),
assert: assertError("--trust-policy-file is required"),
},
{
name: "no cert",
args: fmt.Sprintf("create secret notation notation-config --trust-policy-file=%s", trustPolicy),
assert: assertError("--ca-cert-file is required"),
},
{
name: "non pem and crt cert",
args: fmt.Sprintf("create secret notation notation-config --ca-cert-file=%s --trust-policy-file=%s", invalidCert.Name(), trustPolicy),
assert: assertError("ca.p12 must end with either .crt or .pem"),
},
{
name: "invalid trust policy",
args: fmt.Sprintf("create secret notation notation-config --ca-cert-file=%s --trust-policy-file=%s", t.TempDir(), invalidTrustPolicy),
assert: assertError("invalid trust policy: a trust policy statement is missing a name, every statement requires a name"),
},
{
name: "invalid trust policy json",
args: fmt.Sprintf("create secret notation notation-config --ca-cert-file=%s --trust-policy-file=%s", t.TempDir(), invalidJson),
assert: assertError(fmt.Sprintf("failed to unmarshal trust policy %s: json: cannot unmarshal string into Go value of type trustpolicy.Document", invalidJson)),
},
{
name: "crt secret",
args: fmt.Sprintf("create secret notation notation-config --ca-cert-file=%s --trust-policy-file=%s --namespace=my-namespace --export", crt.Name(), trustPolicy),
assert: assertGoldenFile("./testdata/create_secret/notation/secret-ca-crt.yaml"),
},
{
name: "pem secret",
args: fmt.Sprintf("create secret notation notation-config --ca-cert-file=%s --trust-policy-file=%s --namespace=my-namespace --export", pem.Name(), trustPolicy),
assert: assertGoldenFile("./testdata/create_secret/notation/secret-ca-pem.yaml"),
},
{
name: "multi secret",
args: fmt.Sprintf("create secret notation notation-config --ca-cert-file=%s --ca-cert-file=%s --trust-policy-file=%s --namespace=my-namespace --export", crt.Name(), pem.Name(), trustPolicy),
assert: assertGoldenFile("./testdata/create_secret/notation/secret-ca-multi.yaml"),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
defer func() {
secretNotationArgs = secretNotationFlags{}
}()
cmd := cmdTestCase{
args: tt.args,
assert: tt.assert,
}
cmd.runTestCmd(t)
})
}
}

View File

@@ -1,217 +0,0 @@
/*
Copyright 2024 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 main
import (
"context"
"fmt"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/pkg/apis/meta"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
"github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils"
)
var createSourceChartCmd = &cobra.Command{
Use: "chart [name]",
Short: "Create or update a HelmChart source",
Long: `The create source chart command generates a HelmChart resource and waits for the chart to be available.`,
Example: ` # Create a source for a chart residing in a HelmRepository
flux create source chart podinfo \
--source=HelmRepository/podinfo \
--chart=podinfo \
--chart-version=6.x
# Create a source for a chart residing in a Git repository
flux create source chart podinfo \
--source=GitRepository/podinfo \
--chart=./charts/podinfo
# Create a source for a chart residing in a S3 Bucket
flux create source chart podinfo \
--source=Bucket/podinfo \
--chart=./charts/podinfo
# Create a source for a chart from OCI and verify its signature
flux create source chart podinfo \
--source HelmRepository/podinfo \
--chart podinfo \
--chart-version=6.6.2 \
--verify-provider=cosign \
--verify-issuer=https://token.actions.githubusercontent.com \
--verify-subject=https://github.com/stefanprodan/podinfo/.github/workflows/release.yml@refs/tags/6.6.2`,
RunE: createSourceChartCmdRun,
}
type sourceChartFlags struct {
chart string
chartVersion string
source flags.LocalHelmChartSource
reconcileStrategy string
verifyProvider flags.SourceOCIVerifyProvider
verifySecretRef string
verifyOIDCIssuer string
verifySubject string
}
var sourceChartArgs sourceChartFlags
func init() {
createSourceChartCmd.Flags().StringVar(&sourceChartArgs.chart, "chart", "", "Helm chart name or path")
createSourceChartCmd.Flags().StringVar(&sourceChartArgs.chartVersion, "chart-version", "", "Helm chart version, accepts a semver range (ignored for charts from GitRepository sources)")
createSourceChartCmd.Flags().Var(&sourceChartArgs.source, "source", sourceChartArgs.source.Description())
createSourceChartCmd.Flags().StringVar(&sourceChartArgs.reconcileStrategy, "reconcile-strategy", "ChartVersion", "the reconcile strategy for helm chart (accepted values: Revision and ChartRevision)")
createSourceChartCmd.Flags().Var(&sourceChartArgs.verifyProvider, "verify-provider", sourceOCIRepositoryArgs.verifyProvider.Description())
createSourceChartCmd.Flags().StringVar(&sourceChartArgs.verifySecretRef, "verify-secret-ref", "", "the name of a secret to use for signature verification")
createSourceChartCmd.Flags().StringVar(&sourceChartArgs.verifySubject, "verify-subject", "", "regular expression to use for the OIDC subject during signature verification")
createSourceChartCmd.Flags().StringVar(&sourceChartArgs.verifyOIDCIssuer, "verify-issuer", "", "regular expression to use for the OIDC issuer during signature verification")
createSourceCmd.AddCommand(createSourceChartCmd)
}
func createSourceChartCmdRun(cmd *cobra.Command, args []string) error {
name := args[0]
if sourceChartArgs.source.Kind == "" || sourceChartArgs.source.Name == "" {
return fmt.Errorf("chart source is required")
}
if sourceChartArgs.chart == "" {
return fmt.Errorf("chart name or path is required")
}
logger.Generatef("generating HelmChart source")
sourceLabels, err := parseLabels()
if err != nil {
return err
}
helmChart := &sourcev1.HelmChart{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: *kubeconfigArgs.Namespace,
Labels: sourceLabels,
},
Spec: sourcev1.HelmChartSpec{
Chart: sourceChartArgs.chart,
Version: sourceChartArgs.chartVersion,
Interval: metav1.Duration{
Duration: createArgs.interval,
},
ReconcileStrategy: sourceChartArgs.reconcileStrategy,
SourceRef: sourcev1.LocalHelmChartSourceReference{
Kind: sourceChartArgs.source.Kind,
Name: sourceChartArgs.source.Name,
},
},
}
if provider := sourceChartArgs.verifyProvider.String(); provider != "" {
helmChart.Spec.Verify = &sourcev1.OCIRepositoryVerification{
Provider: provider,
}
if secretName := sourceChartArgs.verifySecretRef; secretName != "" {
helmChart.Spec.Verify.SecretRef = &meta.LocalObjectReference{
Name: secretName,
}
}
verifyIssuer := sourceChartArgs.verifyOIDCIssuer
verifySubject := sourceChartArgs.verifySubject
if verifyIssuer != "" || verifySubject != "" {
helmChart.Spec.Verify.MatchOIDCIdentity = []sourcev1.OIDCIdentityMatch{{
Issuer: verifyIssuer,
Subject: verifySubject,
}}
}
} else if sourceChartArgs.verifySecretRef != "" {
return fmt.Errorf("a verification provider must be specified when a secret is specified")
} else if sourceChartArgs.verifyOIDCIssuer != "" || sourceOCIRepositoryArgs.verifySubject != "" {
return fmt.Errorf("a verification provider must be specified when OIDC issuer/subject is specified")
}
if createArgs.export {
return printExport(exportHelmChart(helmChart))
}
logger.Actionf("applying HelmChart source")
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(kubeconfigArgs, kubeclientOptions)
if err != nil {
return err
}
namespacedName, err := upsertHelmChart(ctx, kubeClient, helmChart)
if err != nil {
return err
}
logger.Waitingf("waiting for HelmChart source reconciliation")
readyConditionFunc := isObjectReadyConditionFunc(kubeClient, namespacedName, helmChart)
if err := wait.PollUntilContextTimeout(ctx, rootArgs.pollInterval, rootArgs.timeout, true, readyConditionFunc); err != nil {
return err
}
logger.Successf("HelmChart source reconciliation completed")
if helmChart.Status.Artifact == nil {
return fmt.Errorf("HelmChart source reconciliation completed but no artifact was found")
}
logger.Successf("fetched revision: %s", helmChart.Status.Artifact.Revision)
return nil
}
func upsertHelmChart(ctx context.Context, kubeClient client.Client,
helmChart *sourcev1.HelmChart) (types.NamespacedName, error) {
namespacedName := types.NamespacedName{
Namespace: helmChart.GetNamespace(),
Name: helmChart.GetName(),
}
var existing sourcev1.HelmChart
err := kubeClient.Get(ctx, namespacedName, &existing)
if err != nil {
if errors.IsNotFound(err) {
if err := kubeClient.Create(ctx, helmChart); err != nil {
return namespacedName, err
} else {
logger.Successf("source created")
return namespacedName, nil
}
}
return namespacedName, err
}
existing.Labels = helmChart.Labels
existing.Spec = helmChart.Spec
if err := kubeClient.Update(ctx, &existing); err != nil {
return namespacedName, err
}
helmChart = &existing
logger.Successf("source updated")
return namespacedName, nil
}

View File

@@ -1,91 +0,0 @@
//go:build unit
// +build unit
/*
Copyright 2024 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 main
import "testing"
func TestCreateSourceChart(t *testing.T) {
tmpl := map[string]string{
"fluxns": allocateNamespace("flux-system"),
}
setupSourceChart(t, tmpl)
tests := []struct {
name string
args string
assert assertFunc
}{
{
name: "missing name",
args: "create source chart --export",
assert: assertError("name is required"),
},
{
name: "missing source reference",
args: "create source chart podinfo --export ",
assert: assertError("chart source is required"),
},
{
name: "missing chart name",
args: "create source chart podinfo --source helmrepository/podinfo --export",
assert: assertError("chart name or path is required"),
},
{
name: "unknown source kind",
args: "create source chart podinfo --source foobar/podinfo --export",
assert: assertError(`invalid argument "foobar/podinfo" for "--source" flag: source kind 'foobar' is not supported, must be one of: HelmRepository, GitRepository, Bucket`),
},
{
name: "basic chart",
args: "create source chart podinfo --source helmrepository/podinfo --chart podinfo --export",
assert: assertGoldenTemplateFile("testdata/create_source_chart/basic.yaml", tmpl),
},
{
name: "chart with basic signature verification",
args: "create source chart podinfo --source helmrepository/podinfo --chart podinfo --verify-provider cosign --export",
assert: assertGoldenTemplateFile("testdata/create_source_chart/verify_basic.yaml", tmpl),
},
{
name: "unknown signature verification provider",
args: "create source chart podinfo --source helmrepository/podinfo --chart podinfo --verify-provider foobar --export",
assert: assertError(`invalid argument "foobar" for "--verify-provider" flag: source OCI verify provider 'foobar' is not supported, must be one of: cosign`),
},
{
name: "chart with complete signature verification",
args: "create source chart podinfo --source helmrepository/podinfo --chart podinfo --verify-provider cosign --verify-issuer foo --verify-subject bar --export",
assert: assertGoldenTemplateFile("testdata/create_source_chart/verify_complete.yaml", tmpl),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cmd := cmdTestCase{
args: tt.args + " -n " + tmpl["fluxns"],
assert: tt.assert,
}
cmd.runTestCmd(t)
})
}
}
func setupSourceChart(t *testing.T, tmpl map[string]string) {
t.Helper()
testEnv.CreateObjectFile("./testdata/create_source_chart/setup-source.yaml", tmpl, t)
}

View File

@@ -22,6 +22,7 @@ import (
"net/url" "net/url"
"os" "os"
"github.com/fluxcd/pkg/apis/meta"
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
@@ -31,8 +32,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
"github.com/fluxcd/pkg/apis/meta" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret" "github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
@@ -41,8 +41,8 @@ import (
var createSourceHelmCmd = &cobra.Command{ var createSourceHelmCmd = &cobra.Command{
Use: "helm [name]", Use: "helm [name]",
Short: "Create or update a HelmRepository source", Short: "Create or update a HelmRepository source",
Long: `The create source helm command generates a HelmRepository resource and waits for it to fetch the index. Long: withPreviewNote(`The create source helm command generates a HelmRepository resource and waits for it to fetch the index.
For private Helm repositories, the basic authentication credentials are stored in a Kubernetes secret.`, For private Helm repositories, the basic authentication credentials are stored in a Kubernetes secret.`),
Example: ` # Create a source for an HTTPS public Helm repository Example: ` # Create a source for an HTTPS public Helm repository
flux create source helm podinfo \ flux create source helm podinfo \
--url=https://stefanprodan.github.io/podinfo \ --url=https://stefanprodan.github.io/podinfo \

View File

@@ -30,8 +30,7 @@ import (
"github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/apis/meta"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2"
"github.com/fluxcd/flux2/v2/internal/flags" "github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
@@ -44,17 +43,8 @@ var createSourceOCIRepositoryCmd = &cobra.Command{
Example: ` # Create an OCIRepository for a public container image Example: ` # Create an OCIRepository for a public container image
flux create source oci podinfo \ flux create source oci podinfo \
--url=oci://ghcr.io/stefanprodan/manifests/podinfo \ --url=oci://ghcr.io/stefanprodan/manifests/podinfo \
--tag=6.6.2 \ --tag=6.1.6 \
--interval=10m --interval=10m
# Create an OCIRepository with OIDC signature verification
flux create source oci podinfo \
--url=oci://ghcr.io/stefanprodan/manifests/podinfo \
--tag=6.6.2 \
--interval=10m \
--verify-provider=cosign \
--verify-subject="^https://github.com/stefanprodan/podinfo/.github/workflows/release.yml@refs/tags/6.6.2$" \
--verify-issuer="^https://token.actions.githubusercontent.com$"
`, `,
RunE: createSourceOCIRepositoryCmdRun, RunE: createSourceOCIRepositoryCmdRun,
} }
@@ -69,8 +59,6 @@ type sourceOCIRepositoryFlags struct {
certSecretRef string certSecretRef string
verifyProvider flags.SourceOCIVerifyProvider verifyProvider flags.SourceOCIVerifyProvider
verifySecretRef string verifySecretRef string
verifyOIDCIssuer string
verifySubject string
ignorePaths []string ignorePaths []string
provider flags.SourceOCIProvider provider flags.SourceOCIProvider
insecure bool insecure bool
@@ -80,7 +68,7 @@ var sourceOCIRepositoryArgs = newSourceOCIFlags()
func newSourceOCIFlags() sourceOCIRepositoryFlags { func newSourceOCIFlags() sourceOCIRepositoryFlags {
return sourceOCIRepositoryFlags{ return sourceOCIRepositoryFlags{
provider: flags.SourceOCIProvider(sourcev1b2.GenericOCIProvider), provider: flags.SourceOCIProvider(sourcev1.GenericOCIProvider),
} }
} }
@@ -95,8 +83,6 @@ func init() {
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.certSecretRef, "cert-ref", "", "the name of a secret to use for TLS certificates") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.certSecretRef, "cert-ref", "", "the name of a secret to use for TLS certificates")
createSourceOCIRepositoryCmd.Flags().Var(&sourceOCIRepositoryArgs.verifyProvider, "verify-provider", sourceOCIRepositoryArgs.verifyProvider.Description()) createSourceOCIRepositoryCmd.Flags().Var(&sourceOCIRepositoryArgs.verifyProvider, "verify-provider", sourceOCIRepositoryArgs.verifyProvider.Description())
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.verifySecretRef, "verify-secret-ref", "", "the name of a secret to use for signature verification") createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.verifySecretRef, "verify-secret-ref", "", "the name of a secret to use for signature verification")
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.verifySubject, "verify-subject", "", "regular expression to use for the OIDC subject during signature verification")
createSourceOCIRepositoryCmd.Flags().StringVar(&sourceOCIRepositoryArgs.verifyOIDCIssuer, "verify-issuer", "", "regular expression to use for the OIDC issuer during signature verification")
createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)") createSourceOCIRepositoryCmd.Flags().StringSliceVar(&sourceOCIRepositoryArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore resources (can specify multiple paths with commas: path1,path2)")
createSourceOCIRepositoryCmd.Flags().BoolVar(&sourceOCIRepositoryArgs.insecure, "insecure", false, "for when connecting to a non-TLS registries over plain HTTP") createSourceOCIRepositoryCmd.Flags().BoolVar(&sourceOCIRepositoryArgs.insecure, "insecure", false, "for when connecting to a non-TLS registries over plain HTTP")
@@ -125,20 +111,20 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
ignorePaths = &ignorePathsStr ignorePaths = &ignorePathsStr
} }
repository := &sourcev1b2.OCIRepository{ repository := &sourcev1.OCIRepository{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: name, Name: name,
Namespace: *kubeconfigArgs.Namespace, Namespace: *kubeconfigArgs.Namespace,
Labels: sourceLabels, Labels: sourceLabels,
}, },
Spec: sourcev1b2.OCIRepositorySpec{ Spec: sourcev1.OCIRepositorySpec{
Provider: sourceOCIRepositoryArgs.provider.String(), Provider: sourceOCIRepositoryArgs.provider.String(),
URL: sourceOCIRepositoryArgs.url, URL: sourceOCIRepositoryArgs.url,
Insecure: sourceOCIRepositoryArgs.insecure, Insecure: sourceOCIRepositoryArgs.insecure,
Interval: metav1.Duration{ Interval: metav1.Duration{
Duration: createArgs.interval, Duration: createArgs.interval,
}, },
Reference: &sourcev1b2.OCIRepositoryRef{}, Reference: &sourcev1.OCIRepositoryRef{},
Ignore: ignorePaths, Ignore: ignorePaths,
}, },
} }
@@ -182,18 +168,8 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
Name: secretName, Name: secretName,
} }
} }
verifyIssuer := sourceOCIRepositoryArgs.verifyOIDCIssuer
verifySubject := sourceOCIRepositoryArgs.verifySubject
if verifyIssuer != "" || verifySubject != "" {
repository.Spec.Verify.MatchOIDCIdentity = []sourcev1.OIDCIdentityMatch{{
Issuer: verifyIssuer,
Subject: verifySubject,
}}
}
} else if sourceOCIRepositoryArgs.verifySecretRef != "" { } else if sourceOCIRepositoryArgs.verifySecretRef != "" {
return fmt.Errorf("a verification provider must be specified when a secret is specified") return fmt.Errorf("a verification provider must be specified when a secret is specified")
} else if sourceOCIRepositoryArgs.verifyOIDCIssuer != "" || sourceOCIRepositoryArgs.verifySubject != "" {
return fmt.Errorf("a verification provider must be specified when OIDC issuer/subject is specified")
} }
if createArgs.export { if createArgs.export {
@@ -229,13 +205,13 @@ func createSourceOCIRepositoryCmdRun(cmd *cobra.Command, args []string) error {
} }
func upsertOCIRepository(ctx context.Context, kubeClient client.Client, func upsertOCIRepository(ctx context.Context, kubeClient client.Client,
ociRepository *sourcev1b2.OCIRepository) (types.NamespacedName, error) { ociRepository *sourcev1.OCIRepository) (types.NamespacedName, error) {
namespacedName := types.NamespacedName{ namespacedName := types.NamespacedName{
Namespace: ociRepository.GetNamespace(), Namespace: ociRepository.GetNamespace(),
Name: ociRepository.GetName(), Name: ociRepository.GetName(),
} }
var existing sourcev1b2.OCIRepository var existing sourcev1.OCIRepository
err := kubeClient.Get(ctx, namespacedName, &existing) err := kubeClient.Get(ctx, namespacedName, &existing)
if err != nil { if err != nil {
if errors.IsNotFound(err) { if errors.IsNotFound(err) {

View File

@@ -37,35 +37,10 @@ func TestCreateSourceOCI(t *testing.T) {
assertFunc: assertError("url is required"), assertFunc: assertError("url is required"),
}, },
{ {
name: "verify secret specified but provider missing", name: "verify provider not specified",
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --verify-secret-ref=cosign-pub", args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --verify-secret-ref=cosign-pub",
assertFunc: assertError("a verification provider must be specified when a secret is specified"), assertFunc: assertError("a verification provider must be specified when a secret is specified"),
}, },
{
name: "verify issuer specified but provider missing",
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --verify-issuer=github.com",
assertFunc: assertError("a verification provider must be specified when OIDC issuer/subject is specified"),
},
{
name: "verify identity specified but provider missing",
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --verify-subject=developer",
assertFunc: assertError("a verification provider must be specified when OIDC issuer/subject is specified"),
},
{
name: "verify issuer specified but subject missing",
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --verify-issuer=github --verify-provider=cosign --export",
assertFunc: assertGoldenFile("./testdata/oci/export_with_issuer.golden"),
},
{
name: "all verify fields set",
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --verify-issuer=github verify-subject=stefanprodan --verify-provider=cosign --export",
assertFunc: assertGoldenFile("./testdata/oci/export_with_issuer.golden"),
},
{
name: "verify subject specified but issuer missing",
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --verify-subject=stefanprodan --verify-provider=cosign --export",
assertFunc: assertGoldenFile("./testdata/oci/export_with_subject.golden"),
},
{ {
name: "export manifest", name: "export manifest",
args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --export", args: "create source oci podinfo --url=oci://ghcr.io/stefanprodan/manifests/podinfo --tag=6.3.5 --interval 10m --export",

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2024 The Flux authors Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -19,14 +19,14 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
) )
var deleteHelmReleaseCmd = &cobra.Command{ var deleteHelmReleaseCmd = &cobra.Command{
Use: "helmrelease [name]", Use: "helmrelease [name]",
Aliases: []string{"hr"}, Aliases: []string{"hr"},
Short: "Delete a HelmRelease resource", Short: "Delete a HelmRelease resource",
Long: "The delete helmrelease command removes the given HelmRelease from the cluster.", Long: withPreviewNote("The delete helmrelease command removes the given HelmRelease from the cluster."),
Example: ` # Delete a Helm release and the Kubernetes resources created by it Example: ` # Delete a Helm release and the Kubernetes resources created by it
flux delete hr podinfo`, flux delete hr podinfo`,
ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)), ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)),

View File

@@ -19,7 +19,7 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
) )
var deleteImageUpdateCmd = &cobra.Command{ var deleteImageUpdateCmd = &cobra.Command{

View File

@@ -1,40 +0,0 @@
/*
Copyright 2024 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 main
import (
"github.com/spf13/cobra"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
)
var deleteSourceChartCmd = &cobra.Command{
Use: "chart [name]",
Short: "Delete a HelmChart source",
Long: "The delete source chart command deletes the given HelmChart from the cluster.",
Example: ` # Delete a HelmChart
flux delete source chart podinfo`,
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind)),
RunE: deleteCommand{
apiType: helmChartType,
object: universalAdapter{&sourcev1.HelmChart{}},
}.run,
}
func init() {
deleteSourceCmd.AddCommand(deleteSourceChartCmd)
}

View File

@@ -19,13 +19,13 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
) )
var deleteSourceHelmCmd = &cobra.Command{ var deleteSourceHelmCmd = &cobra.Command{
Use: "helm [name]", Use: "helm [name]",
Short: "Delete a HelmRepository source", Short: "Delete a HelmRepository source",
Long: "The delete source helm command deletes the given HelmRepository from the cluster.", Long: withPreviewNote("The delete source helm command deletes the given HelmRepository from the cluster."),
Example: ` # Delete a Helm repository Example: ` # Delete a Helm repository
flux delete source helm podinfo`, flux delete source helm podinfo`,
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)), ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)),

View File

@@ -23,9 +23,8 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
"github.com/fluxcd/flux2/v2/internal/build" "github.com/fluxcd/flux2/v2/internal/build"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
) )
var diffKsCmd = &cobra.Command{ var diffKsCmd = &cobra.Command{
@@ -54,7 +53,6 @@ type diffKsFlags struct {
path string path string
ignorePaths []string ignorePaths []string
progressBar bool progressBar bool
strictSubst bool
} }
var diffKsArgs diffKsFlags var diffKsArgs diffKsFlags
@@ -64,8 +62,6 @@ func init() {
diffKsCmd.Flags().BoolVar(&diffKsArgs.progressBar, "progress-bar", true, "Boolean to set the progress bar. The default value is true.") diffKsCmd.Flags().BoolVar(&diffKsArgs.progressBar, "progress-bar", true, "Boolean to set the progress bar. The default value is true.")
diffKsCmd.Flags().StringSliceVar(&diffKsArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore in .gitignore format") diffKsCmd.Flags().StringSliceVar(&diffKsArgs.ignorePaths, "ignore-paths", nil, "set paths to ignore in .gitignore format")
diffKsCmd.Flags().StringVar(&diffKsArgs.kustomizationFile, "kustomization-file", "", "Path to the Flux Kustomization YAML file.") diffKsCmd.Flags().StringVar(&diffKsArgs.kustomizationFile, "kustomization-file", "", "Path to the Flux Kustomization YAML file.")
diffKsCmd.Flags().BoolVar(&diffKsArgs.strictSubst, "strict-substitute", false,
"When enabled, the post build substitutions will fail if a var without a default value is declared in files but is missing from the input vars.")
diffCmd.AddCommand(diffKsCmd) diffCmd.AddCommand(diffKsCmd)
} }
@@ -100,7 +96,6 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
build.WithKustomizationFile(diffKsArgs.kustomizationFile), build.WithKustomizationFile(diffKsArgs.kustomizationFile),
build.WithProgressBar(), build.WithProgressBar(),
build.WithIgnore(diffKsArgs.ignorePaths), build.WithIgnore(diffKsArgs.ignorePaths),
build.WithStrictSubstitute(diffKsArgs.strictSubst),
) )
} else { } else {
builder, err = build.NewBuilder(name, diffKsArgs.path, builder, err = build.NewBuilder(name, diffKsArgs.path,
@@ -108,7 +103,6 @@ func diffKsCmdRun(cmd *cobra.Command, args []string) error {
build.WithTimeout(rootArgs.timeout), build.WithTimeout(rootArgs.timeout),
build.WithKustomizationFile(diffKsArgs.kustomizationFile), build.WithKustomizationFile(diffKsArgs.kustomizationFile),
build.WithIgnore(diffKsArgs.ignorePaths), build.WithIgnore(diffKsArgs.ignorePaths),
build.WithStrictSubstitute(diffKsArgs.strictSubst),
) )
} }

View File

@@ -1,74 +0,0 @@
/*
Copyright 2024 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 main
import (
"bufio"
"fmt"
"github.com/fluxcd/pkg/envsubst"
"github.com/spf13/cobra"
)
var envsubstCmd = &cobra.Command{
Use: "envsubst",
Args: cobra.NoArgs,
Short: "envsubst substitutes the values of environment variables",
Long: withPreviewNote(`The envsubst command substitutes the values of environment variables
in the string piped as standard input and writes the result to the standard output. This command can be used
to replicate the behavior of the Flux Kustomization post-build substitutions.`),
Example: ` # Run env var substitutions on the kustomization build output
export cluster_region=eu-central-1
kustomize build . | flux envsubst
# Run env var substitutions and error out if a variable is not set
kustomize build . | flux envsubst --strict
`,
RunE: runEnvsubstCmd,
}
type envsubstFlags struct {
strict bool
}
var envsubstArgs envsubstFlags
func init() {
envsubstCmd.Flags().BoolVar(&envsubstArgs.strict, "strict", false,
"fail if a variable without a default value is declared in the input but is missing from the environment")
rootCmd.AddCommand(envsubstCmd)
}
func runEnvsubstCmd(cmd *cobra.Command, args []string) error {
stdin := bufio.NewScanner(rootCmd.InOrStdin())
stdout := bufio.NewWriter(rootCmd.OutOrStdout())
for stdin.Scan() {
line, err := envsubst.EvalEnv(stdin.Text(), envsubstArgs.strict)
if err != nil {
return err
}
_, err = fmt.Fprintln(stdout, line)
if err != nil {
return err
}
err = stdout.Flush()
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,50 +0,0 @@
/*
Copyright 2024 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 main
import (
"bytes"
"os"
"testing"
. "github.com/onsi/gomega"
)
func TestEnvsubst(t *testing.T) {
g := NewWithT(t)
input, err := os.ReadFile("testdata/envsubst/file.yaml")
g.Expect(err).NotTo(HaveOccurred())
t.Setenv("REPO_NAME", "test")
output, err := executeCommandWithIn("envsubst", bytes.NewReader(input))
g.Expect(err).NotTo(HaveOccurred())
expected, err := os.ReadFile("testdata/envsubst/file.gold")
g.Expect(err).NotTo(HaveOccurred())
g.Expect(output).To(Equal(string(expected)))
}
func TestEnvsubst_Strinct(t *testing.T) {
g := NewWithT(t)
input, err := os.ReadFile("testdata/envsubst/file.yaml")
g.Expect(err).NotTo(HaveOccurred())
_, err = executeCommandWithIn("envsubst --strict", bytes.NewReader(input))
g.Expect(err).To(HaveOccurred())
g.Expect(err.Error()).To(ContainSubstring("variable not set (strict mode)"))
}

View File

@@ -39,8 +39,8 @@ import (
cmdutil "k8s.io/kubectl/pkg/cmd/util" cmdutil "k8s.io/kubectl/pkg/cmd/util"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
notificationv1 "github.com/fluxcd/notification-controller/api/v1" notificationv1 "github.com/fluxcd/notification-controller/api/v1"
@@ -422,7 +422,7 @@ var fluxKindMap = refMap{
gvk: helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind), gvk: helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind),
crossNamespaced: true, crossNamespaced: true,
otherRefs: func(namespace, name string) []string { otherRefs: func(namespace, name string) []string {
return []string{fmt.Sprintf("%s/%s-%s", sourcev1.HelmChartKind, namespace, name)} return []string{fmt.Sprintf("%s/%s-%s", sourcev1b2.HelmChartKind, namespace, name)}
}, },
field: []string{"spec", "chart", "spec", "sourceRef"}, field: []string{"spec", "chart", "spec", "sourceRef"},
}, },
@@ -440,15 +440,15 @@ var fluxKindMap = refMap{
crossNamespaced: true, crossNamespaced: true,
field: []string{"spec", "imageRepositoryRef"}, field: []string{"spec", "imageRepositoryRef"},
}, },
sourcev1.HelmChartKind: { sourcev1b2.HelmChartKind: {
gvk: sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind), gvk: sourcev1b2.GroupVersion.WithKind(sourcev1b2.HelmChartKind),
crossNamespaced: true, crossNamespaced: true,
field: []string{"spec", "sourceRef"}, field: []string{"spec", "sourceRef"},
}, },
sourcev1.GitRepositoryKind: {gvk: sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)}, sourcev1.GitRepositoryKind: {gvk: sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)},
sourcev1b2.OCIRepositoryKind: {gvk: sourcev1b2.GroupVersion.WithKind(sourcev1b2.OCIRepositoryKind)}, sourcev1b2.OCIRepositoryKind: {gvk: sourcev1b2.GroupVersion.WithKind(sourcev1b2.OCIRepositoryKind)},
sourcev1b2.BucketKind: {gvk: sourcev1b2.GroupVersion.WithKind(sourcev1b2.BucketKind)}, sourcev1b2.BucketKind: {gvk: sourcev1b2.GroupVersion.WithKind(sourcev1b2.BucketKind)},
sourcev1.HelmRepositoryKind: {gvk: sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)}, sourcev1b2.HelmRepositoryKind: {gvk: sourcev1b2.GroupVersion.WithKind(sourcev1b2.HelmRepositoryKind)},
autov1.ImageUpdateAutomationKind: {gvk: autov1.GroupVersion.WithKind(autov1.ImageUpdateAutomationKind)}, autov1.ImageUpdateAutomationKind: {gvk: autov1.GroupVersion.WithKind(autov1.ImageUpdateAutomationKind)},
imagev1.ImageRepositoryKind: {gvk: imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)}, imagev1.ImageRepositoryKind: {gvk: imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)},
} }

View File

@@ -31,7 +31,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/client/fake"
eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1" eventv1 "github.com/fluxcd/pkg/apis/event/v1beta1"
ssautil "github.com/fluxcd/pkg/ssa/utils" "github.com/fluxcd/pkg/ssa"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
) )
@@ -78,7 +78,7 @@ spec:
timeout: 1m0s timeout: 1m0s
url: ssh://git@github.com/example/repo url: ssh://git@github.com/example/repo
--- ---
apiVersion: helm.toolkit.fluxcd.io/v2 apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease kind: HelmRelease
metadata: metadata:
name: podinfo name: podinfo
@@ -95,7 +95,7 @@ spec:
version: '*' version: '*'
interval: 5m0s interval: 5m0s
--- ---
apiVersion: source.toolkit.fluxcd.io/v1 apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmRepository kind: HelmRepository
metadata: metadata:
name: podinfo name: podinfo
@@ -104,7 +104,7 @@ spec:
interval: 1m0s interval: 1m0s
url: https://stefanprodan.github.io/podinfo url: https://stefanprodan.github.io/podinfo
--- ---
apiVersion: source.toolkit.fluxcd.io/v1 apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: HelmChart kind: HelmChart
metadata: metadata:
name: default-podinfo name: default-podinfo
@@ -160,7 +160,7 @@ metadata:
func Test_getObjectRef(t *testing.T) { func Test_getObjectRef(t *testing.T) {
g := NewWithT(t) g := NewWithT(t)
objs, err := ssautil.ReadObjects(strings.NewReader(objects)) objs, err := ssa.ReadObjects(strings.NewReader(objects))
g.Expect(err).To(Not(HaveOccurred())) g.Expect(err).To(Not(HaveOccurred()))
builder := fake.NewClientBuilder().WithScheme(utils.NewScheme()) builder := fake.NewClientBuilder().WithScheme(utils.NewScheme())
@@ -244,7 +244,7 @@ func Test_getObjectRef(t *testing.T) {
func Test_getRows(t *testing.T) { func Test_getRows(t *testing.T) {
g := NewWithT(t) g := NewWithT(t)
objs, err := ssautil.ReadObjects(strings.NewReader(objects)) objs, err := ssa.ReadObjects(strings.NewReader(objects))
g.Expect(err).To(Not(HaveOccurred())) g.Expect(err).To(Not(HaveOccurred()))
builder := fake.NewClientBuilder().WithScheme(utils.NewScheme()) builder := fake.NewClientBuilder().WithScheme(utils.NewScheme())

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2024 The Flux authors Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -20,14 +20,14 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
) )
var exportHelmReleaseCmd = &cobra.Command{ var exportHelmReleaseCmd = &cobra.Command{
Use: "helmrelease [name]", Use: "helmrelease [name]",
Aliases: []string{"hr"}, Aliases: []string{"hr"},
Short: "Export HelmRelease resources in YAML format", Short: "Export HelmRelease resources in YAML format",
Long: "The export helmrelease command exports one or all HelmRelease resources in YAML format.", Long: withPreviewNote("The export helmrelease command exports one or all HelmRelease resources in YAML format."),
Example: ` # Export all HelmRelease resources Example: ` # Export all HelmRelease resources
flux export helmrelease --all > kustomizations.yaml flux export helmrelease --all > kustomizations.yaml

View File

@@ -20,7 +20,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
) )
var exportImageUpdateCmd = &cobra.Command{ var exportImageUpdateCmd = &cobra.Command{

View File

@@ -1,67 +0,0 @@
/*
Copyright 2024 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 main
import (
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
)
var exportSourceChartCmd = &cobra.Command{
Use: "chart [name]",
Short: "Export HelmChart sources in YAML format",
Long: withPreviewNote("The export source chart command exports one or all HelmChart sources in YAML format."),
Example: ` # Export all chart sources
flux export source chart --all > sources.yaml`,
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind)),
RunE: exportCommand{
list: helmChartListAdapter{&sourcev1.HelmChartList{}},
object: helmChartAdapter{&sourcev1.HelmChart{}},
}.run,
}
func init() {
exportSourceCmd.AddCommand(exportSourceChartCmd)
}
func exportHelmChart(source *sourcev1.HelmChart) interface{} {
gvk := sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind)
export := sourcev1.HelmChart{
TypeMeta: metav1.TypeMeta{
Kind: gvk.Kind,
APIVersion: gvk.GroupVersion().String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: source.Name,
Namespace: source.Namespace,
Labels: source.Labels,
Annotations: source.Annotations,
},
Spec: source.Spec,
}
return export
}
func (ex helmChartAdapter) export() interface{} {
return exportHelmChart(ex.HelmChart)
}
func (ex helmChartListAdapter) exportItem(i int) interface{} {
return exportHelmChart(&ex.HelmChartList.Items[i])
}

View File

@@ -21,13 +21,13 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
) )
var exportSourceHelmCmd = &cobra.Command{ var exportSourceHelmCmd = &cobra.Command{
Use: "helm [name]", Use: "helm [name]",
Short: "Export HelmRepository sources in YAML format", Short: "Export HelmRepository sources in YAML format",
Long: "The export source git command exports one or all HelmRepository sources in YAML format.", Long: withPreviewNote("The export source git command exports one or all HelmRepository sources in YAML format."),
Example: ` # Export all HelmRepository sources Example: ` # Export all HelmRepository sources
flux export source helm --all > sources.yaml flux export source helm --all > sources.yaml

View File

@@ -58,12 +58,6 @@ func TestExport(t *testing.T) {
"testdata/export/git-repo.yaml", "testdata/export/git-repo.yaml",
tmpl, tmpl,
}, },
{
"source chart",
"export source chart flux-system",
"testdata/export/helm-chart.yaml",
tmpl,
},
{ {
"source helm", "source helm",
"export source helm flux-system", "export source helm flux-system",

View File

@@ -18,6 +18,7 @@ package main
import ( import (
"context" "context"
"errors"
"fmt" "fmt"
"os" "os"
"strings" "strings"
@@ -27,6 +28,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
watchtools "k8s.io/client-go/tools/watch" watchtools "k8s.io/client-go/tools/watch"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
@@ -176,7 +178,8 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
err = kubeClient.List(ctx, get.list.asClientList(), listOpts...) err = kubeClient.List(ctx, get.list.asClientList(), listOpts...)
if err != nil { if err != nil {
if getAll && apimeta.IsNoMatchError(err) { var discErr *discovery.ErrGroupDiscoveryFailed
if getAll && (strings.Contains(err.Error(), "no matches for kind") || errors.As(err, &discErr)) {
return nil return nil
} }
return err return err

View File

@@ -17,10 +17,11 @@ limitations under the License.
package main package main
import ( import (
"github.com/spf13/cobra" "strings"
apimeta "k8s.io/apimachinery/pkg/api/meta"
helmv2 "github.com/fluxcd/helm-controller/api/v2" "github.com/spf13/cobra"
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
notificationv1 "github.com/fluxcd/notification-controller/api/v1" notificationv1 "github.com/fluxcd/notification-controller/api/v1"
notificationv1b3 "github.com/fluxcd/notification-controller/api/v1beta3" notificationv1b3 "github.com/fluxcd/notification-controller/api/v1beta3"
@@ -86,7 +87,7 @@ var getAllCmd = &cobra.Command{
} }
func logError(err error) { func logError(err error) {
if !apimeta.IsNoMatchError(err) { if !strings.Contains(err.Error(), "no matches for kind") {
logger.Failuref(err.Error()) logger.Failuref(err.Error())
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2024 The Flux authors Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -25,14 +25,14 @@ import (
"golang.org/x/text/language" "golang.org/x/text/language"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
) )
var getHelmReleaseCmd = &cobra.Command{ var getHelmReleaseCmd = &cobra.Command{
Use: "helmreleases", Use: "helmreleases",
Aliases: []string{"hr", "helmrelease"}, Aliases: []string{"hr", "helmrelease"},
Short: "Get HelmRelease statuses", Short: "Get HelmRelease statuses",
Long: "The get helmreleases command prints the statuses of the resources.", Long: withPreviewNote("The get helmreleases command prints the statuses of the resources."),
Example: ` # List all Helm releases and their status Example: ` # List all Helm releases and their status
flux get helmreleases`, flux get helmreleases`,
ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)), ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)),
@@ -72,16 +72,9 @@ func init() {
getCmd.AddCommand(getHelmReleaseCmd) getCmd.AddCommand(getHelmReleaseCmd)
} }
func getHelmReleaseRevision(helmRelease helmv2.HelmRelease) string {
if helmRelease.Status.History != nil && len(helmRelease.Status.History) > 0 {
return helmRelease.Status.History[0].ChartVersion
}
return helmRelease.Status.LastAttemptedRevision
}
func (a helmReleaseListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string { func (a helmReleaseListAdapter) summariseItem(i int, includeNamespace bool, includeKind bool) []string {
item := a.Items[i] item := a.Items[i]
revision := getHelmReleaseRevision(item) revision := item.Status.LastAppliedRevision
status, msg := statusAndMessage(item.Status.Conditions) status, msg := statusAndMessage(item.Status.Conditions)
return append(nameColumns(&item, includeNamespace, includeKind), return append(nameColumns(&item, includeNamespace, includeKind),
revision, cases.Title(language.English).String(strconv.FormatBool(item.Spec.Suspend)), status, msg) revision, cases.Title(language.English).String(strconv.FormatBool(item.Spec.Suspend)), status, msg)

View File

@@ -19,7 +19,7 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2"
) )

View File

@@ -26,7 +26,7 @@ import (
"golang.org/x/text/language" "golang.org/x/text/language"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
) )
var getImageUpdateCmd = &cobra.Command{ var getImageUpdateCmd = &cobra.Command{

View File

@@ -17,8 +17,9 @@ limitations under the License.
package main package main
import ( import (
"strings"
"github.com/spf13/cobra" "github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1"
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2" sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2"
@@ -54,17 +55,17 @@ var getSourceAllCmd = &cobra.Command{
}, },
{ {
apiType: helmRepositoryType, apiType: helmRepositoryType,
list: &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}}, list: &helmRepositoryListAdapter{&sourcev1b2.HelmRepositoryList{}},
}, },
{ {
apiType: helmChartType, apiType: helmChartType,
list: &helmChartListAdapter{&sourcev1.HelmChartList{}}, list: &helmChartListAdapter{&sourcev1b2.HelmChartList{}},
}, },
} }
for _, c := range allSourceCmd { for _, c := range allSourceCmd {
if err := c.run(cmd, args); err != nil { if err := c.run(cmd, args); err != nil {
if !apimeta.IsNoMatchError(err) { if !strings.Contains(err.Error(), "no matches for kind") {
logger.Failuref(err.Error()) logger.Failuref(err.Error())
} }
} }

View File

@@ -25,7 +25,7 @@ import (
"golang.org/x/text/language" "golang.org/x/text/language"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
) )
@@ -33,7 +33,7 @@ import (
var getSourceHelmChartCmd = &cobra.Command{ var getSourceHelmChartCmd = &cobra.Command{
Use: "chart", Use: "chart",
Short: "Get HelmChart statuses", Short: "Get HelmChart statuses",
Long: "The get sources chart command prints the status of the HelmCharts.", Long: withPreviewNote("The get sources chart command prints the status of the HelmCharts."),
Example: ` # List all Helm charts and their status Example: ` # List all Helm charts and their status
flux get sources chart flux get sources chart

View File

@@ -26,7 +26,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
) )
@@ -34,7 +34,7 @@ import (
var getSourceHelmCmd = &cobra.Command{ var getSourceHelmCmd = &cobra.Command{
Use: "helm", Use: "helm",
Short: "Get HelmRepository source statuses", Short: "Get HelmRepository source statuses",
Long: "The get sources helm command prints the status of the HelmRepository sources.", Long: withPreviewNote("The get sources helm command prints the status of the HelmRepository sources."),
Example: ` # List all Helm repositories and their status Example: ` # List all Helm repositories and their status
flux get sources helm flux get sources helm

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2024 The Flux authors Copyright 2021 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ package main
import ( import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
) )
// helmv2.HelmRelease // helmv2.HelmRelease

View File

@@ -19,7 +19,7 @@ package main
import ( import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2"
) )

View File

@@ -21,20 +21,16 @@ import (
"fmt" "fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"time" "time"
"github.com/manifoldco/promptui" "github.com/manifoldco/promptui"
"github.com/spf13/cobra" "github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/yaml"
"github.com/fluxcd/flux2/v2/internal/flags" "github.com/fluxcd/flux2/v2/internal/flags"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/flux2/v2/pkg/manifestgen" "github.com/fluxcd/flux2/v2/pkg/manifestgen"
"github.com/fluxcd/flux2/v2/pkg/manifestgen/install" "github.com/fluxcd/flux2/v2/pkg/manifestgen/install"
"github.com/fluxcd/flux2/v2/pkg/manifestgen/sourcesecret"
"github.com/fluxcd/flux2/v2/pkg/status" "github.com/fluxcd/flux2/v2/pkg/status"
) )
@@ -70,7 +66,6 @@ type installFlags struct {
defaultComponents []string defaultComponents []string
extraComponents []string extraComponents []string
registry string registry string
registryCredential string
imagePullSecret string imagePullSecret string
branch string branch string
watchAllNamespaces bool watchAllNamespaces bool
@@ -97,8 +92,6 @@ func init() {
installCmd.Flags().StringVar(&installArgs.manifestsPath, "manifests", "", "path to the manifest directory") installCmd.Flags().StringVar(&installArgs.manifestsPath, "manifests", "", "path to the manifest directory")
installCmd.Flags().StringVar(&installArgs.registry, "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(&installArgs.registryCredential, "registry-creds", "",
"container registry credentials in the format 'user:password', requires --image-pull-secret to be set")
installCmd.Flags().StringVar(&installArgs.imagePullSecret, "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().BoolVar(&installArgs.watchAllNamespaces, "watch-all-namespaces", rootArgs.defaults.WatchAllNamespaces, installCmd.Flags().BoolVar(&installArgs.watchAllNamespaces, "watch-all-namespaces", rootArgs.defaults.WatchAllNamespaces,
@@ -109,7 +102,7 @@ func init() {
installCmd.Flags().StringVar(&installArgs.clusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain") installCmd.Flags().StringVar(&installArgs.clusterDomain, "cluster-domain", rootArgs.defaults.ClusterDomain, "internal cluster domain")
installCmd.Flags().StringSliceVar(&installArgs.tolerationKeys, "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().BoolVar(&installArgs.force, "force", false, "override existing Flux installation if it's managed by a different tool such as Helm") installCmd.Flags().BoolVar(&installArgs.force, "force", false, "override existing Flux installation if it's managed by a diffrent tool such as Helm")
installCmd.Flags().MarkHidden("manifests") installCmd.Flags().MarkHidden("manifests")
rootCmd.AddCommand(installCmd) rootCmd.AddCommand(installCmd)
@@ -131,14 +124,6 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
if installArgs.registryCredential != "" && installArgs.imagePullSecret == "" {
return fmt.Errorf("--registry-creds requires --image-pull-secret to be set")
}
if installArgs.registryCredential != "" && len(strings.Split(installArgs.registryCredential, ":")) != 2 {
return fmt.Errorf("invalid --registry-creds format, expected 'user:password'")
}
if ver, err := getVersion(installArgs.version); err != nil { if ver, err := getVersion(installArgs.version); err != nil {
return err return err
} else { } else {
@@ -169,7 +154,6 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
Namespace: *kubeconfigArgs.Namespace, Namespace: *kubeconfigArgs.Namespace,
Components: components, Components: components,
Registry: installArgs.registry, Registry: installArgs.registry,
RegistryCredential: installArgs.registryCredential,
ImagePullSecret: installArgs.imagePullSecret, ImagePullSecret: installArgs.imagePullSecret,
WatchAllNamespaces: installArgs.watchAllNamespaces, WatchAllNamespaces: installArgs.watchAllNamespaces,
NetworkPolicy: installArgs.networkPolicy, NetworkPolicy: installArgs.networkPolicy,
@@ -240,29 +224,6 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
fmt.Fprintln(os.Stderr, applyOutput) fmt.Fprintln(os.Stderr, applyOutput)
if opts.ImagePullSecret != "" && opts.RegistryCredential != "" {
logger.Actionf("generating image pull secret %s", opts.ImagePullSecret)
credentials := strings.SplitN(opts.RegistryCredential, ":", 2)
secretOpts := sourcesecret.Options{
Name: opts.ImagePullSecret,
Namespace: opts.Namespace,
Registry: opts.Registry,
Username: credentials[0],
Password: credentials[1],
}
imagePullSecret, err := sourcesecret.Generate(secretOpts)
if err != nil {
return fmt.Errorf("install failed: %w", err)
}
var s corev1.Secret
if err := yaml.Unmarshal([]byte(imagePullSecret.Content), &s); err != nil {
return fmt.Errorf("install failed: %w", err)
}
if err := upsertSecret(ctx, kubeClient, s); err != nil {
return fmt.Errorf("install failed: %w", err)
}
}
kubeConfig, err := utils.KubeConfig(kubeconfigArgs, kubeclientOptions) kubeConfig, err := utils.KubeConfig(kubeconfigArgs, kubeclientOptions)
if err != nil { if err != nil {
return fmt.Errorf("install failed: %w", err) return fmt.Errorf("install failed: %w", err)

View File

@@ -42,11 +42,6 @@ func TestInstall(t *testing.T) {
args: "install unexpectedPosArg --namespace=example", args: "install unexpectedPosArg --namespace=example",
assert: assertError(`unknown command "unexpectedPosArg" for "flux install"`), assert: assertError(`unknown command "unexpectedPosArg" for "flux install"`),
}, },
{
name: "missing image pull secret",
args: "install --registry-creds=fluxcd:test",
assert: assertError(`--registry-creds requires --image-pull-secret to be set`),
},
} }
for _, tt := range tests { for _, tt := range tests {

View File

@@ -31,6 +31,7 @@ import (
"text/template" "text/template"
"time" "time"
"github.com/fluxcd/flux2/v2/internal/utils"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/mattn/go-shellwords" "github.com/mattn/go-shellwords"
"k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/errors"
@@ -39,8 +40,6 @@ import (
"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/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/envtest"
"github.com/fluxcd/flux2/v2/internal/utils"
) )
var nextNamespaceId int64 var nextNamespaceId int64
@@ -394,29 +393,6 @@ func executeCommand(cmd string) (string, error) {
return result, err return result, err
} }
// Run the command while passing the string as input and return the captured output.
func executeCommandWithIn(cmd string, in io.Reader) (string, error) {
defer resetCmdArgs()
args, err := shellwords.Parse(cmd)
if err != nil {
return "", err
}
buf := new(bytes.Buffer)
rootCmd.SetOut(buf)
rootCmd.SetErr(buf)
rootCmd.SetArgs(args)
if in != nil {
rootCmd.SetIn(in)
}
_, err = rootCmd.ExecuteC()
result := buf.String()
return result, err
}
// resetCmdArgs resets the flags for various cmd // resetCmdArgs resets the flags for various cmd
// Note: this will also clear default value of the flags set in init() // Note: this will also clear default value of the flags set in init()
func resetCmdArgs() { func resetCmdArgs() {
@@ -465,7 +441,7 @@ func resetCmdArgs() {
versionArgs = versionFlags{ versionArgs = versionFlags{
output: "yaml", output: "yaml",
} }
envsubstArgs = envsubstFlags{}
} }
func isChangeError(err error) bool { func isChangeError(err error) bool {

View File

@@ -114,7 +114,6 @@ type pushArtifactFlags struct {
annotations []string annotations []string
output string output string
debug bool debug bool
reproducible bool
} }
var pushArtifactArgs = newPushArtifactFlags() var pushArtifactArgs = newPushArtifactFlags()
@@ -136,7 +135,6 @@ func init() {
pushArtifactCmd.Flags().StringVarP(&pushArtifactArgs.output, "output", "o", "", pushArtifactCmd.Flags().StringVarP(&pushArtifactArgs.output, "output", "o", "",
"the format in which the artifact digest should be printed, can be 'json' or 'yaml'") "the format in which the artifact digest should be printed, can be 'json' or 'yaml'")
pushArtifactCmd.Flags().BoolVarP(&pushArtifactArgs.debug, "debug", "", false, "display logs from underlying library") pushArtifactCmd.Flags().BoolVarP(&pushArtifactArgs.debug, "debug", "", false, "display logs from underlying library")
pushArtifactCmd.Flags().BoolVar(&pushArtifactArgs.reproducible, "reproducible", false, "ensure reproducible image digests by setting the created timestamp to '1970-01-01T00:00:00Z'")
pushCmd.AddCommand(pushArtifactCmd) pushCmd.AddCommand(pushArtifactCmd)
} }
@@ -204,11 +202,6 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
Annotations: annotations, Annotations: annotations,
} }
if pushArtifactArgs.reproducible {
zeroTime := time.Unix(0, 0)
meta.Created = zeroTime.Format(time.RFC3339)
}
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel() defer cancel()

View File

@@ -31,7 +31,6 @@ import (
"k8s.io/client-go/util/retry" "k8s.io/client-go/util/retry"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
helmv2 "github.com/fluxcd/helm-controller/api/v2"
"github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
@@ -167,26 +166,14 @@ func requestReconciliation(ctx context.Context, kubeClient client.Client,
return err return err
} }
patch := client.MergeFrom(object.DeepCopy()) patch := client.MergeFrom(object.DeepCopy())
if ann := object.GetAnnotations(); ann == nil {
// Add a timestamp annotation to trigger a reconciliation. object.SetAnnotations(map[string]string{
ts := time.Now().Format(time.RFC3339Nano) meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano),
annotations := object.GetAnnotations() })
if annotations == nil { } else {
annotations = make(map[string]string, 1) ann[meta.ReconcileRequestAnnotation] = time.Now().Format(time.RFC3339Nano)
object.SetAnnotations(ann)
} }
annotations[meta.ReconcileRequestAnnotation] = ts
// HelmRelease specific annotations to force or reset a release.
if gvk.Kind == helmv2.HelmReleaseKind {
if rhrArgs.syncForce {
annotations[helmv2.ForceRequestAnnotation] = ts
}
if rhrArgs.syncReset {
annotations[helmv2.ResetRequestAnnotation] = ts
}
}
object.SetAnnotations(annotations)
return kubeClient.Patch(ctx, object, patch) return kubeClient.Patch(ctx, object, patch)
}) })
} }

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2024 The Flux authors Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -22,8 +22,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
sourcev1 "github.com/fluxcd/source-controller/api/v1"
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2" sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2"
) )
@@ -47,16 +46,13 @@ The reconcile kustomization command triggers a reconciliation of a HelmRelease r
type reconcileHelmReleaseFlags struct { type reconcileHelmReleaseFlags struct {
syncHrWithSource bool syncHrWithSource bool
syncForce bool
syncReset bool
} }
var rhrArgs reconcileHelmReleaseFlags var rhrArgs reconcileHelmReleaseFlags
func init() { func init() {
reconcileHrCmd.Flags().BoolVar(&rhrArgs.syncHrWithSource, "with-source", false, "reconcile HelmRelease source") reconcileHrCmd.Flags().BoolVar(&rhrArgs.syncHrWithSource, "with-source", false, "reconcile HelmRelease source")
reconcileHrCmd.Flags().BoolVar(&rhrArgs.syncForce, "force", false, "force a one-off install or upgrade of the HelmRelease resource")
reconcileHrCmd.Flags().BoolVar(&rhrArgs.syncReset, "reset", false, "reset the failure count for this HelmRelease resource")
reconcileCmd.AddCommand(reconcileHrCmd) reconcileCmd.AddCommand(reconcileHrCmd)
} }
@@ -69,47 +65,21 @@ func (obj helmReleaseAdapter) reconcileSource() bool {
} }
func (obj helmReleaseAdapter) getSource() (reconcileSource, types.NamespacedName) { func (obj helmReleaseAdapter) getSource() (reconcileSource, types.NamespacedName) {
var ( cmd := reconcileWithSourceCommand{
name string apiType: helmChartType,
ns string object: helmChartAdapter{&sourcev1b2.HelmChart{}},
) force: true,
switch { }
case obj.Spec.ChartRef != nil:
name, ns = obj.Spec.ChartRef.Name, obj.Spec.ChartRef.Namespace ns := obj.Spec.Chart.Spec.SourceRef.Namespace
if ns == "" { if ns == "" {
ns = obj.Namespace ns = obj.Namespace
} }
namespacedName := types.NamespacedName{
Name: name, return cmd, types.NamespacedName{
Name: fmt.Sprintf("%s-%s", obj.Namespace, obj.Name),
Namespace: ns, Namespace: ns,
} }
if obj.Spec.ChartRef.Kind == sourcev1.HelmChartKind {
return reconcileWithSourceCommand{
apiType: helmChartType,
object: helmChartAdapter{&sourcev1.HelmChart{}},
force: true,
}, namespacedName
}
return reconcileCommand{
apiType: ociRepositoryType,
object: ociRepositoryAdapter{&sourcev1b2.OCIRepository{}},
}, namespacedName
default:
// default case assumes the HelmRelease is using a HelmChartTemplate
ns = obj.Spec.Chart.Spec.SourceRef.Namespace
if ns == "" {
ns = obj.Namespace
}
name = fmt.Sprintf("%s-%s", obj.Namespace, obj.Name)
return reconcileWithSourceCommand{
apiType: helmChartType,
object: helmChartAdapter{&sourcev1.HelmChart{}},
force: true,
}, types.NamespacedName{
Name: name,
Namespace: ns,
}
}
} }
func (obj helmReleaseAdapter) isStatic() bool { func (obj helmReleaseAdapter) isStatic() bool {

View File

@@ -22,7 +22,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta" apimeta "k8s.io/apimachinery/pkg/api/meta"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
meta "github.com/fluxcd/pkg/apis/meta" meta "github.com/fluxcd/pkg/apis/meta"
) )

View File

@@ -33,10 +33,10 @@ var reconcileSourceHelmChartCmd = &cobra.Command{
# Trigger a reconciliation of the HelmCharts's source and apply changes # Trigger a reconciliation of the HelmCharts's source and apply changes
flux reconcile helmchart podinfo --with-source`, flux reconcile helmchart podinfo --with-source`,
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind)), ValidArgsFunction: resourceNamesCompletionFunc(sourcev1b2.GroupVersion.WithKind(sourcev1b2.HelmChartKind)),
RunE: reconcileWithSourceCommand{ RunE: reconcileWithSourceCommand{
apiType: helmChartType, apiType: helmChartType,
object: helmChartAdapter{&sourcev1.HelmChart{}}, object: helmChartAdapter{&sourcev1b2.HelmChart{}},
}.run, }.run,
} }
@@ -62,10 +62,10 @@ func (obj helmChartAdapter) reconcileSource() bool {
func (obj helmChartAdapter) getSource() (reconcileSource, types.NamespacedName) { func (obj helmChartAdapter) getSource() (reconcileSource, types.NamespacedName) {
var cmd reconcileCommand var cmd reconcileCommand
switch obj.Spec.SourceRef.Kind { switch obj.Spec.SourceRef.Kind {
case sourcev1.HelmRepositoryKind: case sourcev1b2.HelmRepositoryKind:
cmd = reconcileCommand{ cmd = reconcileCommand{
apiType: helmRepositoryType, apiType: helmRepositoryType,
object: helmRepositoryAdapter{&sourcev1.HelmRepository{}}, object: helmRepositoryAdapter{&sourcev1b2.HelmRepository{}},
} }
case sourcev1.GitRepositoryKind: case sourcev1.GitRepositoryKind:
cmd = reconcileCommand{ cmd = reconcileCommand{

View File

@@ -23,7 +23,7 @@ import (
"github.com/fluxcd/pkg/apis/meta" "github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/runtime/conditions" "github.com/fluxcd/pkg/runtime/conditions"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
) )
var reconcileSourceHelmCmd = &cobra.Command{ var reconcileSourceHelmCmd = &cobra.Command{

View File

@@ -10,9 +10,8 @@ import (
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/flux2/v2/internal/utils" "github.com/fluxcd/flux2/v2/internal/utils"
"github.com/fluxcd/pkg/apis/meta"
) )
type reconcileWithSource interface { type reconcileWithSource interface {

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2024 The Flux authors Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -21,7 +21,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
) )
var resumeHrCmd = &cobra.Command{ var resumeHrCmd = &cobra.Command{
@@ -55,7 +55,7 @@ func (obj helmReleaseAdapter) setUnsuspended() {
} }
func (obj helmReleaseAdapter) successMessage() string { func (obj helmReleaseAdapter) successMessage() string {
return fmt.Sprintf("applied revision %s", getHelmReleaseRevision(*obj.HelmRelease)) return fmt.Sprintf("applied revision %s", obj.Status.LastAppliedRevision)
} }
func (a helmReleaseListAdapter) resumeItem(i int) resumable { func (a helmReleaseListAdapter) resumeItem(i int) resumable {

View File

@@ -19,7 +19,7 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
) )
var resumeImageUpdateCmd = &cobra.Command{ var resumeImageUpdateCmd = &cobra.Command{

View File

@@ -21,7 +21,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
) )
var resumeSourceHelmChartCmd = &cobra.Command{ var resumeSourceHelmChartCmd = &cobra.Command{

View File

@@ -19,7 +19,7 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
) )
var resumeSourceHelmCmd = &cobra.Command{ var resumeSourceHelmCmd = &cobra.Command{

View File

@@ -95,16 +95,16 @@ func (a bucketListAdapter) len() int {
return len(a.BucketList.Items) return len(a.BucketList.Items)
} }
// sourcev1.HelmChart // sourcev1b2.HelmChart
var helmChartType = apiType{ var helmChartType = apiType{
kind: sourcev1.HelmChartKind, kind: sourcev1b2.HelmChartKind,
humanKind: "source chart", humanKind: "source chart",
groupVersion: sourcev1.GroupVersion, groupVersion: sourcev1b2.GroupVersion,
} }
type helmChartAdapter struct { type helmChartAdapter struct {
*sourcev1.HelmChart *sourcev1b2.HelmChart
} }
func (a helmChartAdapter) asClientObject() client.Object { func (a helmChartAdapter) asClientObject() client.Object {
@@ -115,10 +115,10 @@ func (a helmChartAdapter) deepCopyClientObject() client.Object {
return a.HelmChart.DeepCopy() return a.HelmChart.DeepCopy()
} }
// sourcev1.HelmChartList // sourcev1b2.HelmChartList
type helmChartListAdapter struct { type helmChartListAdapter struct {
*sourcev1.HelmChartList *sourcev1b2.HelmChartList
} }
func (a helmChartListAdapter) asClientList() client.ObjectList { func (a helmChartListAdapter) asClientList() client.ObjectList {
@@ -163,16 +163,16 @@ func (a gitRepositoryListAdapter) len() int {
return len(a.GitRepositoryList.Items) return len(a.GitRepositoryList.Items)
} }
// sourcev1.HelmRepository // sourcev1b2.HelmRepository
var helmRepositoryType = apiType{ var helmRepositoryType = apiType{
kind: sourcev1.HelmRepositoryKind, kind: sourcev1b2.HelmRepositoryKind,
humanKind: "source helm", humanKind: "source helm",
groupVersion: sourcev1.GroupVersion, groupVersion: sourcev1b2.GroupVersion,
} }
type helmRepositoryAdapter struct { type helmRepositoryAdapter struct {
*sourcev1.HelmRepository *sourcev1b2.HelmRepository
} }
func (a helmRepositoryAdapter) asClientObject() client.Object { func (a helmRepositoryAdapter) asClientObject() client.Object {
@@ -183,10 +183,10 @@ func (a helmRepositoryAdapter) deepCopyClientObject() client.Object {
return a.HelmRepository.DeepCopy() return a.HelmRepository.DeepCopy()
} }
// sourcev1.HelmRepositoryList // sourcev1b2.HelmRepositoryList
type helmRepositoryListAdapter struct { type helmRepositoryListAdapter struct {
*sourcev1.HelmRepositoryList *sourcev1b2.HelmRepositoryList
} }
func (a helmRepositoryListAdapter) asClientList() client.ObjectList { func (a helmRepositoryListAdapter) asClientList() client.ObjectList {

View File

@@ -27,8 +27,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/cli-utils/pkg/kstatus/status" "github.com/fluxcd/cli-utils/pkg/kstatus/status"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2" imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta2"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1" kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1"
notificationv1 "github.com/fluxcd/notification-controller/api/v1" notificationv1 "github.com/fluxcd/notification-controller/api/v1"
@@ -42,7 +42,6 @@ import (
var statsCmd = &cobra.Command{ var statsCmd = &cobra.Command{
Use: "stats", Use: "stats",
Args: cobra.NoArgs,
Short: "Stats of Flux reconciles", Short: "Stats of Flux reconciles",
Long: withPreviewNote(`The stats command prints a report of Flux custom resources present on a cluster, Long: withPreviewNote(`The stats command prints a report of Flux custom resources present on a cluster,
including their reconcile status and the amount of cumulative storage used for each source type`), including their reconcile status and the amount of cumulative storage used for each source type`),
@@ -87,14 +86,14 @@ func runStatsCmd(cmd *cobra.Command, args []string) error {
Group: sourcev1b2.GroupVersion.Group, Group: sourcev1b2.GroupVersion.Group,
}, },
{ {
Kind: sourcev1.HelmRepositoryKind, Kind: sourcev1b2.HelmRepositoryKind,
Version: sourcev1.GroupVersion.Version, Version: sourcev1b2.GroupVersion.Version,
Group: sourcev1.GroupVersion.Group, Group: sourcev1b2.GroupVersion.Group,
}, },
{ {
Kind: sourcev1.HelmChartKind, Kind: sourcev1b2.HelmChartKind,
Version: sourcev1.GroupVersion.Version, Version: sourcev1b2.GroupVersion.Version,
Group: sourcev1.GroupVersion.Group, Group: sourcev1b2.GroupVersion.Group,
}, },
{ {
Kind: sourcev1b2.BucketKind, Kind: sourcev1b2.BucketKind,

View File

@@ -1,5 +1,5 @@
/* /*
Copyright 2024 The Flux authors Copyright 2020 The Flux authors
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@@ -19,7 +19,7 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
helmv2 "github.com/fluxcd/helm-controller/api/v2" helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
) )
var suspendHrCmd = &cobra.Command{ var suspendHrCmd = &cobra.Command{

View File

@@ -19,7 +19,7 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta2" autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
) )
var suspendImageUpdateCmd = &cobra.Command{ var suspendImageUpdateCmd = &cobra.Command{

View File

@@ -19,7 +19,7 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
) )
var suspendSourceHelmChartCmd = &cobra.Command{ var suspendSourceHelmChartCmd = &cobra.Command{

View File

@@ -19,7 +19,7 @@ package main
import ( import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
sourcev1 "github.com/fluxcd/source-controller/api/v1" sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
) )
var suspendSourceHelmCmd = &cobra.Command{ var suspendSourceHelmCmd = &cobra.Command{

View File

@@ -1,3 +1,3 @@
► checking prerequisites ► checking prerequisites
✔ Kubernetes {{ .serverVersion }} >=1.28.0-0 ✔ Kubernetes {{ .serverVersion }} >=1.25.0-0
✔ prerequisites checks passed ✔ prerequisites checks passed

View File

@@ -1,15 +0,0 @@
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
chart:
spec:
chart: podinfo
reconcileStrategy: ChartVersion
sourceRef:
kind: HelmRepository
name: podinfo
interval: 1m0s

View File

@@ -1,11 +0,0 @@
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
chartRef:
kind: HelmChart
name: podinfo
interval: 1m0s

View File

@@ -1,11 +0,0 @@
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
chartRef:
kind: OCIRepository
name: podinfo
interval: 1m0s

View File

@@ -1,39 +0,0 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: {{ .fluxns }}
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
interval: 1m0s
provider: generic
type: oci
url: oci://ghcr.io/stefanprodan/charts
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmChart
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
interval: 1m0s
chart: podinfo
sourceRef:
kind: HelmRepository
name: podinfo
---
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: OCIRepository
metadata:
name: podinfo
namespace: flux-system
spec:
interval: 10m
url: oci://ghcr.io/stefanprodan/manifests/podinfo
ref:
tag: latest

View File

@@ -1,4 +0,0 @@
{
"version": "1.0",
"trustPolicies": [{}]
}

View File

@@ -1 +0,0 @@
""

View File

@@ -1,28 +0,0 @@
---
apiVersion: v1
kind: Secret
metadata:
name: notation-config
namespace: my-namespace
stringData:
ca.crt: ca-data-crt
trustpolicy.json: |
{
"version": "1.0",
"trustPolicies": [
{
"name": "fluxcd.io",
"registryScopes": [
"*"
],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:fluxcd.io" ],
"trustedIdentities": [
"*"
]
}
]
}

View File

@@ -1,29 +0,0 @@
---
apiVersion: v1
kind: Secret
metadata:
name: notation-config
namespace: my-namespace
stringData:
ca.crt: ca-data-crt
ca.pem: ca-data-pem
trustpolicy.json: |
{
"version": "1.0",
"trustPolicies": [
{
"name": "fluxcd.io",
"registryScopes": [
"*"
],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:fluxcd.io" ],
"trustedIdentities": [
"*"
]
}
]
}

View File

@@ -1,28 +0,0 @@
---
apiVersion: v1
kind: Secret
metadata:
name: notation-config
namespace: my-namespace
stringData:
ca.pem: ca-data-pem
trustpolicy.json: |
{
"version": "1.0",
"trustPolicies": [
{
"name": "fluxcd.io",
"registryScopes": [
"*"
],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:fluxcd.io" ],
"trustedIdentities": [
"*"
]
}
]
}

View File

@@ -1,21 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDbDCCAlSgAwIBAgIUP7zhmTw5XTWLcgBGkBEsErMOkz4wDQYJKoZIhvcNAQEL
BQAwWjELMAkGA1UEBhMCUk8xCzAJBgNVBAgMAkJVMRIwEAYDVQQHDAlCdWNoYXJl
c3QxDzANBgNVBAoMBk5vdGFyeTEZMBcGA1UEAwwQc3RlZmFucHJvZGFuLmNvbTAe
Fw0yNDAyMjUxMDAyMzZaFw0yOTAyMjQxMDAyMzZaMFoxCzAJBgNVBAYTAlJPMQsw
CQYDVQQIDAJCVTESMBAGA1UEBwwJQnVjaGFyZXN0MQ8wDQYDVQQKDAZOb3Rhcnkx
GTAXBgNVBAMMEHN0ZWZhbnByb2Rhbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDtH4oPi3SyX/DGv6NdjIvmApvD9eeSgsmHdwpAly8T9D2me+fx
Z+wRNJmq4aq/A1anX+Sg28iwHzV+1WKpsHnjYzDAJSEYP2S8A5H1nGRKUoibdijw
C3QBh5C75rjF/tmZVSX/Vgbf3HJJEsF4WUxWabLxoV2QLo7UlEsQd9+bSeKNMncx
1+E6FdbRCrYo90iobvZJ8K/S2zCWq/JTeHfTnmSEDhx6nMJcaSjvMPn3zyauWcQw
dDpkcaGiJ64fEJRT2OFxXv9u+vDmIMKzo/Wjbd+IzFj6YY4VisK88aU7tmDelnk5
gQB9eu62PFoaVsYJp4VOhblFKvGJpQwbWB9BAgMBAAGjKjAoMA4GA1UdDwEB/wQE
AwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEA
6x+C6hAIbLwMvkNx4K5p7Qe/pLQR0VwQFAw10yr/5KSN+YKFpon6pQ0TebL7qll+
uBGZvtQhN6v+DlnVqB7lvJKd+89isgirkkews5KwuXg7Gv5UPIugH0dXISZU8DMJ
7J4oKREv5HzdFmfsUfNlQcfyVTjKL6UINXfKGdqNNxXxR9b4a1TY2JcmEhzBTHaq
ZqX6HK784a0dB7aHgeFrFwPCCP4M684Hs7CFbk3jo2Ef4ljnB5AyWpe8pwCLMdRt
UjSjL5xJWVQvRU+STQsPr6SvpokPCG4rLQyjgeYYk4CCj5piSxbSUZFavq8v1y7Y
m91USVqfeUX7ZzjDxPHE2A==
-----END CERTIFICATE-----

View File

@@ -1,21 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDbDCCAlSgAwIBAgIUP7zhmTw5XTWLcgBGkBEsErMOkz4wDQYJKoZIhvcNAQEL
BQAwWjELMAkGA1UEBhMCUk8xCzAJBgNVBAgMAkJVMRIwEAYDVQQHDAlCdWNoYXJl
c3QxDzANBgNVBAoMBk5vdGFyeTEZMBcGA1UEAwwQc3RlZmFucHJvZGFuLmNvbTAe
Fw0yNDAyMjUxMDAyMzZaFw0yOTAyMjQxMDAyMzZaMFoxCzAJBgNVBAYTAlJPMQsw
CQYDVQQIDAJCVTESMBAGA1UEBwwJQnVjaGFyZXN0MQ8wDQYDVQQKDAZOb3Rhcnkx
GTAXBgNVBAMMEHN0ZWZhbnByb2Rhbi5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQDtH4oPi3SyX/DGv6NdjIvmApvD9eeSgsmHdwpAly8T9D2me+fx
Z+wRNJmq4aq/A1anX+Sg28iwHzV+1WKpsHnjYzDAJSEYP2S8A5H1nGRKUoibdijw
C3QBh5C75rjF/tmZVSX/Vgbf3HJJEsF4WUxWabLxoV2QLo7UlEsQd9+bSeKNMncx
1+E6FdbRCrYo90iobvZJ8K/S2zCWq/JTeHfTnmSEDhx6nMJcaSjvMPn3zyauWcQw
dDpkcaGiJ64fEJRT2OFxXv9u+vDmIMKzo/Wjbd+IzFj6YY4VisK88aU7tmDelnk5
gQB9eu62PFoaVsYJp4VOhblFKvGJpQwbWB9BAgMBAAGjKjAoMA4GA1UdDwEB/wQE
AwIHgDAWBgNVHSUBAf8EDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEA
6x+C6hAIbLwMvkNx4K5p7Qe/pLQR0VwQFAw10yr/5KSN+YKFpon6pQ0TebL7qll+
uBGZvtQhN6v+DlnVqB7lvJKd+89isgirkkews5KwuXg7Gv5UPIugH0dXISZU8DMJ
7J4oKREv5HzdFmfsUfNlQcfyVTjKL6UINXfKGdqNNxXxR9b4a1TY2JcmEhzBTHaq
ZqX6HK784a0dB7aHgeFrFwPCCP4M684Hs7CFbk3jo2Ef4ljnB5AyWpe8pwCLMdRt
UjSjL5xJWVQvRU+STQsPr6SvpokPCG4rLQyjgeYYk4CCj5piSxbSUZFavq8v1y7Y
m91USVqfeUX7ZzjDxPHE2A==
-----END CERTIFICATE-----

View File

@@ -1,18 +0,0 @@
{
"version": "1.0",
"trustPolicies": [
{
"name": "fluxcd.io",
"registryScopes": [
"*"
],
"signatureVerification": {
"level" : "strict"
},
"trustStores": [ "ca:fluxcd.io" ],
"trustedIdentities": [
"*"
]
}
]
}

View File

@@ -1,14 +0,0 @@
✚ generating HelmChart source
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmChart
metadata:
name: podinfo
namespace: {{ .fluxns }}
spec:
chart: podinfo
interval: 0s
reconcileStrategy: ChartVersion
sourceRef:
kind: HelmRepository
name: podinfo

Some files were not shown because too many files have changed in this diff Show More