Compare commits
233 Commits
v2.0.0-rc.
...
release/v2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b66d15b3d1 | ||
|
|
1ecb6383bb | ||
|
|
a18d4f3450 | ||
|
|
95c5c5ab30 | ||
|
|
51532e75b2 | ||
|
|
cef3eef641 | ||
|
|
5e412ee73d | ||
|
|
b3e432cd8e | ||
|
|
62d65edddf | ||
|
|
47da5290ce | ||
|
|
23f9492707 | ||
|
|
cd16ff4aa4 | ||
|
|
a0d2c2520c | ||
|
|
026ab61ba7 | ||
|
|
8da931aed4 | ||
|
|
24c0de031a | ||
|
|
df60d40f91 | ||
|
|
188ce1bad1 | ||
|
|
88bad4b7ae | ||
|
|
4fc2df7b57 | ||
|
|
0fd975bf66 | ||
|
|
40992037da | ||
|
|
f94acd5ef3 | ||
|
|
c87f48fdea | ||
|
|
68ff588910 | ||
|
|
f420cfbf7c | ||
|
|
f3e99a6cfa | ||
|
|
22cf986a79 | ||
|
|
d80b697fbd | ||
|
|
8b9aaad20a | ||
|
|
4080d5807a | ||
|
|
7c2072eed1 | ||
|
|
d21e779b9f | ||
|
|
f7e5223533 | ||
|
|
525bd21cd1 | ||
|
|
8df27d8c3a | ||
|
|
6464d6c7b4 | ||
|
|
2fc9d73c5f | ||
|
|
b32051df53 | ||
|
|
bf36a29ca2 | ||
|
|
a2ac94b625 | ||
|
|
c81afa6993 | ||
|
|
4fa93ec4d6 | ||
|
|
00c6ac81b9 | ||
|
|
8801031f06 | ||
|
|
2a033215a4 | ||
|
|
8214fefde6 | ||
|
|
4cdb75b74d | ||
|
|
eac82585ad | ||
|
|
2c76c70205 | ||
|
|
a9e09b856f | ||
|
|
c03a0b7f87 | ||
|
|
0ab8740832 | ||
|
|
aa1eae22c7 | ||
|
|
4f3b34f86b | ||
|
|
8435cb8df9 | ||
|
|
0d457d6d11 | ||
|
|
484015ceea | ||
|
|
1b5c4245df | ||
|
|
ce68a06436 | ||
|
|
7273059cb9 | ||
|
|
a03ea8ace3 | ||
|
|
d6cbfa39f8 | ||
|
|
a2e4cbbfe2 | ||
|
|
23518953d0 | ||
|
|
2716ca449e | ||
|
|
ecb1ad6ca5 | ||
|
|
3fa7af12e0 | ||
|
|
12efb1967e | ||
|
|
56b1e80758 | ||
|
|
baf874ea67 | ||
|
|
28262f59d3 | ||
|
|
44d69d6fc0 | ||
|
|
4d76ff4e6a | ||
|
|
1eaf259e52 | ||
|
|
bca1fa0968 | ||
|
|
bd79884d84 | ||
|
|
3b42b200d3 | ||
|
|
dad4a20fa7 | ||
|
|
90d95988aa | ||
|
|
e88577fe52 | ||
|
|
6fa495b843 | ||
|
|
3311bfd3ca | ||
|
|
cfd4d285da | ||
|
|
c751bf6bdb | ||
|
|
6f94844a35 | ||
|
|
f74d097837 | ||
|
|
0a58b0cdad | ||
|
|
6f94ec728f | ||
|
|
e3747209eb | ||
|
|
36b39a50a4 | ||
|
|
d9c7ff8685 | ||
|
|
625d865625 | ||
|
|
00c6bd0240 | ||
|
|
506da2466b | ||
|
|
9ea0a535ea | ||
|
|
25d2a3cdf1 | ||
|
|
9fa59df798 | ||
|
|
93c0467f91 | ||
|
|
c377fe7651 | ||
|
|
9ed24522bb | ||
|
|
ddcabbf95d | ||
|
|
5c58b45340 | ||
|
|
5690b639cd | ||
|
|
22d0ff8173 | ||
|
|
8e61fe805c | ||
|
|
5356436c94 | ||
|
|
8ca8b92f92 | ||
|
|
7c98f20e11 | ||
|
|
1a8798a5d4 | ||
|
|
926842a216 | ||
|
|
9e11b860ec | ||
|
|
5abf1ee817 | ||
|
|
4e78e80619 | ||
|
|
33be9840f0 | ||
|
|
33fdaee399 | ||
|
|
91660a98d5 | ||
|
|
8d5c4492d8 | ||
|
|
29ad52bb46 | ||
|
|
590b7b7682 | ||
|
|
ea06d9614f | ||
|
|
41ba55634a | ||
|
|
f09616e780 | ||
|
|
a4d7e35cdd | ||
|
|
346e0ea734 | ||
|
|
ce854236cf | ||
|
|
1588663358 | ||
|
|
68fdc0a2b6 | ||
|
|
d335f8f981 | ||
|
|
b4efd15afd | ||
|
|
0e6f9da761 | ||
|
|
02b34f05c8 | ||
|
|
f26800eb85 | ||
|
|
d2cc01169b | ||
|
|
d8924cd8a9 | ||
|
|
25af5d2968 | ||
|
|
3580d4ff85 | ||
|
|
42607aadc3 | ||
|
|
2fe86a4cde | ||
|
|
db0256e0f7 | ||
|
|
224e808c21 | ||
|
|
6ed6b937f8 | ||
|
|
99b940f56f | ||
|
|
66a417a3ee | ||
|
|
761762bdc0 | ||
|
|
bd8ada9e4a | ||
|
|
ba5c7e4fc3 | ||
|
|
903284fe59 | ||
|
|
cf7ee0081c | ||
|
|
e6a1d8156b | ||
|
|
b850f51ef5 | ||
|
|
4e57de4776 | ||
|
|
0a2945e7f1 | ||
|
|
4f9beae49d | ||
|
|
15a49334d8 | ||
|
|
cf5e7c39e0 | ||
|
|
173ee5fcdc | ||
|
|
67968dff7e | ||
|
|
c596c70d42 | ||
|
|
d30c3aef32 | ||
|
|
f7e5101753 | ||
|
|
597b13d1b3 | ||
|
|
2b8385a874 | ||
|
|
ddcc301ab6 | ||
|
|
ab983c678f | ||
|
|
79dfbec910 | ||
|
|
6bf439d4ce | ||
|
|
063c5ee328 | ||
|
|
19137b8e8c | ||
|
|
95aa30ad41 | ||
|
|
55aa96a33a | ||
|
|
5460348450 | ||
|
|
0d1a68ecb4 | ||
|
|
98466220c7 | ||
|
|
6d2dd076dc | ||
|
|
5e07bcb79a | ||
|
|
9c81a74743 | ||
|
|
a3f2b1d829 | ||
|
|
cbdd71e44e | ||
|
|
f01cf5e04c | ||
|
|
bbb3063cb2 | ||
|
|
c0fa6e6939 | ||
|
|
0337362eec | ||
|
|
fb3013cb95 | ||
|
|
833fec3d21 | ||
|
|
007b79c729 | ||
|
|
09f55955e8 | ||
|
|
29c2c72d8f | ||
|
|
ae9b541ce2 | ||
|
|
8d86637d3f | ||
|
|
390ff1bcf7 | ||
|
|
aa65589391 | ||
|
|
9ee23a9086 | ||
|
|
41cdd3dcf7 | ||
|
|
aba5741450 | ||
|
|
cb5eb417c5 | ||
|
|
9f8b8b624b | ||
|
|
8728b07e85 | ||
|
|
e1ffd83b64 | ||
|
|
020a494f3f | ||
|
|
96ed1e1372 | ||
|
|
860682e476 | ||
|
|
2903b4910c | ||
|
|
c07e33eff0 | ||
|
|
a5b1b04915 | ||
|
|
799848c2a0 | ||
|
|
7e6cd34071 | ||
|
|
b8c24f906d | ||
|
|
e678738ded | ||
|
|
9000be6daa | ||
|
|
13ff4afaa4 | ||
|
|
40b9c07641 | ||
|
|
0ce5117715 | ||
|
|
526d154172 | ||
|
|
9e422576b8 | ||
|
|
069bca29d1 | ||
|
|
34ac124b6b | ||
|
|
e475a22435 | ||
|
|
d1ec628d6c | ||
|
|
d13227b277 | ||
|
|
fcb992240e | ||
|
|
cf5eb6a0bc | ||
|
|
2aa38baa35 | ||
|
|
84d046ab2a | ||
|
|
29b08fc306 | ||
|
|
a7153a0ff5 | ||
|
|
bc67308f85 | ||
|
|
6e93a87265 | ||
|
|
6fd1f794f9 | ||
|
|
5942e65b1c | ||
|
|
77d670c224 | ||
|
|
70546e5dfe | ||
|
|
fec7dfefa4 |
9
.github/aur/flux-bin/.SRCINFO.template
vendored
9
.github/aur/flux-bin/.SRCINFO.template
vendored
@@ -4,19 +4,16 @@ pkgbase = flux-bin
|
||||
pkgrel = ${PKGREL}
|
||||
url = https://fluxcd.io/
|
||||
arch = x86_64
|
||||
arch = armv6h
|
||||
arch = armv7h
|
||||
arch = aarch64
|
||||
license = APACHE
|
||||
optdepends = bash-completion: auto-completion for flux in Bash
|
||||
optdepends = zsh-completions: auto-completion for flux in ZSH
|
||||
source_x86_64 = flux-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_amd64.tar.gz
|
||||
source_x86_64 = flux-bin-${PKGVER}_linux_amd64.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_amd64.tar.gz
|
||||
sha256sums_x86_64 = ${SHA256SUM_AMD64}
|
||||
source_armv6h = flux-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_arm.tar.gz
|
||||
sha256sums_armv6h = ${SHA256SUM_ARM}
|
||||
source_armv7h = flux-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_arm.tar.gz
|
||||
source_armv7h = flux-bin-${PKGVER}_linux_arm.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_arm.tar.gz
|
||||
sha256sums_armv7h = ${SHA256SUM_ARM}
|
||||
source_aarch64 = flux-${PKGVER}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_arm64.tar.gz
|
||||
source_aarch64 = flux-bin-${PKGVER}_linux_arm64.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_arm64.tar.gz
|
||||
sha256sums_aarch64 = ${SHA256SUM_ARM64}
|
||||
|
||||
pkgname = flux-bin
|
||||
|
||||
14
.github/aur/flux-bin/PKGBUILD.template
vendored
14
.github/aur/flux-bin/PKGBUILD.template
vendored
@@ -8,28 +8,22 @@ _srcname=flux
|
||||
_srcver=${VERSION}
|
||||
pkgdesc="Open and extensible continuous delivery solution for Kubernetes"
|
||||
url="https://fluxcd.io/"
|
||||
arch=("x86_64" "armv6h" "armv7h" "aarch64")
|
||||
arch=("x86_64" "armv7h" "aarch64")
|
||||
license=("APACHE")
|
||||
optdepends=('bash-completion: auto-completion for flux in Bash'
|
||||
'zsh-completions: auto-completion for flux in ZSH')
|
||||
source_x86_64=(
|
||||
"${pkgname}-${pkgver}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${_srcver}/flux_${_srcver}_linux_amd64.tar.gz"
|
||||
)
|
||||
source_armv6h=(
|
||||
"${pkgname}-${pkgver}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${_srcver}/flux_${_srcver}_linux_arm.tar.gz"
|
||||
"${pkgname}-${pkgver}_linux_amd64.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${_srcver}/flux_${_srcver}_linux_amd64.tar.gz"
|
||||
)
|
||||
source_armv7h=(
|
||||
"${pkgname}-${pkgver}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${_srcver}/flux_${_srcver}_linux_arm.tar.gz"
|
||||
"${pkgname}-${pkgver}_linux_arm.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${_srcver}/flux_${_srcver}_linux_arm.tar.gz"
|
||||
)
|
||||
source_aarch64=(
|
||||
"${pkgname}-${pkgver}.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${_srcver}/flux_${_srcver}_linux_arm64.tar.gz"
|
||||
"${pkgname}-${pkgver}_linux_arm64.tar.gz::https://github.com/fluxcd/flux2/releases/download/v${_srcver}/flux_${_srcver}_linux_arm64.tar.gz"
|
||||
)
|
||||
sha256sums_x86_64=(
|
||||
${SHA256SUM_AMD64}
|
||||
)
|
||||
sha256sums_armv6h=(
|
||||
${SHA256SUM_ARM}
|
||||
)
|
||||
sha256sums_armv7h=(
|
||||
${SHA256SUM_ARM}
|
||||
)
|
||||
|
||||
1
.github/aur/flux-go/.SRCINFO.template
vendored
1
.github/aur/flux-go/.SRCINFO.template
vendored
@@ -4,7 +4,6 @@ pkgbase = flux-go
|
||||
pkgrel = ${PKGREL}
|
||||
url = https://fluxcd.io/
|
||||
arch = x86_64
|
||||
arch = armv6h
|
||||
arch = armv7h
|
||||
arch = aarch64
|
||||
license = APACHE
|
||||
|
||||
6
.github/aur/flux-go/PKGBUILD.template
vendored
6
.github/aur/flux-go/PKGBUILD.template
vendored
@@ -8,13 +8,13 @@ _srcname=flux
|
||||
_srcver=${VERSION}
|
||||
pkgdesc="Open and extensible continuous delivery solution for Kubernetes"
|
||||
url="https://fluxcd.io/"
|
||||
arch=("x86_64" "armv6h" "armv7h" "aarch64")
|
||||
arch=("x86_64" "armv7h" "aarch64")
|
||||
license=("APACHE")
|
||||
provides=("flux-bin")
|
||||
conflicts=("flux-bin")
|
||||
replaces=("flux-cli")
|
||||
depends=("glibc")
|
||||
makedepends=('go>=1.17', 'kustomize>=3.0')
|
||||
makedepends=('go>=1.20', 'kustomize>=5.0')
|
||||
optdepends=('bash-completion: auto-completion for flux in Bash',
|
||||
'zsh-completions: auto-completion for flux in ZSH')
|
||||
source=(
|
||||
@@ -41,7 +41,7 @@ check() {
|
||||
aarch64)
|
||||
export ENVTEST_ARCH=arm64
|
||||
;;
|
||||
armv6h|armv7h)
|
||||
armv7h)
|
||||
export ENVTEST_ARCH=arm
|
||||
;;
|
||||
esac
|
||||
|
||||
1
.github/aur/flux-scm/.SRCINFO.template
vendored
1
.github/aur/flux-scm/.SRCINFO.template
vendored
@@ -4,7 +4,6 @@ pkgbase = flux-scm
|
||||
pkgrel = ${PKGREL}
|
||||
url = https://fluxcd.io/
|
||||
arch = x86_64
|
||||
arch = armv6h
|
||||
arch = armv7h
|
||||
arch = aarch64
|
||||
license = APACHE
|
||||
|
||||
6
.github/aur/flux-scm/PKGBUILD.template
vendored
6
.github/aur/flux-scm/PKGBUILD.template
vendored
@@ -7,12 +7,12 @@ pkgrel=${PKGREL}
|
||||
_srcname=flux
|
||||
pkgdesc="Open and extensible continuous delivery solution for Kubernetes"
|
||||
url="https://fluxcd.io/"
|
||||
arch=("x86_64" "armv6h" "armv7h" "aarch64")
|
||||
arch=("x86_64" "armv7h" "aarch64")
|
||||
license=("APACHE")
|
||||
provides=("flux-bin")
|
||||
conflicts=("flux-bin")
|
||||
depends=("glibc")
|
||||
makedepends=('go>=1.17', 'kustomize>=3.0', 'git')
|
||||
makedepends=('go>=1.20', 'kustomize>=5.0', 'git')
|
||||
optdepends=('bash-completion: auto-completion for flux in Bash',
|
||||
'zsh-completions: auto-completion for flux in ZSH')
|
||||
source=(
|
||||
@@ -42,7 +42,7 @@ check() {
|
||||
aarch64)
|
||||
export ENVTEST_ARCH=arm64
|
||||
;;
|
||||
armv6h|armv7h)
|
||||
armv7h)
|
||||
export ENVTEST_ARCH=arm
|
||||
;;
|
||||
esac
|
||||
|
||||
11
.github/dependabot.yml
vendored
11
.github/dependabot.yml
vendored
@@ -3,7 +3,14 @@ version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
labels: ["area/build"]
|
||||
labels: ["area/ci", "dependencies"]
|
||||
groups:
|
||||
# Group all updates together, so that they are all applied in a single PR.
|
||||
# Grouped updates are currently in beta and is subject to change.
|
||||
# xref: https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#groups
|
||||
ci:
|
||||
patterns:
|
||||
- "*"
|
||||
schedule:
|
||||
# by default this will be on a monday.
|
||||
# By default, this will be on a monday.
|
||||
interval: "weekly"
|
||||
|
||||
49
.github/labels.yaml
vendored
Normal file
49
.github/labels.yaml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
# Configuration file to declaratively configure labels
|
||||
# Ref: https://github.com/EndBug/label-sync#Config-files
|
||||
|
||||
- name: area/bootstrap
|
||||
description: Bootstrap related issues and pull requests
|
||||
color: '#86efc9'
|
||||
- name: area/install
|
||||
description: Install and uninstall related issues and pull requests
|
||||
color: '#86efc9'
|
||||
- name: area/diff
|
||||
description: Diff related issues and pull requests
|
||||
color: '#BA4192'
|
||||
- name: area/bucket
|
||||
description: Bucket related issues and pull requests
|
||||
color: '#00b140'
|
||||
- name: area/git
|
||||
description: Git related issues and pull requests
|
||||
color: '#863faf'
|
||||
- name: area/oci
|
||||
description: OCI related issues and pull requests
|
||||
color: '#c739ff'
|
||||
- name: area/kustomization
|
||||
description: Kustomization related issues and pull requests
|
||||
color: '#00e54d'
|
||||
- name: area/helm
|
||||
description: Helm related issues and pull requests
|
||||
color: '#1673b6'
|
||||
- name: area/image-automation
|
||||
description: Automated image updates related issues and pull requests
|
||||
color: '#c5def5'
|
||||
- name: area/monitoring
|
||||
description: Monitoring related issues and pull requests
|
||||
color: '#dd75ae'
|
||||
- name: area/multi-tenancy
|
||||
description: Multi-tenancy related issues and pull requests
|
||||
color: '#72CDBD'
|
||||
- name: area/notification
|
||||
description: Notification API related issues and pull requests
|
||||
color: '#434ec1'
|
||||
- name: area/source
|
||||
description: Source API related issues and pull requests
|
||||
color: '#863faf'
|
||||
- name: area/rfc
|
||||
description: Feature request proposals in the RFC format
|
||||
color: '#D621C3'
|
||||
aliases: ['area/RFC']
|
||||
- name: backport:release/v2.0.x
|
||||
description: To be backported to release/v2.0.x
|
||||
color: '#ffd700'
|
||||
29
.github/workflows/action.yaml
vendored
Normal file
29
.github/workflows/action.yaml
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
name: test-gh-action
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'action/**'
|
||||
push:
|
||||
paths:
|
||||
- 'action/**'
|
||||
branches:
|
||||
- 'main'
|
||||
- 'release/**'
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
actions:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
version: [ubuntu-latest, macos-latest, windows-latest]
|
||||
|
||||
runs-on: ${{ matrix.version }}
|
||||
name: action on ${{ matrix.version }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup flux
|
||||
uses: ./action
|
||||
31
.github/workflows/backport.yaml
vendored
Normal file
31
.github/workflows/backport.yaml
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
name: backport
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [closed, labeled]
|
||||
|
||||
jobs:
|
||||
pull-request:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
if: github.event.pull_request.state == 'closed' && github.event.pull_request.merged && (github.event_name != 'labeled' || startsWith('backport:', github.event.label.name))
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Create backport PRs
|
||||
uses: korthout/backport-action@bd68141f079bd036e45ea8149bc9d174d5a04703 # v1.4.0
|
||||
# xref: https://github.com/korthout/backport-action#inputs
|
||||
with:
|
||||
# Use token to allow workflows to be triggered for the created PR
|
||||
github_token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
# Match labels with a pattern `backport:<target-branch>`
|
||||
label_pattern: '^backport:([^ ]+)$'
|
||||
# A bit shorter pull-request title than the default
|
||||
pull_title: '[${target_branch}] ${pull_title}'
|
||||
# Simpler PR description than default
|
||||
pull_description: |-
|
||||
Automated backport to `${target_branch}`, triggered by a label in #${pull_number}.
|
||||
9
.github/workflows/e2e-arm64.yaml
vendored
9
.github/workflows/e2e-arm64.yaml
vendored
@@ -3,7 +3,7 @@ name: e2e-arm64
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ main, update-components, e2e-*, release-* ]
|
||||
branches: [ 'main', 'update-components', 'e2e-*', 'release/**' ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -17,12 +17,13 @@ jobs:
|
||||
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.8, 1.26.3, 1.27.1 ]
|
||||
KUBERNETES_VERSION: [ 1.25.11, 1.26.6, 1.27.3, 1.28.0 ]
|
||||
fail-fast: false
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache-dependency-path: |
|
||||
|
||||
18
.github/workflows/e2e-azure.yaml
vendored
18
.github/workflows/e2e-azure.yaml
vendored
@@ -5,7 +5,17 @@ on:
|
||||
schedule:
|
||||
- cron: '0 6 * * *'
|
||||
push:
|
||||
branches: [ azure* ]
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'tests/**'
|
||||
- '.github/workflows/e2e-azure.yaml'
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'tests/**'
|
||||
- '.github/workflows/e2e-azure.yaml'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -13,11 +23,13 @@ permissions:
|
||||
jobs:
|
||||
e2e-amd64-aks:
|
||||
runs-on: ubuntu-22.04
|
||||
# This job is currently disabled since if always evaluates to false. 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@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache-dependency-path: |
|
||||
|
||||
18
.github/workflows/e2e-bootstrap.yaml
vendored
18
.github/workflows/e2e-bootstrap.yaml
vendored
@@ -3,9 +3,10 @@ name: e2e-bootstrap
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ main, release-* ]
|
||||
branches: [ 'main', 'release/**' ]
|
||||
pull_request:
|
||||
branches: [ main, release-* ]
|
||||
branches: [ 'main', 'release/**' ]
|
||||
paths-ignore: [ 'docs/**', 'rfcs/**' ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -16,23 +17,23 @@ jobs:
|
||||
if: (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@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@d8ccf8fb623ce1bb360ae2f45f323d9d5c5e9f00 # v1.5.0
|
||||
uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0
|
||||
with:
|
||||
version: v0.17.0
|
||||
version: v0.20.0
|
||||
cluster_name: kind
|
||||
# The versions below should target the newest Kubernetes version
|
||||
# Keep this up-to-date with https://endoflife.date/kubernetes
|
||||
node_image: kindest/node:v1.26.0
|
||||
kubectl_version: v1.26.2
|
||||
node_image: kindest/node:v1.28.0@sha256:9f3ff58f19dcf1a0611d11e8ac989fdb30a28f40f236f59f0bea31fb956ccf5c
|
||||
kubectl_version: v1.28.0
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
- name: Build
|
||||
@@ -98,7 +99,6 @@ jobs:
|
||||
--path=test-cluster \
|
||||
--read-write-key
|
||||
/tmp/flux reconcile image repository podinfo
|
||||
/tmp/flux reconcile image update flux-system
|
||||
/tmp/flux get images all
|
||||
|
||||
retries=10
|
||||
|
||||
17
.github/workflows/e2e.yaml
vendored
17
.github/workflows/e2e.yaml
vendored
@@ -3,9 +3,10 @@ name: e2e
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ main, release-* ]
|
||||
branches: [ 'main', 'release/**' ]
|
||||
pull_request:
|
||||
branches: [ main, release-* ]
|
||||
branches: [ 'main', 'release/**' ]
|
||||
paths-ignore: [ 'docs/**', 'rfcs/**' ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -20,24 +21,24 @@ jobs:
|
||||
- 5000:5000
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Setup Kubernetes
|
||||
uses: helm/kind-action@d8ccf8fb623ce1bb360ae2f45f323d9d5c5e9f00 # v1.5.0
|
||||
uses: helm/kind-action@dda0770415bac9fc20092cacbc54aa298604d140 # v1.8.0
|
||||
with:
|
||||
version: v0.17.0
|
||||
version: v0.20.0
|
||||
cluster_name: kind
|
||||
config: .github/kind/config.yaml # disable KIND-net
|
||||
# The versions below should target the newest Kubernetes version
|
||||
# Keep this up-to-date with https://endoflife.date/kubernetes
|
||||
node_image: kindest/node:v1.26.0
|
||||
kubectl_version: v1.26.2
|
||||
node_image: kindest/node:v1.28.0@sha256:9f3ff58f19dcf1a0611d11e8ac989fdb30a28f40f236f59f0bea31fb956ccf5c
|
||||
kubectl_version: v1.28.0
|
||||
- name: Setup Calico for network policy
|
||||
run: |
|
||||
kubectl apply -f https://docs.projectcalico.org/v3.25/manifests/calico.yaml
|
||||
|
||||
39
.github/workflows/ossf.yaml
vendored
Normal file
39
.github/workflows/ossf.yaml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: ossf
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
schedule:
|
||||
# Weekly on Saturdays.
|
||||
- cron: '30 1 * * 6'
|
||||
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
scorecard:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
security-events: write
|
||||
id-token: write
|
||||
actions: read
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Run analysis
|
||||
uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_results: true
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
- name: Upload SARIF results
|
||||
uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
87
.github/workflows/release.yaml
vendored
87
.github/workflows/release.yaml
vendored
@@ -9,6 +9,10 @@ permissions:
|
||||
|
||||
jobs:
|
||||
release-flux-cli:
|
||||
outputs:
|
||||
hashes: ${{ steps.slsa.outputs.hashes }}
|
||||
image_url: ${{ steps.slsa.outputs.image_url }}
|
||||
image_digest: ${{ steps.slsa.outputs.image_digest }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write # needed to write releases
|
||||
@@ -16,33 +20,33 @@ jobs:
|
||||
packages: write # needed for ghcr access
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Unshallow
|
||||
run: git fetch --prune --unshallow
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache: false
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@e81a89b1732b9c48d79cd809d8d81d79c4647a18 # v2.1.0
|
||||
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2.2.0
|
||||
- name: Setup Docker Buildx
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@4b4e9c3e2d4531116a6f8ba8e71fc6e2cb6e6c8c # v2.5.0
|
||||
uses: docker/setup-buildx-action@4c0219f9ac95b02789c1075625400b2acbff50b1 # v2.9.1
|
||||
- name: Setup Syft
|
||||
uses: anchore/sbom-action/download-syft@4d571ad1038a9cc29d676154ef265ab8f9027042 # v0.14.2
|
||||
uses: anchore/sbom-action/download-syft@78fc58e266e87a38d4194b2137a3d4e9bcaf7ca1 # v0.14.3
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@204a51a57a74d190b284a0ce69b44bc37201f343 # v3.0.3
|
||||
uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 # v3.1.1
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
|
||||
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
|
||||
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
@@ -74,7 +78,8 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@f82d6c1c344bcacabba2c841718984797f664a6b # v4.2.0
|
||||
id: run-goreleaser
|
||||
uses: goreleaser/goreleaser-action@3fa32b8bb5620a2c1afe798654bbad59f9da4906 # v4.4.0
|
||||
with:
|
||||
version: latest
|
||||
args: release --release-notes=output/notes.md --skip-validate
|
||||
@@ -82,6 +87,22 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
HOMEBREW_TAP_GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
AUR_BOT_SSH_PRIVATE_KEY: ${{ secrets.AUR_BOT_SSH_PRIVATE_KEY }}
|
||||
- name: Generate SLSA metadata
|
||||
id: slsa
|
||||
env:
|
||||
ARTIFACTS: "${{ steps.run-goreleaser.outputs.artifacts }}"
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
hashes=$(echo -E $ARTIFACTS | jq --raw-output '.[] | {name, "digest": (.extra.Digest // .extra.Checksum)} | select(.digest) | {digest} + {name} | join(" ") | sub("^sha256:";"")' | base64 -w0)
|
||||
echo "hashes=$hashes" >> $GITHUB_OUTPUT
|
||||
|
||||
image_url=fluxcd/flux-cli:$GITHUB_REF_NAME
|
||||
echo "image_url=$image_url" >> $GITHUB_OUTPUT
|
||||
|
||||
image_digest=$(docker buildx imagetools inspect ${image_url} --format '{{json .}}' | jq -r .manifest.digest)
|
||||
echo "image_digest=$image_digest" >> $GITHUB_OUTPUT
|
||||
|
||||
release-flux-manifests:
|
||||
runs-on: ubuntu-latest
|
||||
needs: release-flux-cli
|
||||
@@ -89,7 +110,7 @@ jobs:
|
||||
id-token: write
|
||||
packages: write
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
- name: Setup Flux CLI
|
||||
@@ -100,13 +121,13 @@ jobs:
|
||||
VERSION=$(flux version --client | awk '{ print $NF }')
|
||||
echo "version=${VERSION}" >> $GITHUB_OUTPUT
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
|
||||
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.GHCR_TOKEN }}
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a # v2.1.0
|
||||
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2.2.0
|
||||
with:
|
||||
username: fluxcdbot
|
||||
password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
@@ -134,7 +155,7 @@ jobs:
|
||||
--path="./flux-system" \
|
||||
--source=${{ github.repositoryUrl }} \
|
||||
--revision="${{ github.ref_name }}@sha1:${{ github.sha }}"
|
||||
- uses: sigstore/cosign-installer@204a51a57a74d190b284a0ce69b44bc37201f343 # v3.0.3
|
||||
- uses: sigstore/cosign-installer@6e04d228eb30da1757ee4e1dd75a0ec73a653e06 # v3.1.1
|
||||
- name: Sign manifests
|
||||
env:
|
||||
COSIGN_EXPERIMENTAL: 1
|
||||
@@ -148,3 +169,43 @@ jobs:
|
||||
|
||||
flux tag artifact oci://docker.io/fluxcd/flux-manifests:${{ steps.prep.outputs.version }} \
|
||||
--tag latest
|
||||
|
||||
release-provenance:
|
||||
needs: [release-flux-cli]
|
||||
permissions:
|
||||
actions: read # for detecting the Github Actions environment.
|
||||
id-token: write # for creating OIDC tokens for signing.
|
||||
contents: write # for uploading attestations to GitHub releases.
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
|
||||
with:
|
||||
provenance-name: "provenance.intoto.jsonl"
|
||||
base64-subjects: "${{ needs.release-flux-cli.outputs.hashes }}"
|
||||
upload-assets: true
|
||||
|
||||
dockerhub-provenance:
|
||||
needs: [release-flux-cli]
|
||||
permissions:
|
||||
actions: read # for detecting the Github Actions environment.
|
||||
id-token: write # for creating OIDC tokens for signing.
|
||||
packages: write # for uploading attestations.
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
|
||||
with:
|
||||
image: ${{ needs.release-flux-cli.outputs.image_url }}
|
||||
digest: ${{ needs.release-flux-cli.outputs.image_digest }}
|
||||
registry-username: fluxcdbot
|
||||
secrets:
|
||||
registry-password: ${{ secrets.DOCKER_FLUXCD_PASSWORD }}
|
||||
|
||||
ghcr-provenance:
|
||||
needs: [release-flux-cli]
|
||||
permissions:
|
||||
actions: read # for detecting the Github Actions environment.
|
||||
id-token: write # for creating OIDC tokens for signing.
|
||||
packages: write # for uploading attestations.
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
|
||||
with:
|
||||
image: ghcr.io/${{ needs.release-flux-cli.outputs.image_url }}
|
||||
digest: ${{ needs.release-flux-cli.outputs.image_digest }}
|
||||
registry-username: fluxcdbot
|
||||
secrets:
|
||||
registry-password: ${{ secrets.GHCR_TOKEN }}
|
||||
|
||||
27
.github/workflows/scan.yaml
vendored
27
.github/workflows/scan.yaml
vendored
@@ -3,9 +3,9 @@ name: scan
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: [ main ]
|
||||
branches: [ 'main', 'release/**' ]
|
||||
pull_request:
|
||||
branches: [ main ]
|
||||
branches: [ 'main', 'release/**' ]
|
||||
schedule:
|
||||
- cron: '18 10 * * 3'
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Run FOSSA scan and upload build data
|
||||
uses: fossa-contrib/fossa-action@6728dc6fe9a068c648d080c33829ffbe56565023 # v2.0.0
|
||||
with:
|
||||
@@ -31,11 +31,11 @@ jobs:
|
||||
security-events: write
|
||||
if: (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup Kustomize
|
||||
uses: fluxcd/pkg/actions/kustomize@main
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache-dependency-path: |
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
run: |
|
||||
make tidy
|
||||
make cmd/flux/.manifests.done
|
||||
- uses: snyk/actions/setup@806182742461562b67788a64410098c9d9b96adb
|
||||
- uses: snyk/actions/setup@b98d498629f1c368650224d6d212bf7dfa89e4bf
|
||||
- name: Run Snyk to check for vulnerabilities
|
||||
continue-on-error: true
|
||||
run: |
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
env:
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
- name: Upload result to GitHub Code Scanning
|
||||
uses: github/codeql-action/upload-sarif@29b1f65c5e92e24fe6b6647da1eaabe529cec70f # v2.3.3
|
||||
uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
with:
|
||||
sarif_file: snyk.sarif
|
||||
|
||||
@@ -64,19 +64,22 @@ jobs:
|
||||
if: github.actor != 'dependabot[bot]'
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache-dependency-path: |
|
||||
**/go.sum
|
||||
**/go.mod
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@29b1f65c5e92e24fe6b6647da1eaabe529cec70f # v2.3.3
|
||||
uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
with:
|
||||
languages: go
|
||||
# xref: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# xref: https://codeql.github.com/codeql-query-help/go/
|
||||
queries: security-and-quality
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@29b1f65c5e92e24fe6b6647da1eaabe529cec70f # v2.3.3
|
||||
uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@29b1f65c5e92e24fe6b6647da1eaabe529cec70f # v2.3.3
|
||||
uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4
|
||||
|
||||
28
.github/workflows/sync-labels.yaml
vendored
Normal file
28
.github/workflows/sync-labels.yaml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: sync-labels
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- .github/labels.yaml
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
labels:
|
||||
name: Run sync
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- uses: EndBug/label-sync@da00f2c11fdb78e4fae44adac2fdd713778ea3e8 # v2.3.2
|
||||
with:
|
||||
# Configuration file
|
||||
config-file: |
|
||||
https://raw.githubusercontent.com/fluxcd/community/main/.github/standard-labels.yaml
|
||||
.github/labels.yaml
|
||||
# Strictly declarative
|
||||
delete-other-labels: true
|
||||
8
.github/workflows/update.yaml
vendored
8
.github/workflows/update.yaml
vendored
@@ -18,9 +18,9 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@4d34df0c2316fe8122ab82dc22947d607c0c91f9 # v4.0.0
|
||||
uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0
|
||||
with:
|
||||
go-version: 1.20.x
|
||||
cache-dependency-path: |
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
id: cpr
|
||||
uses: peter-evans/create-pull-request@284f54f989303d2699d373481a0cfa13ad5a6666 # v5.0.1
|
||||
uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5.0.2
|
||||
with:
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN }}
|
||||
commit-message: |
|
||||
@@ -99,7 +99,7 @@ jobs:
|
||||
body: |
|
||||
${{ steps.update.outputs.pr_body }}
|
||||
labels: |
|
||||
area/build
|
||||
dependencies
|
||||
reviewers: ${{ secrets.ASSIGNEES }}
|
||||
|
||||
- name: Check output
|
||||
|
||||
@@ -83,14 +83,7 @@ brews:
|
||||
install: |
|
||||
bin.install "flux"
|
||||
|
||||
bash_output = Utils.safe_popen_read(bin/"flux", "completion", "bash")
|
||||
(bash_completion/"flux").write bash_output
|
||||
|
||||
zsh_output = Utils.safe_popen_read(bin/"flux", "completion", "zsh")
|
||||
(zsh_completion/"_flux").write zsh_output
|
||||
|
||||
fish_output = Utils.safe_popen_read(bin/"flux", "completion", "fish")
|
||||
(fish_completion/"flux.fish").write fish_output
|
||||
generate_completions_from_executable(bin/"flux", "completion")
|
||||
test: |
|
||||
system "#{bin}/flux --version"
|
||||
publishers:
|
||||
|
||||
@@ -68,8 +68,8 @@ for source changes.
|
||||
Prerequisites:
|
||||
|
||||
* go >= 1.20
|
||||
* kubectl >= 1.20
|
||||
* kustomize >= 4.4
|
||||
* kubectl >= 1.24
|
||||
* kustomize >= 5.0
|
||||
* coreutils (on Mac OS)
|
||||
|
||||
Install the [controller-runtime/envtest](https://github.com/kubernetes-sigs/controller-runtime/tree/master/tools/setup-envtest) binaries with:
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
FROM alpine:3.17 as builder
|
||||
FROM alpine:3.18 as builder
|
||||
|
||||
RUN apk add --no-cache ca-certificates curl
|
||||
|
||||
ARG ARCH=linux/amd64
|
||||
ARG KUBECTL_VER=1.26.2
|
||||
ARG KUBECTL_VER=1.27.3
|
||||
|
||||
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 && \
|
||||
kubectl version --client=true
|
||||
|
||||
FROM alpine:3.17 as flux-cli
|
||||
FROM alpine:3.18 as flux-cli
|
||||
|
||||
RUN apk add --no-cache ca-certificates
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
[](https://github.com/fluxcd/flux2/releases)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4782)
|
||||
[](https://api.securityscorecards.dev/projects/github.com/fluxcd/flux2)
|
||||
[](https://app.fossa.com/projects/custom%2B162%2Fgithub.com%2Ffluxcd%2Fflux2?ref=badge_shield)
|
||||
[](https://artifacthub.io/packages/helm/fluxcd-community/flux2)
|
||||
|
||||
@@ -42,7 +43,7 @@ runtime for Flux v2. The APIs comprise Kubernetes custom resources,
|
||||
which can be created and updated by a cluster user, or by other
|
||||
automation tooling.
|
||||
|
||||

|
||||

|
||||
|
||||
You can use the toolkit to extend Flux, or to build your own systems
|
||||
for continuous delivery -- see [the developer
|
||||
|
||||
220
action/README.md
220
action/README.md
@@ -1,216 +1,22 @@
|
||||
# Flux GitHub Action
|
||||
|
||||
Usage:
|
||||
To install the latest Flux CLI on Linux, macOS or Windows GitHub runners:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
- name: Run Flux commands
|
||||
run: flux -v
|
||||
steps:
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
with:
|
||||
version: 'latest'
|
||||
- name: Run Flux CLI
|
||||
run: flux version --client
|
||||
```
|
||||
|
||||
The latest stable version of the `flux` binary is downloaded from
|
||||
GitHub [releases](https://github.com/fluxcd/flux2/releases)
|
||||
and placed at `/usr/local/bin/flux`.
|
||||
The Flux GitHub Action can be used to automate various tasks in CI, such as:
|
||||
|
||||
Note that this action can only be used on GitHub **Linux** runners.
|
||||
You can change the arch (defaults to `amd64`) with:
|
||||
- [Automate Flux upgrades on clusters via Pull Requests](https://fluxcd.io/flux/flux-gh-action/#automate-flux-updates)
|
||||
- [Push Kubernetes manifests to container registries](https://fluxcd.io/flux/flux-gh-action/#push-kubernetes-manifests-to-container-registries)
|
||||
- [Run end-to-end testing with Flux and Kubernetes Kind](https://fluxcd.io/flux/flux-gh-action/#end-to-end-testing)
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
with:
|
||||
arch: arm64 # can be amd64, arm64 or arm
|
||||
```
|
||||
For more information, please see the [Flux GitHub Action documentation](/flux/flux-gh-action.md).
|
||||
|
||||
You can download a specific version with:
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
with:
|
||||
version: 0.32.0
|
||||
```
|
||||
|
||||
You can also authenticate against the GitHub API using GitHub Actions' `GITHUB_TOKEN` secret.
|
||||
|
||||
For more information, please [read about the GitHub token secret](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#about-the-github_token-secret).
|
||||
|
||||
```yaml
|
||||
steps:
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
```
|
||||
|
||||
This is useful if you are seeing failures on shared runners, those failures are usually API limits being hit.
|
||||
|
||||
### Automate Flux updates
|
||||
|
||||
Example workflow for updating Flux's components generated with `flux bootstrap --path=clusters/production`:
|
||||
|
||||
```yaml
|
||||
name: update-flux
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: "0 * * * *"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
components:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
- name: Check for updates
|
||||
id: update
|
||||
run: |
|
||||
flux install \
|
||||
--export > ./clusters/production/flux-system/gotk-components.yaml
|
||||
|
||||
VERSION="$(flux -v)"
|
||||
echo "flux_version=$VERSION" >> $GITHUB_OUTPUT
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: update-flux
|
||||
commit-message: Update to ${{ steps.update.outputs.flux_version }}
|
||||
title: Update to ${{ steps.update.outputs.flux_version }}
|
||||
body: |
|
||||
${{ steps.update.outputs.flux_version }}
|
||||
```
|
||||
|
||||
### Push Kubernetes manifests to container registries
|
||||
|
||||
Example workflow for publishing Kubernetes manifests bundled as OCI artifacts to GitHub Container Registry:
|
||||
|
||||
```yaml
|
||||
name: push-artifact-staging
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
permissions:
|
||||
packages: write # needed for ghcr.io access
|
||||
|
||||
env:
|
||||
OCI_REPO: "oci://ghcr.io/my-org/manifests/${{ github.event.repository.name }}"
|
||||
|
||||
jobs:
|
||||
kubernetes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Generate manifests
|
||||
run: |
|
||||
kustomize build ./manifests/staging > ./deploy/app.yaml
|
||||
- name: Push manifests
|
||||
run: |
|
||||
flux push artifact $OCI_REPO:$(git rev-parse --short HEAD) \
|
||||
--path="./deploy" \
|
||||
--source="$(git config --get remote.origin.url)" \
|
||||
--revision="$(git branch --show-current)@sha1:$(git rev-parse HEAD)"
|
||||
- name: Deploy manifests to staging
|
||||
run: |
|
||||
flux tag artifact $OCI_REPO:$(git rev-parse --short HEAD) --tag staging
|
||||
```
|
||||
|
||||
### Push and sign Kubernetes manifests to container registries
|
||||
|
||||
Example workflow for publishing Kubernetes manifests bundled as OCI artifacts
|
||||
which are signed with Cosign and GitHub OIDC:
|
||||
|
||||
```yaml
|
||||
name: push-sign-artifact
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
|
||||
permissions:
|
||||
packages: write # needed for ghcr.io access
|
||||
id-token: write # needed for keyless signing
|
||||
|
||||
env:
|
||||
OCI_REPO: "oci://ghcr.io/my-org/manifests/${{ github.event.repository.name }}"
|
||||
|
||||
jobs:
|
||||
kubernetes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
- name: Setup Cosign
|
||||
uses: sigstore/cosign-installer@main
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Push and sign manifests
|
||||
run: |
|
||||
digest_url=$(flux push artifact \
|
||||
$OCI_REPO:$(git rev-parse --short HEAD) \
|
||||
--path="./manifests" \
|
||||
--source="$(git config --get remote.origin.url)" \
|
||||
--revision="$(git branch --show-current)@sha1:$(git rev-parse HEAD)" |\
|
||||
jq -r '. | .repository + "@" + .digest')
|
||||
|
||||
cosign sign $digest_url
|
||||
```
|
||||
|
||||
### End-to-end testing
|
||||
|
||||
Example workflow for running Flux in Kubernetes Kind:
|
||||
|
||||
```yaml
|
||||
name: e2e
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '*'
|
||||
|
||||
jobs:
|
||||
kubernetes:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Setup Flux CLI
|
||||
uses: fluxcd/flux2/action@main
|
||||
- name: Setup Kubernetes Kind
|
||||
uses: engineerd/setup-kind@v0.5.0
|
||||
- name: Install Flux in Kubernetes Kind
|
||||
run: flux install
|
||||
```
|
||||
|
||||
A complete e2e testing workflow is available here
|
||||
[flux2-kustomize-helm-example](https://github.com/fluxcd/flux2-kustomize-helm-example/blob/main/.github/workflows/e2e.yaml)
|
||||
|
||||
@@ -1,64 +1,120 @@
|
||||
name: Setup Flux CLI
|
||||
description: A GitHub Action for running Flux commands
|
||||
author: Stefan Prodan
|
||||
description: A GitHub Action for installing the Flux CLI
|
||||
author: Flux project
|
||||
branding:
|
||||
color: blue
|
||||
icon: command
|
||||
inputs:
|
||||
version:
|
||||
description: "Flux version e.g. 0.8.0 (defaults to latest stable release)"
|
||||
description: "Flux version e.g. 2.0.0 (defaults to latest stable release)"
|
||||
required: false
|
||||
arch:
|
||||
description: "arch can be amd64, arm64 or arm"
|
||||
required: true
|
||||
default: "amd64"
|
||||
required: false
|
||||
deprecationMessage: "No longer required, action will now detect runner arch."
|
||||
bindir:
|
||||
description: "Optional location of the Flux binary. Will not use sudo if set. Updates System Path."
|
||||
description: "Alternative location for the Flux binary, defaults to path relative to $RUNNER_TOOL_CACHE."
|
||||
required: false
|
||||
token:
|
||||
description: "GitHub Token used to authentication against the API (generally only needed to prevent quota limit errors)"
|
||||
description: "Token used to authentication against the GitHub.com API. Defaults to the token from the GitHub context of the workflow."
|
||||
required: false
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- name: "Download flux binary to tmp"
|
||||
- name: "Download the binary to the runner's cache dir"
|
||||
shell: bash
|
||||
run: |
|
||||
ARCH=${{ inputs.arch }}
|
||||
VERSION=${{ inputs.version }}
|
||||
TOKEN=${{ inputs.token }}
|
||||
|
||||
if [ -z "${VERSION}" ]; then
|
||||
if [ -n "${TOKEN}" ]; then
|
||||
VERSION_SLUG=$(curl https://api.github.com/repos/fluxcd/flux2/releases/latest --silent --location --header "Authorization: token ${TOKEN}" | grep tag_name)
|
||||
else
|
||||
# With no GITHUB_TOKEN you will experience occasional failures due to rate limiting
|
||||
# Ref: https://github.com/fluxcd/flux2/issues/3509#issuecomment-1400820992
|
||||
VERSION_SLUG=$(curl https://api.github.com/repos/fluxcd/flux2/releases/latest --silent --location | grep tag_name)
|
||||
TOKEN=${{ inputs.token }}
|
||||
if [[ -z "$TOKEN" ]]; then
|
||||
TOKEN=${{ github.token }}
|
||||
fi
|
||||
|
||||
if [[ -z "$VERSION" ]] || [[ "$VERSION" = "latest" ]]; then
|
||||
VERSION=$(curl -fsSL -H "Authorization: token ${TOKEN}" https://api.github.com/repos/fluxcd/flux2/releases/latest | grep tag_name | cut -d '"' -f 4)
|
||||
fi
|
||||
if [[ -z "$VERSION" ]]; then
|
||||
echo "Unable to determine Flux CLI version"
|
||||
exit 1
|
||||
fi
|
||||
if [[ $VERSION = v* ]]; then
|
||||
VERSION="${VERSION:1}"
|
||||
fi
|
||||
|
||||
OS=$(echo "${RUNNER_OS}" | tr '[:upper:]' '[:lower:]')
|
||||
if [[ "$OS" == "macos" ]]; then
|
||||
OS="darwin"
|
||||
fi
|
||||
|
||||
ARCH=$(echo "${RUNNER_ARCH}" | tr '[:upper:]' '[:lower:]')
|
||||
if [[ "$ARCH" == "x64" ]]; then
|
||||
ARCH="amd64"
|
||||
elif [[ "$ARCH" == "x86" ]]; then
|
||||
ARCH="386"
|
||||
fi
|
||||
|
||||
FLUX_EXEC_FILE="flux"
|
||||
if [[ "$OS" == "windows" ]]; then
|
||||
FLUX_EXEC_FILE="${FLUX_EXEC_FILE}.exe"
|
||||
fi
|
||||
|
||||
FLUX_TOOL_DIR=${{ inputs.bindir }}
|
||||
if [[ -z "$FLUX_TOOL_DIR" ]]; then
|
||||
FLUX_TOOL_DIR="${RUNNER_TOOL_CACHE}/flux2/${VERSION}/${OS}/${ARCH}"
|
||||
fi
|
||||
if [[ ! -x "$FLUX_TOOL_DIR/FLUX_EXEC_FILE" ]]; then
|
||||
DL_DIR="$(mktemp -dt flux2-XXXXXX)"
|
||||
trap 'rm -rf $DL_DIR' EXIT
|
||||
|
||||
echo "Downloading flux ${VERSION} for ${OS}/${ARCH}"
|
||||
FLUX_TARGET_FILE="flux_${VERSION}_${OS}_${ARCH}.tar.gz"
|
||||
if [[ "$OS" == "windows" ]]; then
|
||||
FLUX_TARGET_FILE="flux_${VERSION}_${OS}_${ARCH}.zip"
|
||||
fi
|
||||
|
||||
VERSION=$(echo "${VERSION_SLUG}" | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
|
||||
FLUX_CHECKSUMS_FILE="flux_${VERSION}_checksums.txt"
|
||||
|
||||
FLUX_DOWNLOAD_URL="https://github.com/fluxcd/flux2/releases/download/v${VERSION}/"
|
||||
|
||||
curl -fsSL -o "$DL_DIR/$FLUX_TARGET_FILE" "$FLUX_DOWNLOAD_URL/$FLUX_TARGET_FILE"
|
||||
curl -fsSL -o "$DL_DIR/$FLUX_CHECKSUMS_FILE" "$FLUX_DOWNLOAD_URL/$FLUX_CHECKSUMS_FILE"
|
||||
|
||||
echo "Verifying checksum"
|
||||
sum=""
|
||||
if command -v openssl > /dev/null; then
|
||||
sum=$(openssl sha256 "$DL_DIR/$FLUX_TARGET_FILE" | awk '{print $2}')
|
||||
elif command -v sha256sum > /dev/null; then
|
||||
sum=$(sha256sum "$DL_DIR/$FLUX_TARGET_FILE" | awk '{print $1}')
|
||||
fi
|
||||
|
||||
if [[ -z "$sum" ]]; then
|
||||
echo "Neither openssl nor sha256sum found. Cannot calculate checksum."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
expected_sum=$(grep " $FLUX_TARGET_FILE\$" "$DL_DIR/$FLUX_CHECKSUMS_FILE" | awk '{print $1}')
|
||||
if [ "$sum" != "$expected_sum" ]; then
|
||||
echo "SHA sum of ${FLUX_TARGET_FILE} does not match. Aborting."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Installing flux to ${FLUX_TOOL_DIR}"
|
||||
mkdir -p "$FLUX_TOOL_DIR"
|
||||
|
||||
if [[ "$OS" == "windows" ]]; then
|
||||
unzip "$DL_DIR/$FLUX_TARGET_FILE" "$FLUX_EXEC_FILE" -d "$FLUX_TOOL_DIR"
|
||||
else
|
||||
tar xzf "$DL_DIR/$FLUX_TARGET_FILE" -C "$FLUX_TOOL_DIR" $FLUX_EXEC_FILE
|
||||
fi
|
||||
|
||||
chmod +x "$FLUX_TOOL_DIR/$FLUX_EXEC_FILE"
|
||||
fi
|
||||
|
||||
BIN_URL="https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_${ARCH}.tar.gz"
|
||||
curl --silent --fail --location "${BIN_URL}" --output /tmp/flux.tar.gz
|
||||
mkdir -p /tmp/flux
|
||||
tar -C /tmp/flux/ -zxvf /tmp/flux.tar.gz
|
||||
- name: "Copy Flux binary to execute location"
|
||||
shell: bash
|
||||
run: |
|
||||
BINDIR=${{ inputs.bindir }}
|
||||
if [ -z "${BINDIR}" ]; then
|
||||
sudo cp /tmp/flux/flux /usr/local/bin
|
||||
else
|
||||
cp /tmp/flux/flux "${BINDIR}"
|
||||
echo "${BINDIR}" >> $GITHUB_PATH
|
||||
fi
|
||||
- name: "Cleanup tmp"
|
||||
shell: bash
|
||||
run: |
|
||||
rm -rf /tmp/flux/ /tmp/flux.tar.gz
|
||||
- name: "Verify correct installation of binary"
|
||||
echo "Adding flux to path"
|
||||
echo "$FLUX_TOOL_DIR" >> "$GITHUB_PATH"
|
||||
|
||||
- name: "Print installed flux version"
|
||||
shell: bash
|
||||
run: |
|
||||
flux -v
|
||||
|
||||
@@ -87,7 +87,7 @@ func buildArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
|
||||
logger.Actionf("building artifact from %s", path)
|
||||
|
||||
ociClient := oci.NewLocalClient()
|
||||
ociClient := oci.NewClient(oci.DefaultOptions())
|
||||
if err := ociClient.Build(buildArtifactArgs.output, path, buildArtifactArgs.ignorePaths); err != nil {
|
||||
return fmt.Errorf("bulding artifact failed, error: %w", err)
|
||||
}
|
||||
|
||||
@@ -159,6 +159,7 @@ spec:
|
||||
tmpl := map[string]string{
|
||||
"fluxns": allocateNamespace("flux-system"),
|
||||
}
|
||||
setup(t, tmpl)
|
||||
|
||||
testEnv.CreateObjectFile("./testdata/build-kustomization/podinfo-source.yaml", tmpl, t)
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ type checkFlags struct {
|
||||
}
|
||||
|
||||
var kubernetesConstraints = []string{
|
||||
">=1.20.6-0",
|
||||
">=1.25.0-0",
|
||||
}
|
||||
|
||||
var checkArgs checkFlags
|
||||
|
||||
@@ -83,9 +83,9 @@ var createHelmReleaseCmd = &cobra.Command{
|
||||
|
||||
# Create a HelmRelease with a custom release name
|
||||
flux create hr podinfo \
|
||||
--release-name=podinfo-dev
|
||||
--release-name=podinfo-dev \
|
||||
--source=HelmRepository/podinfo \
|
||||
--chart=podinfo \
|
||||
--chart=podinfo
|
||||
|
||||
# Create a HelmRelease targeting another namespace than the resource
|
||||
flux create hr podinfo \
|
||||
|
||||
@@ -88,6 +88,7 @@ type secretGitFlags struct {
|
||||
rsaBits flags.RSAKeyBits
|
||||
ecdsaCurve flags.ECDSACurve
|
||||
caFile string
|
||||
caCrtFile string
|
||||
privateKeyFile string
|
||||
bearerToken string
|
||||
}
|
||||
@@ -102,6 +103,7 @@ func init() {
|
||||
createSecretGitCmd.Flags().Var(&secretGitArgs.rsaBits, "ssh-rsa-bits", secretGitArgs.rsaBits.Description())
|
||||
createSecretGitCmd.Flags().Var(&secretGitArgs.ecdsaCurve, "ssh-ecdsa-curve", secretGitArgs.ecdsaCurve.Description())
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.caFile, "ca-file", "", "path to TLS CA file used for validating self-signed certificates")
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.caCrtFile, "ca-crt-file", "", "path to TLS CA certificate file used for validating self-signed certificates; takes precedence over --ca-file")
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.privateKeyFile, "private-key-file", "", "path to a passwordless private key file used for authenticating to the Git SSH server")
|
||||
createSecretGitCmd.Flags().StringVar(&secretGitArgs.bearerToken, "bearer-token", "", "bearer authentication token")
|
||||
|
||||
@@ -160,12 +162,18 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
|
||||
if secretGitArgs.username != "" && secretGitArgs.password != "" && secretGitArgs.bearerToken != "" {
|
||||
return fmt.Errorf("user credentials and bearer token cannot be used together")
|
||||
}
|
||||
if secretGitArgs.caFile != "" {
|
||||
caBundle, err := os.ReadFile(secretGitArgs.caFile)
|
||||
|
||||
// --ca-crt-file takes precedence over --ca-file.
|
||||
if secretGitArgs.caCrtFile != "" {
|
||||
opts.CACrt, err = os.ReadFile(secretGitArgs.caCrtFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
} else if secretGitArgs.caFile != "" {
|
||||
opts.CAFile, err = os.ReadFile(secretGitArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
opts.CAFile = caBundle
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("git URL scheme '%s' not supported, can be: ssh, http and https", u.Scheme)
|
||||
|
||||
@@ -1,10 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateGitSecret(t *testing.T) {
|
||||
file, err := os.CreateTemp(t.TempDir(), "ca-crt")
|
||||
if err != nil {
|
||||
t.Fatal("could not create CA certificate file")
|
||||
}
|
||||
_, err = file.Write([]byte("ca-data"))
|
||||
if err != nil {
|
||||
t.Fatal("could not write to CA certificate file")
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
@@ -35,6 +46,11 @@ func TestCreateGitSecret(t *testing.T) {
|
||||
args: "create secret git bearer-token-auth --url=https://github.com/stefanprodan/podinfo --bearer-token=ghp_baR2qnFF0O41WlucePL3udt2N9vVZS4R0hAS --namespace=my-namespace --export",
|
||||
assert: assertGoldenFile("testdata/create_secret/git/git-bearer-token.yaml"),
|
||||
},
|
||||
{
|
||||
name: "git authentication with CA certificate",
|
||||
args: fmt.Sprintf("create secret git ca-crt --url=https://github.com/stefanprodan/podinfo --password=my-password --username=my-username --ca-crt-file=%s --namespace=my-namespace --export", file.Name()),
|
||||
assert: assertGoldenFile("testdata/create_secret/git/secret-ca-crt.yaml"),
|
||||
},
|
||||
{
|
||||
name: "git authentication with basic auth and bearer token",
|
||||
args: "create secret git podinfo-auth --url=https://github.com/stefanprodan/podinfo --username=aaa --password=zzzz --bearer-token=aaaa --namespace=my-namespace --export",
|
||||
|
||||
@@ -41,15 +41,8 @@ var createSecretHelmCmd = &cobra.Command{
|
||||
--export > repo-auth.yaml
|
||||
|
||||
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||
--in-place repo-auth.yaml
|
||||
--in-place repo-auth.yaml`,
|
||||
|
||||
# Create a Helm authentication secret using a custom TLS cert
|
||||
flux create secret helm repo-auth \
|
||||
--username=username \
|
||||
--password=password \
|
||||
--cert-file=./cert.crt \
|
||||
--key-file=./key.crt \
|
||||
--ca-file=./ca.crt`,
|
||||
RunE: createSecretHelmCmdRun,
|
||||
}
|
||||
|
||||
@@ -62,9 +55,16 @@ type secretHelmFlags struct {
|
||||
var secretHelmArgs secretHelmFlags
|
||||
|
||||
func init() {
|
||||
createSecretHelmCmd.Flags().StringVarP(&secretHelmArgs.username, "username", "u", "", "basic authentication username")
|
||||
createSecretHelmCmd.Flags().StringVarP(&secretHelmArgs.password, "password", "p", "", "basic authentication password")
|
||||
initSecretTLSFlags(createSecretHelmCmd.Flags(), &secretHelmArgs.secretTLSFlags)
|
||||
flags := createSecretHelmCmd.Flags()
|
||||
flags.StringVarP(&secretHelmArgs.username, "username", "u", "", "basic authentication username")
|
||||
flags.StringVarP(&secretHelmArgs.password, "password", "p", "", "basic authentication password")
|
||||
|
||||
initSecretDeprecatedTLSFlags(flags, &secretHelmArgs.secretTLSFlags)
|
||||
deprecationMsg := "please use the command `flux create secret tls` to generate TLS secrets"
|
||||
flags.MarkDeprecated("cert-file", deprecationMsg)
|
||||
flags.MarkDeprecated("key-file", deprecationMsg)
|
||||
flags.MarkDeprecated("ca-file", deprecationMsg)
|
||||
|
||||
createSecretCmd.AddCommand(createSecretHelmCmd)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,9 @@ var createSecretTLSCmd = &cobra.Command{
|
||||
# Files are expected to be PEM-encoded.
|
||||
flux create secret tls certs \
|
||||
--namespace=my-namespace \
|
||||
--cert-file=./client.crt \
|
||||
--key-file=./client.key \
|
||||
--tls-crt-file=./client.crt \
|
||||
--tls-key-file=./client.key \
|
||||
--ca-crt-file=./ca.crt \
|
||||
--export > certs.yaml
|
||||
|
||||
sops --encrypt --encrypted-regex '^(data|stringData)$' \
|
||||
@@ -48,22 +49,37 @@ var createSecretTLSCmd = &cobra.Command{
|
||||
}
|
||||
|
||||
type secretTLSFlags struct {
|
||||
certFile string
|
||||
keyFile string
|
||||
caFile string
|
||||
certFile string
|
||||
keyFile string
|
||||
caFile string
|
||||
caCrtFile string
|
||||
tlsKeyFile string
|
||||
tlsCrtFile string
|
||||
}
|
||||
|
||||
var secretTLSArgs secretTLSFlags
|
||||
|
||||
func initSecretTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) {
|
||||
func initSecretDeprecatedTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) {
|
||||
flags.StringVar(&args.certFile, "cert-file", "", "TLS authentication cert file path")
|
||||
flags.StringVar(&args.keyFile, "key-file", "", "TLS authentication key file path")
|
||||
flags.StringVar(&args.caFile, "ca-file", "", "TLS authentication CA file path")
|
||||
}
|
||||
|
||||
func initSecretTLSFlags(flags *pflag.FlagSet, args *secretTLSFlags) {
|
||||
flags.StringVar(&args.tlsCrtFile, "tls-crt-file", "", "TLS authentication cert file path")
|
||||
flags.StringVar(&args.tlsKeyFile, "tls-key-file", "", "TLS authentication key file path")
|
||||
flags.StringVar(&args.caCrtFile, "ca-crt-file", "", "TLS authentication CA file path")
|
||||
}
|
||||
|
||||
func init() {
|
||||
flags := createSecretTLSCmd.Flags()
|
||||
initSecretDeprecatedTLSFlags(flags, &secretTLSArgs)
|
||||
initSecretTLSFlags(flags, &secretTLSArgs)
|
||||
|
||||
flags.MarkDeprecated("cert-file", "please use --tls-crt-file instead")
|
||||
flags.MarkDeprecated("key-file", "please use --tls-key-file instead")
|
||||
flags.MarkDeprecated("ca-file", "please use --ca-crt-file instead")
|
||||
|
||||
createSecretCmd.AddCommand(createSecretTLSCmd)
|
||||
}
|
||||
|
||||
@@ -75,33 +91,40 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
caBundle := []byte{}
|
||||
if secretTLSArgs.caFile != "" {
|
||||
var err error
|
||||
caBundle, err = os.ReadFile(secretTLSArgs.caFile)
|
||||
opts := sourcesecret.Options{
|
||||
Name: name,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Labels: labels,
|
||||
}
|
||||
|
||||
if secretTLSArgs.caCrtFile != "" {
|
||||
opts.CACrt, err = os.ReadFile(secretTLSArgs.caCrtFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
} else if secretTLSArgs.caFile != "" {
|
||||
opts.CAFile, err = os.ReadFile(secretTLSArgs.caFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read TLS CA file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
var certFile, keyFile []byte
|
||||
if secretTLSArgs.certFile != "" && secretTLSArgs.keyFile != "" {
|
||||
if certFile, err = os.ReadFile(secretTLSArgs.certFile); err != nil {
|
||||
if secretTLSArgs.tlsCrtFile != "" && secretTLSArgs.tlsKeyFile != "" {
|
||||
if opts.TLSCrt, err = os.ReadFile(secretTLSArgs.tlsCrtFile); err != nil {
|
||||
return fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if keyFile, err = os.ReadFile(secretTLSArgs.keyFile); err != nil {
|
||||
if opts.TLSKey, err = os.ReadFile(secretTLSArgs.tlsKeyFile); err != nil {
|
||||
return fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
} else if secretTLSArgs.certFile != "" && secretTLSArgs.keyFile != "" {
|
||||
if opts.CertFile, err = os.ReadFile(secretTLSArgs.certFile); err != nil {
|
||||
return fmt.Errorf("failed to read cert file: %w", err)
|
||||
}
|
||||
if opts.KeyFile, err = os.ReadFile(secretTLSArgs.keyFile); err != nil {
|
||||
return fmt.Errorf("failed to read key file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
opts := sourcesecret.Options{
|
||||
Name: name,
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
Labels: labels,
|
||||
CAFile: caBundle,
|
||||
CertFile: certFile,
|
||||
KeyFile: keyFile,
|
||||
}
|
||||
secret, err := sourcesecret.Generate(opts)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestCreateTlsSecretNoArgs(t *testing.T) {
|
||||
func TestCreateTlsSecret(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
args string
|
||||
@@ -15,9 +15,13 @@ func TestCreateTlsSecretNoArgs(t *testing.T) {
|
||||
assert: assertError("name is required"),
|
||||
},
|
||||
{
|
||||
args: "create secret tls certs --namespace=my-namespace --cert-file=./testdata/create_secret/tls/test-cert.pem --key-file=./testdata/create_secret/tls/test-key.pem --export",
|
||||
args: "create secret tls certs --namespace=my-namespace --tls-crt-file=./testdata/create_secret/tls/test-cert.pem --tls-key-file=./testdata/create_secret/tls/test-key.pem --ca-crt-file=./testdata/create_secret/tls/test-ca.pem --export",
|
||||
assert: assertGoldenFile("testdata/create_secret/tls/secret-tls.yaml"),
|
||||
},
|
||||
{
|
||||
args: "create secret tls certs --namespace=my-namespace --cert-file=./testdata/create_secret/tls/test-cert.pem --key-file=./testdata/create_secret/tls/test-key.pem --ca-file=./testdata/create_secret/tls/test-ca.pem --export",
|
||||
assert: assertGoldenFile("testdata/create_secret/tls/deprecated-secret-tls.yaml"),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -64,13 +64,13 @@ For private Helm repositories, the basic authentication credentials are stored i
|
||||
|
||||
# Create a source for an OCI Helm repository
|
||||
flux create source helm podinfo \
|
||||
--url=oci://ghcr.io/stefanprodan/charts/podinfo
|
||||
--url=oci://ghcr.io/stefanprodan/charts/podinfo \
|
||||
--username=username \
|
||||
--password=password
|
||||
|
||||
# Create a source for an OCI Helm repository using an existing secret with basic auth or dockerconfig credentials
|
||||
flux create source helm podinfo \
|
||||
--url=oci://ghcr.io/stefanprodan/charts/podinfo
|
||||
--url=oci://ghcr.io/stefanprodan/charts/podinfo \
|
||||
--secret-ref=docker-config`,
|
||||
RunE: createSourceHelmCmdRun,
|
||||
}
|
||||
|
||||
@@ -21,10 +21,11 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
oci "github.com/fluxcd/pkg/oci/client"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
)
|
||||
|
||||
var diffArtifactCmd = &cobra.Command{
|
||||
@@ -81,7 +82,7 @@ func diffArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
ociClient := oci.NewLocalClient()
|
||||
ociClient := oci.NewClient(oci.DefaultOptions())
|
||||
|
||||
if diffArtifactArgs.provider.String() == sourcev1.GenericOCIProvider && diffArtifactArgs.creds != "" {
|
||||
logger.Actionf("logging in to registry with credentials")
|
||||
|
||||
@@ -91,6 +91,12 @@ func TestDiffKustomization(t *testing.T) {
|
||||
objectFile: "./testdata/diff-kustomization/stringdata-sops-secret.yaml",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/diff-with-drifted-stringdata-sops-secret.golden"),
|
||||
},
|
||||
{
|
||||
name: "diff where kustomization file has multiple objects with the same name",
|
||||
args: "diff kustomization podinfo --path ./testdata/build-kustomization/podinfo --progress-bar=false --kustomization-file ./testdata/diff-kustomization/flux-kustomization-multiobj.yaml",
|
||||
objectFile: "",
|
||||
assert: assertGoldenFile("./testdata/diff-kustomization/nothing-is-deployed.golden"),
|
||||
},
|
||||
}
|
||||
|
||||
tmpl := map[string]string{
|
||||
|
||||
@@ -127,6 +127,9 @@ func eventsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
rows, err := getRows(ctx, kubeclient, clientListOpts, refListOpts, showNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(rows) == 0 {
|
||||
if eventArgs.allNamespaces {
|
||||
logger.Failuref("No events found.")
|
||||
|
||||
@@ -18,6 +18,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
@@ -27,6 +28,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
watchtools "k8s.io/client-go/tools/watch"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
@@ -176,6 +178,10 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
|
||||
|
||||
err = kubeClient.List(ctx, get.list.asClientList(), listOpts...)
|
||||
if err != nil {
|
||||
var discErr *discovery.ErrGroupDiscoveryFailed
|
||||
if getAll && (strings.Contains(err.Error(), "no matches for kind") || errors.As(err, &discErr)) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -17,8 +17,6 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
|
||||
@@ -57,9 +55,7 @@ var getImageAllCmd = &cobra.Command{
|
||||
|
||||
for _, c := range allImageCmd {
|
||||
if err := c.run(cmd, args); err != nil {
|
||||
if !strings.Contains(err.Error(), "no matches for kind") {
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
logger.Failuref(err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,11 +61,26 @@ func TestKustomizationFromGit(t *testing.T) {
|
||||
"testdata/kustomization/suspend_kustomization_from_git.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"suspend kustomization tkfg foo tkfg bar",
|
||||
"testdata/kustomization/suspend_kustomization_from_git_multiple_args.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"resume kustomization tkfg foo --wait",
|
||||
"testdata/kustomization/resume_kustomization_from_git_multiple_args_wait.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"resume kustomization tkfg",
|
||||
"testdata/kustomization/resume_kustomization_from_git.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"resume kustomization tkfg tkfg",
|
||||
"testdata/kustomization/resume_kustomization_from_git_multiple_args.golden",
|
||||
tmpl,
|
||||
},
|
||||
{
|
||||
"delete kustomization tkfg --silent",
|
||||
"testdata/kustomization/delete_kustomization_from_git.golden",
|
||||
|
||||
@@ -78,7 +78,7 @@ func listArtifactsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
ociClient := oci.NewLocalClient()
|
||||
ociClient := oci.NewClient(oci.DefaultOptions())
|
||||
|
||||
if listArtifactArgs.provider.String() == sourcev1.GenericOCIProvider && listArtifactArgs.creds != "" {
|
||||
logger.Actionf("logging in to registry with credentials")
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
@@ -76,7 +77,7 @@ type logsFlags struct {
|
||||
sinceSeconds time.Duration
|
||||
}
|
||||
|
||||
var logsArgs = &logsFlags{
|
||||
var logsArgs = logsFlags{
|
||||
tail: -1,
|
||||
}
|
||||
|
||||
@@ -115,7 +116,7 @@ func logsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("no argument required")
|
||||
}
|
||||
|
||||
pods, err := getPods(ctx, clientset, fluxSelector)
|
||||
pods, err := getPods(ctx, clientset, logsArgs.fluxNamespace, fluxSelector)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -163,13 +164,16 @@ func logsCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return podLogs(ctx, requests)
|
||||
}
|
||||
|
||||
func getPods(ctx context.Context, c *kubernetes.Clientset, label string) ([]corev1.Pod, error) {
|
||||
// getPods searches for all Deployments in the given namespace that match the given label and returns a list of Pods
|
||||
// from these Deployments. For each Deployment a single Pod is chosen (based on various factors such as the running
|
||||
// state). If no Pod is found, an error is returned.
|
||||
func getPods(ctx context.Context, c *kubernetes.Clientset, ns string, label string) ([]corev1.Pod, error) {
|
||||
var ret []corev1.Pod
|
||||
|
||||
opts := metav1.ListOptions{
|
||||
LabelSelector: label,
|
||||
}
|
||||
deployList, err := c.AppsV1().Deployments(logsArgs.fluxNamespace).List(ctx, opts)
|
||||
deployList, err := c.AppsV1().Deployments(ns).List(ctx, opts)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
@@ -179,7 +183,7 @@ func getPods(ctx context.Context, c *kubernetes.Clientset, label string) ([]core
|
||||
opts := metav1.ListOptions{
|
||||
LabelSelector: createLabelStringFromMap(label),
|
||||
}
|
||||
podList, err := c.CoreV1().Pods(logsArgs.fluxNamespace).List(ctx, opts)
|
||||
podList, err := c.CoreV1().Pods(ns).List(ctx, opts)
|
||||
if err != nil {
|
||||
return ret, err
|
||||
}
|
||||
@@ -196,11 +200,16 @@ func getPods(ctx context.Context, c *kubernetes.Clientset, label string) ([]core
|
||||
}
|
||||
}
|
||||
|
||||
if len(ret) == 0 {
|
||||
return nil, fmt.Errorf("no Flux pods found in namespace %q", ns)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func parallelPodLogs(ctx context.Context, requests []rest.ResponseWrapper) error {
|
||||
reader, writer := io.Pipe()
|
||||
errReader, errWriter := io.Pipe()
|
||||
wg := &sync.WaitGroup{}
|
||||
wg.Add(len(requests))
|
||||
|
||||
@@ -208,7 +217,7 @@ func parallelPodLogs(ctx context.Context, requests []rest.ResponseWrapper) error
|
||||
go func(req rest.ResponseWrapper) {
|
||||
defer wg.Done()
|
||||
if err := logRequest(ctx, req, writer); err != nil {
|
||||
writer.CloseWithError(err)
|
||||
fmt.Fprintf(errWriter, "failed getting logs: %s\n", err)
|
||||
return
|
||||
}
|
||||
}(request)
|
||||
@@ -217,20 +226,40 @@ func parallelPodLogs(ctx context.Context, requests []rest.ResponseWrapper) error
|
||||
go func() {
|
||||
wg.Wait()
|
||||
writer.Close()
|
||||
errWriter.Close()
|
||||
}()
|
||||
|
||||
_, err := io.Copy(os.Stdout, reader)
|
||||
return err
|
||||
stdoutErrCh := asyncCopy(os.Stdout, reader)
|
||||
stderrErrCh := asyncCopy(os.Stderr, errReader)
|
||||
|
||||
return errors.Join(<-stdoutErrCh, <-stderrErrCh)
|
||||
}
|
||||
|
||||
// asyncCopy copies all data from from dst to src asynchronously and returns a channel for reading an error value.
|
||||
// This is basically an asynchronous wrapper around `io.Copy`. The returned channel is unbuffered and always is sent
|
||||
// a value (either nil or the error from `io.Copy`) as soon as `io.Copy` returns.
|
||||
// This function lets you copy from multiple sources into multiple destinations in parallel.
|
||||
func asyncCopy(dst io.Writer, src io.Reader) <-chan error {
|
||||
errCh := make(chan error)
|
||||
go func(errCh chan error) {
|
||||
_, err := io.Copy(dst, src)
|
||||
errCh <- err
|
||||
}(errCh)
|
||||
|
||||
return errCh
|
||||
}
|
||||
|
||||
func podLogs(ctx context.Context, requests []rest.ResponseWrapper) error {
|
||||
var retErr error
|
||||
for _, req := range requests {
|
||||
if err := logRequest(ctx, req, os.Stdout); err != nil {
|
||||
return err
|
||||
fmt.Fprintf(os.Stderr, "failed getting logs: %s\n", err)
|
||||
retErr = fmt.Errorf("failed to collect logs from all Flux pods")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return retErr
|
||||
}
|
||||
|
||||
func createLabelStringFromMap(m map[string]string) string {
|
||||
|
||||
88
cmd/flux/logs_e2e_test.go
Normal file
88
cmd/flux/logs_e2e_test.go
Normal file
@@ -0,0 +1,88 @@
|
||||
//go:build e2e
|
||||
// +build e2e
|
||||
|
||||
/*
|
||||
Copyright 2021 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 TestLogsNoArgs(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs",
|
||||
assert: assertSuccess(),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsWrongNamespace(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --flux-namespace=default",
|
||||
assert: assertError(`no Flux pods found in namespace "default"`),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsAllNamespaces(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --all-namespaces",
|
||||
assert: assertSuccess(),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSince(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since=2m",
|
||||
assert: assertSuccess(),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSinceInvalid(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since=XXX",
|
||||
assert: assertError(`invalid argument "XXX" for "--since" flag: time: invalid duration "XXX"`),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSinceTime(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since-time=2021-08-06T14:26:25.546Z",
|
||||
assert: assertSuccess(),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSinceTimeInvalid(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since-time=XXX",
|
||||
assert: assertError("XXX is not a valid (RFC3339) time"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSinceOnlyOneAllowed(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since=2m --since-time=2021-08-06T14:26:25.546Z",
|
||||
assert: assertError("at most one of `sinceTime` or `sinceSeconds` may be specified"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
@@ -30,73 +30,17 @@ import (
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestLogsNoArgs(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs",
|
||||
assert: assertSuccess(),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsAllNamespaces(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --all-namespaces",
|
||||
assert: assertSuccess(),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSince(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since=2m",
|
||||
assert: assertSuccess(),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSinceInvalid(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since=XXX",
|
||||
assert: assertError(`invalid argument "XXX" for "--since" flag: time: invalid duration "XXX"`),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSinceTime(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since-time=2021-08-06T14:26:25.546Z",
|
||||
assert: assertSuccess(),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSinceTimeInvalid(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since-time=XXX",
|
||||
assert: assertError("XXX is not a valid (RFC3339) time"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogsSinceOnlyOneAllowed(t *testing.T) {
|
||||
cmd := cmdTestCase{
|
||||
args: "logs --since=2m --since-time=2021-08-06T14:26:25.546Z",
|
||||
assert: assertError("at most one of `sinceTime` or `sinceSeconds` may be specified"),
|
||||
}
|
||||
cmd.runTestCmd(t)
|
||||
}
|
||||
|
||||
func TestLogRequest(t *testing.T) {
|
||||
mapper := &testResponseMapper{}
|
||||
tests := []struct {
|
||||
name string
|
||||
namespace string
|
||||
flags *logsFlags
|
||||
flags logsFlags
|
||||
assertFile string
|
||||
}{
|
||||
{
|
||||
name: "all logs",
|
||||
flags: &logsFlags{
|
||||
flags: logsFlags{
|
||||
tail: -1,
|
||||
allNamespaces: true,
|
||||
},
|
||||
@@ -105,14 +49,14 @@ func TestLogRequest(t *testing.T) {
|
||||
{
|
||||
name: "filter by namespace",
|
||||
namespace: "default",
|
||||
flags: &logsFlags{
|
||||
flags: logsFlags{
|
||||
tail: -1,
|
||||
},
|
||||
assertFile: "testdata/logs/namespace.txt",
|
||||
},
|
||||
{
|
||||
name: "filter by kind and namespace",
|
||||
flags: &logsFlags{
|
||||
flags: logsFlags{
|
||||
tail: -1,
|
||||
kind: "Kustomization",
|
||||
},
|
||||
@@ -120,7 +64,7 @@ func TestLogRequest(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "filter by loglevel",
|
||||
flags: &logsFlags{
|
||||
flags: logsFlags{
|
||||
tail: -1,
|
||||
logLevel: "error",
|
||||
allNamespaces: true,
|
||||
@@ -130,7 +74,7 @@ func TestLogRequest(t *testing.T) {
|
||||
{
|
||||
name: "filter by namespace, name, loglevel and kind",
|
||||
namespace: "flux-system",
|
||||
flags: &logsFlags{
|
||||
flags: logsFlags{
|
||||
tail: -1,
|
||||
logLevel: "error",
|
||||
kind: "Kustomization",
|
||||
@@ -163,7 +107,7 @@ func TestLogRequest(t *testing.T) {
|
||||
|
||||
// reset flags to default
|
||||
*kubeconfigArgs.Namespace = rootArgs.defaults.Namespace
|
||||
logsArgs = &logsFlags{
|
||||
logsArgs = logsFlags{
|
||||
tail: -1,
|
||||
}
|
||||
})
|
||||
@@ -24,12 +24,14 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/term"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
ctrllog "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
runclient "github.com/fluxcd/pkg/runtime/client"
|
||||
|
||||
@@ -149,6 +151,11 @@ func init() {
|
||||
apiServer := ""
|
||||
kubeconfigArgs.APIServer = &apiServer
|
||||
rootCmd.PersistentFlags().StringVar(kubeconfigArgs.APIServer, "server", *kubeconfigArgs.APIServer, "The address and port of the Kubernetes API server")
|
||||
// Update the description for kubeconfig TLS flags so that user's don't mistake it for a Flux specific flag
|
||||
rootCmd.Flag("insecure-skip-tls-verify").Usage = "If true, the Kubernetes API server's certificate will not be checked for validity. This will make your HTTPS connections insecure"
|
||||
rootCmd.Flag("client-certificate").Usage = "Path to a client certificate file for TLS authentication to the Kubernetes API server"
|
||||
rootCmd.Flag("certificate-authority").Usage = "Path to a cert file for the certificate authority to authenticate the Kubernetes API server"
|
||||
rootCmd.Flag("client-key").Usage = "Path to a client key file for TLS authentication to the Kubernetes API server"
|
||||
|
||||
kubeclientOptions.BindFlags(rootCmd.PersistentFlags())
|
||||
|
||||
@@ -170,6 +177,15 @@ func NewRootFlags() rootFlags {
|
||||
|
||||
func main() {
|
||||
log.SetFlags(0)
|
||||
|
||||
// This is required because controller-runtime expects its consumers to
|
||||
// set a logger through log.SetLogger within 30 seconds of the program's
|
||||
// initalization. If not set, the entire debug stack is printed as an
|
||||
// error, see: https://github.com/kubernetes-sigs/controller-runtime/blob/ed8be90/pkg/log/log.go#L59
|
||||
// Since we have our own logging and don't care about controller-runtime's
|
||||
// logger, we configure it's logger to do nothing.
|
||||
ctrllog.SetLogger(logr.New(ctrllog.NullLogSink{}))
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
|
||||
if err, ok := err.(*RequestError); ok {
|
||||
|
||||
@@ -41,7 +41,7 @@ func TestMain(m *testing.M) {
|
||||
// Install Flux.
|
||||
output, err := executeCommand("install --components-extra=image-reflector-controller,image-automation-controller")
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("install falied: %s error:'%w'", output, err))
|
||||
panic(fmt.Errorf("install failed: %s error:'%w'", output, err))
|
||||
}
|
||||
|
||||
// Run tests
|
||||
@@ -50,7 +50,7 @@ func TestMain(m *testing.M) {
|
||||
// Uninstall Flux
|
||||
output, err = executeCommand("uninstall -s --keep-namespace")
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("uninstall falied: %s error:'%w'", output, err))
|
||||
panic(fmt.Errorf("uninstall failed: %s error:'%w'", output, err))
|
||||
}
|
||||
|
||||
// Delete namespace and wait for finalisation
|
||||
|
||||
@@ -365,6 +365,12 @@ func executeTemplate(content string, templateValues map[string]string) (string,
|
||||
// Run the command and return the captured output.
|
||||
func executeCommand(cmd string) (string, error) {
|
||||
defer resetCmdArgs()
|
||||
defer func() {
|
||||
// need to set this explicitly because apparently its value isn't changed
|
||||
// in subsequent executions which causes tests to fail that rely on the value
|
||||
// of "Changed".
|
||||
resumeCmd.PersistentFlags().Lookup("wait").Changed = false
|
||||
}()
|
||||
args, err := shellwords.Parse(cmd)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@@ -392,6 +398,10 @@ func resetCmdArgs() {
|
||||
alertProviderArgs = alertProviderFlags{}
|
||||
bootstrapArgs = NewBootstrapFlags()
|
||||
bServerArgs = bServerFlags{}
|
||||
logsArgs = logsFlags{
|
||||
tail: -1,
|
||||
fluxNamespace: rootArgs.defaults.Namespace,
|
||||
}
|
||||
buildKsArgs = buildKsFlags{}
|
||||
checkArgs = checkFlags{}
|
||||
createArgs = createFlags{}
|
||||
|
||||
@@ -47,7 +47,7 @@ type copyable interface {
|
||||
deepCopyClientObject() client.Object
|
||||
}
|
||||
|
||||
// listAdapater is the analogue to adapter, but for lists; the
|
||||
// listAdapter is the analogue to adapter, but for lists; the
|
||||
// controller runtime distinguishes between methods dealing with
|
||||
// objects and lists.
|
||||
type listAdapter interface {
|
||||
|
||||
@@ -21,10 +21,11 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
|
||||
oci "github.com/fluxcd/pkg/oci/client"
|
||||
)
|
||||
|
||||
@@ -82,7 +83,7 @@ func pullArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
ociClient := oci.NewLocalClient()
|
||||
ociClient := oci.NewClient(oci.DefaultOptions())
|
||||
|
||||
if pullArtifactArgs.provider.String() == sourcev1.GenericOCIProvider && pullArtifactArgs.creds != "" {
|
||||
logger.Actionf("logging in to registry with credentials")
|
||||
@@ -110,8 +111,12 @@ func pullArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
logger.Successf("source %s", meta.Source)
|
||||
logger.Successf("revision %s", meta.Revision)
|
||||
if meta.Source != "" {
|
||||
logger.Successf("source %s", meta.Source)
|
||||
}
|
||||
if meta.Revision != "" {
|
||||
logger.Successf("revision %s", meta.Revision)
|
||||
}
|
||||
logger.Successf("digest %s", meta.Digest)
|
||||
logger.Successf("artifact content extracted to %s", pullArtifactArgs.output)
|
||||
|
||||
|
||||
@@ -22,14 +22,24 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
"github.com/google/go-containerregistry/pkg/authn"
|
||||
"github.com/google/go-containerregistry/pkg/crane"
|
||||
"github.com/google/go-containerregistry/pkg/logs"
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
reg "github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/google/go-containerregistry/pkg/v1/remote"
|
||||
"github.com/google/go-containerregistry/pkg/v1/remote/transport"
|
||||
"github.com/spf13/cobra"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
oci "github.com/fluxcd/pkg/oci/client"
|
||||
"github.com/fluxcd/pkg/oci"
|
||||
"github.com/fluxcd/pkg/oci/auth/login"
|
||||
"github.com/fluxcd/pkg/oci/client"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
|
||||
"github.com/fluxcd/flux2/v2/internal/flags"
|
||||
)
|
||||
|
||||
var pushArtifactCmd = &cobra.Command{
|
||||
@@ -79,7 +89,7 @@ The command can read the credentials from '~/.docker/config.json' but they can a
|
||||
# Login directly to the registry provider
|
||||
# You might need to export the following variable if you use local config files for AWS:
|
||||
# export AWS_SDK_LOAD_CONFIG=1
|
||||
flux push artifact oci://<account>.dkr.ecr.<region>.amazonaws.com/foo:v1:$(git tag --points-at HEAD) \
|
||||
flux push artifact oci://<account>.dkr.ecr.<region>.amazonaws.com/app-config:$(git tag --points-at HEAD) \
|
||||
--path="./path/to/local/manifests" \
|
||||
--source="$(git config --get remote.origin.url)" \
|
||||
--revision="$(git tag --points-at HEAD)@sha1:$(git rev-parse HEAD)" \
|
||||
@@ -104,6 +114,7 @@ type pushArtifactFlags struct {
|
||||
ignorePaths []string
|
||||
annotations []string
|
||||
output string
|
||||
debug bool
|
||||
}
|
||||
|
||||
var pushArtifactArgs = newPushArtifactFlags()
|
||||
@@ -124,6 +135,7 @@ func init() {
|
||||
pushArtifactCmd.Flags().StringArrayVarP(&pushArtifactArgs.annotations, "annotations", "a", nil, "Set custom OCI annotations in the format '<key>=<value>'")
|
||||
pushArtifactCmd.Flags().StringVarP(&pushArtifactArgs.output, "output", "o", "",
|
||||
"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")
|
||||
|
||||
pushCmd.AddCommand(pushArtifactCmd)
|
||||
}
|
||||
@@ -146,7 +158,12 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("invalid path %q", pushArtifactArgs.path)
|
||||
}
|
||||
|
||||
url, err := oci.ParseArtifactURL(ociURL)
|
||||
url, err := client.ParseArtifactURL(ociURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ref, err := name.ParseReference(url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -174,7 +191,13 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
annotations[kv[0]] = kv[1]
|
||||
}
|
||||
|
||||
meta := oci.Metadata{
|
||||
if pushArtifactArgs.debug {
|
||||
// direct logs from crane library to stderr
|
||||
// this can be useful to figure out things happening underneath e.g when the library is retrying a request
|
||||
logs.Warn.SetOutput(os.Stderr)
|
||||
}
|
||||
|
||||
meta := client.Metadata{
|
||||
Source: pushArtifactArgs.source,
|
||||
Revision: pushArtifactArgs.revision,
|
||||
Annotations: annotations,
|
||||
@@ -183,13 +206,15 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
ociClient := oci.NewLocalClient()
|
||||
|
||||
var auth authn.Authenticator
|
||||
opts := client.DefaultOptions()
|
||||
if pushArtifactArgs.provider.String() == sourcev1.GenericOCIProvider && pushArtifactArgs.creds != "" {
|
||||
logger.Actionf("logging in to registry with credentials")
|
||||
if err := ociClient.LoginWithCredentials(pushArtifactArgs.creds); err != nil {
|
||||
auth, err = client.GetAuthFromCredentials(pushArtifactArgs.creds)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not login with credentials: %w", err)
|
||||
}
|
||||
opts = append(opts, crane.WithAuth(auth))
|
||||
}
|
||||
|
||||
if pushArtifactArgs.provider.String() != sourcev1.GenericOCIProvider {
|
||||
@@ -199,15 +224,43 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
return fmt.Errorf("provider not supported: %w", err)
|
||||
}
|
||||
|
||||
if err := ociClient.LoginWithProvider(ctx, url, ociProvider); err != nil {
|
||||
auth, err = login.NewManager().Login(ctx, url, ref, getProviderLoginOption(ociProvider))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error during login with provider: %w", err)
|
||||
}
|
||||
opts = append(opts, crane.WithAuth(auth))
|
||||
}
|
||||
|
||||
if rootArgs.timeout != 0 {
|
||||
backoff := remote.Backoff{
|
||||
Duration: 1.0 * time.Second,
|
||||
Factor: 3,
|
||||
Jitter: 0.1,
|
||||
// timeout happens when the cap is exceeded or number of steps is reached
|
||||
// 10 steps is big enough that most reasonable cap(under 30min) will be exceeded before
|
||||
// the number of steps are completed.
|
||||
Steps: 10,
|
||||
Cap: rootArgs.timeout,
|
||||
}
|
||||
|
||||
if auth == nil {
|
||||
auth, err = authn.DefaultKeychain.Resolve(ref.Context())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
transportOpts, err := client.WithRetryTransport(ctx, ref, auth, backoff, []string{ref.Context().Scope(transport.PushScope)})
|
||||
if err != nil {
|
||||
return fmt.Errorf("error setting up transport: %w", err)
|
||||
}
|
||||
opts = append(opts, transportOpts, client.WithRetryBackOff(backoff))
|
||||
}
|
||||
|
||||
if pushArtifactArgs.output == "" {
|
||||
logger.Actionf("pushing artifact to %s", url)
|
||||
}
|
||||
|
||||
ociClient := client.NewClient(opts)
|
||||
digestURL, err := ociClient.Push(ctx, url, path, meta, pushArtifactArgs.ignorePaths)
|
||||
if err != nil {
|
||||
return fmt.Errorf("pushing artifact failed: %w", err)
|
||||
@@ -255,3 +308,16 @@ func pushArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func getProviderLoginOption(provider oci.Provider) login.ProviderOptions {
|
||||
var opts login.ProviderOptions
|
||||
switch provider {
|
||||
case oci.ProviderAzure:
|
||||
opts.AzureAutoLogin = true
|
||||
case oci.ProviderAWS:
|
||||
opts.AwsAutoLogin = true
|
||||
case oci.ProviderGCP:
|
||||
opts.GcpAutoLogin = true
|
||||
}
|
||||
return opts
|
||||
}
|
||||
|
||||
@@ -17,11 +17,12 @@ limitations under the License.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
@@ -63,28 +64,20 @@ func (obj helmReleaseAdapter) reconcileSource() bool {
|
||||
return rhrArgs.syncHrWithSource
|
||||
}
|
||||
|
||||
func (obj helmReleaseAdapter) getSource() (reconcileCommand, types.NamespacedName) {
|
||||
var cmd reconcileCommand
|
||||
switch obj.Spec.Chart.Spec.SourceRef.Kind {
|
||||
case sourcev1b2.HelmRepositoryKind:
|
||||
cmd = reconcileCommand{
|
||||
apiType: helmRepositoryType,
|
||||
object: helmRepositoryAdapter{&sourcev1b2.HelmRepository{}},
|
||||
}
|
||||
case sourcev1.GitRepositoryKind:
|
||||
cmd = reconcileCommand{
|
||||
apiType: gitRepositoryType,
|
||||
object: gitRepositoryAdapter{&sourcev1.GitRepository{}},
|
||||
}
|
||||
case sourcev1b2.BucketKind:
|
||||
cmd = reconcileCommand{
|
||||
apiType: bucketType,
|
||||
object: bucketAdapter{&sourcev1b2.Bucket{}},
|
||||
}
|
||||
func (obj helmReleaseAdapter) getSource() (reconcileSource, types.NamespacedName) {
|
||||
cmd := reconcileWithSourceCommand{
|
||||
apiType: helmChartType,
|
||||
object: helmChartAdapter{&sourcev1b2.HelmChart{}},
|
||||
force: true,
|
||||
}
|
||||
|
||||
ns := obj.Spec.Chart.Spec.SourceRef.Namespace
|
||||
if ns == "" {
|
||||
ns = obj.Namespace
|
||||
}
|
||||
|
||||
return cmd, types.NamespacedName{
|
||||
Name: obj.Spec.Chart.Spec.SourceRef.Name,
|
||||
Namespace: obj.Spec.Chart.Spec.SourceRef.Namespace,
|
||||
Name: fmt.Sprintf("%s-%s", obj.Namespace, obj.Name),
|
||||
Namespace: ns,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ func (obj kustomizationAdapter) reconcileSource() bool {
|
||||
return rksArgs.syncKsWithSource
|
||||
}
|
||||
|
||||
func (obj kustomizationAdapter) getSource() (reconcileCommand, types.NamespacedName) {
|
||||
func (obj kustomizationAdapter) getSource() (reconcileSource, types.NamespacedName) {
|
||||
var cmd reconcileCommand
|
||||
switch obj.Spec.SourceRef.Kind {
|
||||
case sourcev1b2.OCIRepositoryKind:
|
||||
|
||||
86
cmd/flux/reconcile_source_chart.go
Normal file
86
cmd/flux/reconcile_source_chart.go
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
Copyright 2020 The Flux authors
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
sourcev1 "github.com/fluxcd/source-controller/api/v1"
|
||||
sourcev1b2 "github.com/fluxcd/source-controller/api/v1beta2"
|
||||
)
|
||||
|
||||
var reconcileSourceHelmChartCmd = &cobra.Command{
|
||||
Use: "chart [name]",
|
||||
Short: "Reconcile a HelmChart source",
|
||||
Long: `The reconcile source command triggers a reconciliation of a HelmChart resource and waits for it to finish.`,
|
||||
Example: ` # Trigger a reconciliation for an existing source
|
||||
flux reconcile source chart podinfo
|
||||
|
||||
# Trigger a reconciliation of the HelmCharts's source and apply changes
|
||||
flux reconcile helmchart podinfo --with-source`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1b2.GroupVersion.WithKind(sourcev1b2.HelmChartKind)),
|
||||
RunE: reconcileWithSourceCommand{
|
||||
apiType: helmChartType,
|
||||
object: helmChartAdapter{&sourcev1b2.HelmChart{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
func init() {
|
||||
reconcileSourceHelmChartCmd.Flags().BoolVar(&rhcArgs.syncHrWithSource, "with-source", false, "reconcile HelmChart source")
|
||||
reconcileSourceCmd.AddCommand(reconcileSourceHelmChartCmd)
|
||||
}
|
||||
|
||||
func (obj helmChartAdapter) lastHandledReconcileRequest() string {
|
||||
return obj.Status.GetLastHandledReconcileRequest()
|
||||
}
|
||||
|
||||
type reconcileHelmChartFlags struct {
|
||||
syncHrWithSource bool
|
||||
}
|
||||
|
||||
var rhcArgs reconcileHelmChartFlags
|
||||
|
||||
func (obj helmChartAdapter) reconcileSource() bool {
|
||||
return rhcArgs.syncHrWithSource
|
||||
}
|
||||
|
||||
func (obj helmChartAdapter) getSource() (reconcileSource, types.NamespacedName) {
|
||||
var cmd reconcileCommand
|
||||
switch obj.Spec.SourceRef.Kind {
|
||||
case sourcev1b2.HelmRepositoryKind:
|
||||
cmd = reconcileCommand{
|
||||
apiType: helmRepositoryType,
|
||||
object: helmRepositoryAdapter{&sourcev1b2.HelmRepository{}},
|
||||
}
|
||||
case sourcev1.GitRepositoryKind:
|
||||
cmd = reconcileCommand{
|
||||
apiType: gitRepositoryType,
|
||||
object: gitRepositoryAdapter{&sourcev1.GitRepository{}},
|
||||
}
|
||||
case sourcev1b2.BucketKind:
|
||||
cmd = reconcileCommand{
|
||||
apiType: bucketType,
|
||||
object: bucketAdapter{&sourcev1b2.Bucket{}},
|
||||
}
|
||||
}
|
||||
|
||||
return cmd, types.NamespacedName{
|
||||
Name: obj.Spec.SourceRef.Name,
|
||||
Namespace: obj.Namespace,
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,17 @@ type reconcileWithSource interface {
|
||||
adapter
|
||||
reconcilable
|
||||
reconcileSource() bool
|
||||
getSource() (reconcileCommand, types.NamespacedName)
|
||||
getSource() (reconcileSource, types.NamespacedName)
|
||||
}
|
||||
|
||||
type reconcileSource interface {
|
||||
run(cmd *cobra.Command, args []string) error
|
||||
}
|
||||
|
||||
type reconcileWithSourceCommand struct {
|
||||
apiType
|
||||
object reconcileWithSource
|
||||
force bool
|
||||
}
|
||||
|
||||
func (reconcile reconcileWithSourceCommand) run(cmd *cobra.Command, args []string) error {
|
||||
@@ -54,7 +59,7 @@ func (reconcile reconcileWithSourceCommand) run(cmd *cobra.Command, args []strin
|
||||
return fmt.Errorf("resource is suspended")
|
||||
}
|
||||
|
||||
if reconcile.object.reconcileSource() {
|
||||
if reconcile.object.reconcileSource() || reconcile.force {
|
||||
reconcileCmd, nsName := reconcile.object.getSource()
|
||||
nsCopy := *kubeconfigArgs.Namespace
|
||||
if nsName.Namespace != "" {
|
||||
|
||||
@@ -19,6 +19,8 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
@@ -59,8 +61,10 @@ type resumable interface {
|
||||
|
||||
type resumeCommand struct {
|
||||
apiType
|
||||
object resumable
|
||||
list listResumable
|
||||
client client.WithWatch
|
||||
list listResumable
|
||||
namespace string
|
||||
shouldReconcile bool
|
||||
}
|
||||
|
||||
type listResumable interface {
|
||||
@@ -68,6 +72,11 @@ type listResumable interface {
|
||||
resumeItem(i int) resumable
|
||||
}
|
||||
|
||||
type reconcileResponse struct {
|
||||
resumable
|
||||
err error
|
||||
}
|
||||
|
||||
func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
|
||||
if len(args) < 1 && !resumeArgs.all {
|
||||
return fmt.Errorf("%s name is required", resume.humanKind)
|
||||
@@ -80,52 +89,162 @@ func (resume resumeCommand) run(cmd *cobra.Command, args []string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resume.client = kubeClient
|
||||
resume.namespace = *kubeconfigArgs.Namespace
|
||||
|
||||
var listOpts []client.ListOption
|
||||
listOpts = append(listOpts, client.InNamespace(*kubeconfigArgs.Namespace))
|
||||
if len(args) > 0 {
|
||||
listOpts = append(listOpts, client.MatchingFields{
|
||||
"metadata.name": args[0],
|
||||
})
|
||||
}
|
||||
// require waiting for the object(s) if the user has not provided the --wait flag and gave exactly
|
||||
// one object to resume. This is necessary to maintain backwards compatibility with prior versions
|
||||
// of this command. Otherwise just follow the value of the --wait flag (including its default).
|
||||
resume.shouldReconcile = !resumeCmd.PersistentFlags().Changed("wait") && len(args) == 1 || resumeArgs.wait
|
||||
|
||||
err = kubeClient.List(ctx, resume.list.asClientList(), listOpts...)
|
||||
resumables, err := resume.getPatchedResumables(ctx, args)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if resume.list.len() == 0 {
|
||||
logger.Failuref("no %s objects found in %s namespace", resume.kind, *kubeconfigArgs.Namespace)
|
||||
return nil
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(len(resumables))
|
||||
|
||||
resultChan := make(chan reconcileResponse, len(resumables))
|
||||
for _, r := range resumables {
|
||||
go func(res resumable) {
|
||||
defer wg.Done()
|
||||
resultChan <- resume.reconcile(ctx, res)
|
||||
}(r)
|
||||
}
|
||||
|
||||
for i := 0; i < resume.list.len(); i++ {
|
||||
logger.Actionf("resuming %s %s in %s namespace", resume.humanKind, resume.list.resumeItem(i).asClientObject().GetName(), *kubeconfigArgs.Namespace)
|
||||
obj := resume.list.resumeItem(i)
|
||||
patch := client.MergeFrom(obj.deepCopyClientObject())
|
||||
obj.setUnsuspended()
|
||||
if err := kubeClient.Patch(ctx, obj.asClientObject(), patch); err != nil {
|
||||
return err
|
||||
}
|
||||
go func() {
|
||||
defer close(resultChan)
|
||||
wg.Wait()
|
||||
}()
|
||||
|
||||
logger.Successf("%s resumed", resume.humanKind)
|
||||
|
||||
if resumeArgs.wait || !resumeArgs.all {
|
||||
namespacedName := types.NamespacedName{
|
||||
Name: resume.list.resumeItem(i).asClientObject().GetName(),
|
||||
Namespace: *kubeconfigArgs.Namespace,
|
||||
}
|
||||
|
||||
logger.Waitingf("waiting for %s reconciliation", resume.kind)
|
||||
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
|
||||
isReady(ctx, kubeClient, namespacedName, resume.list.resumeItem(i))); err != nil {
|
||||
logger.Failuref(err.Error())
|
||||
continue
|
||||
}
|
||||
logger.Successf("%s reconciliation completed", resume.kind)
|
||||
logger.Successf(resume.list.resumeItem(i).successMessage())
|
||||
}
|
||||
reconcileResps := make([]reconcileResponse, 0, len(resumables))
|
||||
for c := range resultChan {
|
||||
reconcileResps = append(reconcileResps, c)
|
||||
}
|
||||
|
||||
resume.printMessage(reconcileResps)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getPatchedResumables returns a list of the given resumable objects that have been patched to be resumed.
|
||||
// If the args slice is empty, it patches all resumable objects in the given namespace.
|
||||
func (resume *resumeCommand) getPatchedResumables(ctx context.Context, args []string) ([]resumable, error) {
|
||||
if len(args) < 1 {
|
||||
objs, err := resume.patch(ctx, []client.ListOption{
|
||||
client.InNamespace(resume.namespace),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed patching objects: %w", err)
|
||||
}
|
||||
|
||||
return objs, nil
|
||||
}
|
||||
|
||||
var resumables []resumable
|
||||
processed := make(map[string]struct{}, len(args))
|
||||
for _, arg := range args {
|
||||
if _, has := processed[arg]; has {
|
||||
continue // skip object that user might have provided more than once
|
||||
}
|
||||
processed[arg] = struct{}{}
|
||||
|
||||
objs, err := resume.patch(ctx, []client.ListOption{
|
||||
client.InNamespace(resume.namespace),
|
||||
client.MatchingFields{
|
||||
"metadata.name": arg,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resumables = append(resumables, objs...)
|
||||
}
|
||||
|
||||
return resumables, nil
|
||||
}
|
||||
|
||||
// Patches resumable objects by setting their status to unsuspended.
|
||||
// Returns a slice of resumables that have been patched and any error encountered during patching.
|
||||
func (resume resumeCommand) patch(ctx context.Context, listOpts []client.ListOption) ([]resumable, error) {
|
||||
if err := resume.client.List(ctx, resume.list.asClientList(), listOpts...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resume.list.len() == 0 {
|
||||
logger.Failuref("no %s objects found in %s namespace", resume.kind, resume.namespace)
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var resumables []resumable
|
||||
|
||||
for i := 0; i < resume.list.len(); i++ {
|
||||
obj := resume.list.resumeItem(i)
|
||||
logger.Actionf("resuming %s %s in %s namespace", resume.humanKind, obj.asClientObject().GetName(), resume.namespace)
|
||||
|
||||
patch := client.MergeFrom(obj.deepCopyClientObject())
|
||||
obj.setUnsuspended()
|
||||
if err := resume.client.Patch(ctx, obj.asClientObject(), patch); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
resumables = append(resumables, obj)
|
||||
|
||||
logger.Successf("%s resumed", resume.humanKind)
|
||||
}
|
||||
|
||||
return resumables, nil
|
||||
}
|
||||
|
||||
// Waits for resumable object to be reconciled and returns the object and any error encountered while waiting.
|
||||
// Returns an empty reconcileResponse, if shouldReconcile is false.
|
||||
func (resume resumeCommand) reconcile(ctx context.Context, res resumable) reconcileResponse {
|
||||
if !resume.shouldReconcile {
|
||||
return reconcileResponse{}
|
||||
}
|
||||
|
||||
namespacedName := types.NamespacedName{
|
||||
Name: res.asClientObject().GetName(),
|
||||
Namespace: resume.namespace,
|
||||
}
|
||||
|
||||
logger.Waitingf("waiting for %s reconciliation", resume.kind)
|
||||
|
||||
if err := wait.PollImmediate(rootArgs.pollInterval, rootArgs.timeout,
|
||||
isReady(ctx, resume.client, namespacedName, res)); err != nil {
|
||||
return reconcileResponse{
|
||||
resumable: res,
|
||||
err: err,
|
||||
}
|
||||
}
|
||||
|
||||
return reconcileResponse{
|
||||
resumable: res,
|
||||
err: nil,
|
||||
}
|
||||
}
|
||||
|
||||
// Sorts the given reconcileResponses by resumable name and prints the success/error message for each response.
|
||||
func (resume resumeCommand) printMessage(responses []reconcileResponse) {
|
||||
sort.Slice(responses, func(i, j int) bool {
|
||||
r1, r2 := responses[i], responses[j]
|
||||
if r1.resumable == nil || r2.resumable == nil {
|
||||
return false
|
||||
}
|
||||
return r1.asClientObject().GetName() <= r2.asClientObject().GetName()
|
||||
})
|
||||
|
||||
// Print success/error message.
|
||||
for _, r := range responses {
|
||||
if r.resumable == nil {
|
||||
continue
|
||||
}
|
||||
if r.err != nil {
|
||||
logger.Failuref(r.err.Error())
|
||||
}
|
||||
logger.Successf("%s %s reconciliation completed", resume.kind, r.asClientObject().GetName())
|
||||
logger.Successf(r.successMessage())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,11 +28,13 @@ var resumeAlertCmd = &cobra.Command{
|
||||
Long: `The resume command marks a previously suspended Alert resource for reconciliation and waits for it to
|
||||
finish the apply.`,
|
||||
Example: ` # Resume reconciliation for an existing Alert
|
||||
flux resume alert main`,
|
||||
flux resume alert main
|
||||
|
||||
# Resume reconciliation for multiple Alerts
|
||||
flux resume alert main-1 main-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(notificationv1.GroupVersion.WithKind(notificationv1.AlertKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: alertType,
|
||||
object: alertAdapter{¬ificationv1.Alert{}},
|
||||
list: &alertListAdapter{¬ificationv1.AlertList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -31,11 +31,13 @@ var resumeHrCmd = &cobra.Command{
|
||||
Long: `The resume command marks a previously suspended HelmRelease resource for reconciliation and waits for it to
|
||||
finish the apply.`,
|
||||
Example: ` # Resume reconciliation for an existing Helm release
|
||||
flux resume hr podinfo`,
|
||||
flux resume hr podinfo
|
||||
|
||||
# Resume reconciliation for multiple Helm releases
|
||||
flux resume hr podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: helmReleaseType,
|
||||
object: helmReleaseAdapter{&helmv2.HelmRelease{}},
|
||||
list: helmReleaseListAdapter{&helmv2.HelmReleaseList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeImageRepositoryCmd = &cobra.Command{
|
||||
Short: "Resume a suspended ImageRepository",
|
||||
Long: `The resume command marks a previously suspended ImageRepository resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing ImageRepository
|
||||
flux resume image repository alpine`,
|
||||
flux resume image repository alpine
|
||||
|
||||
# Resume reconciliation for multiple ImageRepositories
|
||||
flux resume image repository alpine-1 alpine-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: imageRepositoryType,
|
||||
object: imageRepositoryAdapter{&imagev1.ImageRepository{}},
|
||||
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeImageUpdateCmd = &cobra.Command{
|
||||
Short: "Resume a suspended ImageUpdateAutomation",
|
||||
Long: `The resume command marks a previously suspended ImageUpdateAutomation resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing ImageUpdateAutomation
|
||||
flux resume image update latest-images`,
|
||||
flux resume image update latest-images
|
||||
|
||||
# Resume reconciliation for multiple ImageUpdateAutomations
|
||||
flux resume image update latest-images-1 latest-images-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(autov1.GroupVersion.WithKind(autov1.ImageUpdateAutomationKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: imageUpdateAutomationType,
|
||||
object: imageUpdateAutomationAdapter{&autov1.ImageUpdateAutomation{}},
|
||||
list: imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -31,11 +31,13 @@ var resumeKsCmd = &cobra.Command{
|
||||
Long: `The resume command marks a previously suspended Kustomization resource for reconciliation and waits for it to
|
||||
finish the apply.`,
|
||||
Example: ` # Resume reconciliation for an existing Kustomization
|
||||
flux resume ks podinfo`,
|
||||
flux resume ks podinfo
|
||||
|
||||
# Resume reconciliation for multiple Kustomizations
|
||||
flux resume ks podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: kustomizationType,
|
||||
object: kustomizationAdapter{&kustomizev1.Kustomization{}},
|
||||
list: kustomizationListAdapter{&kustomizev1.KustomizationList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -28,11 +28,13 @@ var resumeReceiverCmd = &cobra.Command{
|
||||
Long: `The resume command marks a previously suspended Receiver resource for reconciliation and waits for it to
|
||||
finish the apply.`,
|
||||
Example: ` # Resume reconciliation for an existing Receiver
|
||||
flux resume receiver main`,
|
||||
flux resume receiver main
|
||||
|
||||
# Resume reconciliation for multiple Receivers
|
||||
flux resume receiver main-1 main-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(notificationv1.GroupVersion.WithKind(notificationv1.ReceiverKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: receiverType,
|
||||
object: receiverAdapter{¬ificationv1.Receiver{}},
|
||||
list: receiverListAdapter{¬ificationv1.ReceiverList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeSourceBucketCmd = &cobra.Command{
|
||||
Short: "Resume a suspended Bucket",
|
||||
Long: `The resume command marks a previously suspended Bucket resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing Bucket
|
||||
flux resume source bucket podinfo`,
|
||||
flux resume source bucket podinfo
|
||||
|
||||
# Resume reconciliation for multiple Buckets
|
||||
flux resume source bucket podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.BucketKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: bucketType,
|
||||
object: bucketAdapter{&sourcev1.Bucket{}},
|
||||
list: bucketListAdapter{&sourcev1.BucketList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -29,11 +29,13 @@ var resumeSourceHelmChartCmd = &cobra.Command{
|
||||
Short: "Resume a suspended HelmChart",
|
||||
Long: `The resume command marks a previously suspended HelmChart resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing HelmChart
|
||||
flux resume source chart podinfo`,
|
||||
flux resume source chart podinfo
|
||||
|
||||
# Resume reconciliation for multiple HelmCharts
|
||||
flux resume source chart podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: helmChartType,
|
||||
object: &helmChartAdapter{&sourcev1.HelmChart{}},
|
||||
list: &helmChartListAdapter{&sourcev1.HelmChartList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeSourceGitCmd = &cobra.Command{
|
||||
Short: "Resume a suspended GitRepository",
|
||||
Long: `The resume command marks a previously suspended GitRepository resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing GitRepository
|
||||
flux resume source git podinfo`,
|
||||
flux resume source git podinfo
|
||||
|
||||
# Resume reconciliation for multiple GitRepositories
|
||||
flux resume source git podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: gitRepositoryType,
|
||||
object: gitRepositoryAdapter{&sourcev1.GitRepository{}},
|
||||
list: gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeSourceHelmCmd = &cobra.Command{
|
||||
Short: "Resume a suspended HelmRepository",
|
||||
Long: `The resume command marks a previously suspended HelmRepository resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing HelmRepository
|
||||
flux resume source helm bitnami`,
|
||||
flux resume source helm bitnami
|
||||
|
||||
# Resume reconciliation for multiple HelmRepositories
|
||||
flux resume source helm bitnami-1 bitnami-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: helmRepositoryType,
|
||||
object: helmRepositoryAdapter{&sourcev1.HelmRepository{}},
|
||||
list: helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -27,11 +27,13 @@ var resumeSourceOCIRepositoryCmd = &cobra.Command{
|
||||
Short: "Resume a suspended OCIRepository",
|
||||
Long: `The resume command marks a previously suspended OCIRepository resource for reconciliation and waits for it to finish.`,
|
||||
Example: ` # Resume reconciliation for an existing OCIRepository
|
||||
flux resume source oci podinfo`,
|
||||
flux resume source oci podinfo
|
||||
|
||||
# Resume reconciliation for multiple OCIRepositories
|
||||
flux resume source oci podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)),
|
||||
RunE: resumeCommand{
|
||||
apiType: ociRepositoryType,
|
||||
object: ociRepositoryAdapter{&sourcev1.OCIRepository{}},
|
||||
list: ociRepositoryListAdapter{&sourcev1.OCIRepositoryList{}},
|
||||
}.run,
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
@@ -75,22 +76,53 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
var listOpts []client.ListOption
|
||||
listOpts = append(listOpts, client.InNamespace(*kubeconfigArgs.Namespace))
|
||||
if len(args) > 0 {
|
||||
listOpts = append(listOpts, client.MatchingFields{
|
||||
"metadata.name": args[0],
|
||||
})
|
||||
if len(args) < 1 && suspendArgs.all {
|
||||
listOpts := []client.ListOption{
|
||||
client.InNamespace(*kubeconfigArgs.Namespace),
|
||||
}
|
||||
|
||||
if err := suspend.patch(ctx, kubeClient, listOpts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
err = kubeClient.List(ctx, suspend.list.asClientList(), listOpts...)
|
||||
if err != nil {
|
||||
processed := make(map[string]struct{}, len(args))
|
||||
for _, arg := range args {
|
||||
if _, has := processed[arg]; has {
|
||||
continue // skip object that user might have provided more than once
|
||||
}
|
||||
processed[arg] = struct{}{}
|
||||
|
||||
listOpts := []client.ListOption{
|
||||
client.InNamespace(*kubeconfigArgs.Namespace),
|
||||
client.MatchingFields{
|
||||
"metadata.name": arg,
|
||||
},
|
||||
}
|
||||
|
||||
if err := suspend.patch(ctx, kubeClient, listOpts); err != nil {
|
||||
if err == ErrNoObjectsFound {
|
||||
logger.Failuref("%s %s not found in %s namespace", suspend.kind, arg, *kubeconfigArgs.Namespace)
|
||||
} else {
|
||||
logger.Failuref("failed suspending %s %s in %s namespace: %s", suspend.kind, arg, *kubeconfigArgs.Namespace, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var ErrNoObjectsFound = errors.New("no objects found")
|
||||
|
||||
func (suspend suspendCommand) patch(ctx context.Context, kubeClient client.WithWatch, listOpts []client.ListOption) error {
|
||||
if err := kubeClient.List(ctx, suspend.list.asClientList(), listOpts...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if suspend.list.len() == 0 {
|
||||
logger.Failuref("no %s objects found in %s namespace", suspend.kind, *kubeconfigArgs.Namespace)
|
||||
return nil
|
||||
return ErrNoObjectsFound
|
||||
}
|
||||
|
||||
for i := 0; i < suspend.list.len(); i++ {
|
||||
@@ -102,8 +134,8 @@ func (suspend suspendCommand) run(cmd *cobra.Command, args []string) error {
|
||||
if err := kubeClient.Patch(ctx, obj.asClientObject(), patch); err != nil {
|
||||
return err
|
||||
}
|
||||
logger.Successf("%s suspended", suspend.humanKind)
|
||||
|
||||
logger.Successf("%s suspended", suspend.humanKind)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendAlertCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of Alert",
|
||||
Long: `The suspend command disables the reconciliation of a Alert resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Alert
|
||||
flux suspend alert main`,
|
||||
flux suspend alert main
|
||||
|
||||
# Suspend reconciliation for multiple Alerts
|
||||
flux suspend alert main-1 main-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(notificationv1.GroupVersion.WithKind(notificationv1.AlertKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: alertType,
|
||||
|
||||
@@ -28,7 +28,10 @@ var suspendHrCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of HelmRelease",
|
||||
Long: `The suspend command disables the reconciliation of a HelmRelease resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Helm release
|
||||
flux suspend hr podinfo`,
|
||||
flux suspend hr podinfo
|
||||
|
||||
# Suspend reconciliation for multiple Helm releases
|
||||
flux suspend hr podinfo-1 podinfo-2 `,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(helmv2.GroupVersion.WithKind(helmv2.HelmReleaseKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: helmReleaseType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendImageRepositoryCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of an ImageRepository",
|
||||
Long: `The suspend image repository command disables the reconciliation of a ImageRepository resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing ImageRepository
|
||||
flux suspend image repository alpine`,
|
||||
flux suspend image repository alpine
|
||||
|
||||
# Suspend reconciliation for multiple ImageRepositories
|
||||
flux suspend image repository alpine-1 alpine-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(imagev1.GroupVersion.WithKind(imagev1.ImageRepositoryKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: imageRepositoryType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendImageUpdateCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of an ImageUpdateAutomation",
|
||||
Long: `The suspend image update command disables the reconciliation of a ImageUpdateAutomation resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing ImageUpdateAutomation
|
||||
flux suspend image update latest-images`,
|
||||
flux suspend image update latest-images
|
||||
|
||||
# Suspend reconciliation for multiple ImageUpdateAutomations
|
||||
flux suspend image update latest-images-1 latest-images-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(autov1.GroupVersion.WithKind(autov1.ImageUpdateAutomationKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: imageUpdateAutomationType,
|
||||
|
||||
@@ -28,7 +28,10 @@ var suspendKsCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of Kustomization",
|
||||
Long: `The suspend command disables the reconciliation of a Kustomization resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Kustomization
|
||||
flux suspend ks podinfo`,
|
||||
flux suspend ks podinfo
|
||||
|
||||
# Suspend reconciliation for multiple Kustomizations
|
||||
flux suspend ks podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(kustomizev1.GroupVersion.WithKind(kustomizev1.KustomizationKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: kustomizationType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendReceiverCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of Receiver",
|
||||
Long: `The suspend command disables the reconciliation of a Receiver resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Receiver
|
||||
flux suspend receiver main`,
|
||||
flux suspend receiver main
|
||||
|
||||
# Suspend reconciliation for multiple Receivers
|
||||
flux suspend receiver main-1 main-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(notificationv1.GroupVersion.WithKind(notificationv1.ReceiverKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: receiverType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceBucketCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of a Bucket",
|
||||
Long: `The suspend command disables the reconciliation of a Bucket resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing Bucket
|
||||
flux suspend source bucket podinfo`,
|
||||
flux suspend source bucket podinfo
|
||||
|
||||
# Suspend reconciliation for multiple Buckets
|
||||
flux suspend source bucket podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.BucketKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: bucketType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceHelmChartCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of a HelmChart",
|
||||
Long: `The suspend command disables the reconciliation of a HelmChart resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing HelmChart
|
||||
flux suspend source chart podinfo`,
|
||||
flux suspend source chart podinfo
|
||||
|
||||
# Suspend reconciliation for multiple HelmCharts
|
||||
flux suspend source chart podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmChartKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: helmChartType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceGitCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of a GitRepository",
|
||||
Long: `The suspend command disables the reconciliation of a GitRepository resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing GitRepository
|
||||
flux suspend source git podinfo`,
|
||||
flux suspend source git podinfo
|
||||
|
||||
# Suspend reconciliation for multiple GitRepositories
|
||||
flux suspend source git podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.GitRepositoryKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: gitRepositoryType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceHelmCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of a HelmRepository",
|
||||
Long: `The suspend command disables the reconciliation of a HelmRepository resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing HelmRepository
|
||||
flux suspend source helm bitnami`,
|
||||
flux suspend source helm bitnami
|
||||
|
||||
# Suspend reconciliation for multiple HelmRepositories
|
||||
flux suspend source helm bitnami-1 bitnami-2 `,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.HelmRepositoryKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: helmRepositoryType,
|
||||
|
||||
@@ -27,7 +27,10 @@ var suspendSourceOCIRepositoryCmd = &cobra.Command{
|
||||
Short: "Suspend reconciliation of an OCIRepository",
|
||||
Long: `The suspend command disables the reconciliation of an OCIRepository resource.`,
|
||||
Example: ` # Suspend reconciliation for an existing OCIRepository
|
||||
flux suspend source oci podinfo`,
|
||||
flux suspend source oci podinfo
|
||||
|
||||
# Suspend reconciliation for multiple OCIRepositories
|
||||
flux suspend source oci podinfo-1 podinfo-2`,
|
||||
ValidArgsFunction: resourceNamesCompletionFunc(sourcev1.GroupVersion.WithKind(sourcev1.OCIRepositoryKind)),
|
||||
RunE: suspendCommand{
|
||||
apiType: ociRepositoryType,
|
||||
|
||||
@@ -78,7 +78,7 @@ func tagArtifactCmdRun(cmd *cobra.Command, args []string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
|
||||
defer cancel()
|
||||
|
||||
ociClient := oci.NewLocalClient()
|
||||
ociClient := oci.NewClient(oci.DefaultOptions())
|
||||
|
||||
if tagArtifactArgs.provider.String() == sourcev1.GenericOCIProvider && tagArtifactArgs.creds != "" {
|
||||
logger.Actionf("logging in to registry with credentials")
|
||||
|
||||
2
cmd/flux/testdata/check/check_pre.golden
vendored
2
cmd/flux/testdata/check/check_pre.golden
vendored
@@ -1,3 +1,3 @@
|
||||
► checking prerequisites
|
||||
✔ Kubernetes {{ .serverVersion }} >=1.20.6-0
|
||||
✔ Kubernetes {{ .serverVersion }} >=1.25.0-0
|
||||
✔ prerequisites checks passed
|
||||
|
||||
11
cmd/flux/testdata/create_secret/git/secret-ca-crt.yaml
vendored
Normal file
11
cmd/flux/testdata/create_secret/git/secret-ca-crt.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: ca-crt
|
||||
namespace: my-namespace
|
||||
stringData:
|
||||
ca.crt: ca-data
|
||||
password: my-password
|
||||
username: my-username
|
||||
|
||||
107
cmd/flux/testdata/create_secret/tls/deprecated-secret-tls.yaml
vendored
Normal file
107
cmd/flux/testdata/create_secret/tls/deprecated-secret-tls.yaml
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
Flag --cert-file has been deprecated, please use --tls-crt-file instead
|
||||
Flag --key-file has been deprecated, please use --tls-key-file instead
|
||||
Flag --ca-file has been deprecated, please use --ca-crt-file instead
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: certs
|
||||
namespace: my-namespace
|
||||
stringData:
|
||||
caFile: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBhzCCAS2gAwIBAgIUdsAtiX3gN0uk7ddxASWYE/tdv0wwCgYIKoZIzj0EAwIw
|
||||
GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMjUw
|
||||
NDE2MDgxODAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49
|
||||
AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr
|
||||
RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxijUzBRMA4GA1UdDwEB/wQE
|
||||
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQGyUiU1QEZiMAqjsnIYTwZ
|
||||
4yp5wzAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIQDzdtvKdE8O
|
||||
1+WRTZ9MuSiFYcrEz7Zne7VXouDEKqKEigIgM4WlbDeuNCKbqhqj+xZV0pa3rweb
|
||||
OD8EjjCMY69RMO0=
|
||||
-----END CERTIFICATE-----
|
||||
certFile: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFazCCA1OgAwIBAgIUT84jeO/ncOrqI+FY05Fzbg8Ed7MwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
GEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMTA4MDgxNDQyMzVaFw0yMjA4
|
||||
MDgxNDQyMzVaMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEw
|
||||
HwYDVQQKDBhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwggIiMA0GCSqGSIb3DQEB
|
||||
AQUAA4ICDwAwggIKAoICAQDn/rPsZ74oypiwCzLlx57zplTiCi/WLSF+MmLGuTvM
|
||||
EQnV+OND2zFgvDIV/vFs3brkd6rLVI4NcdgSj4YKULCMwwOl45hQPdCTEPJvUhCm
|
||||
M+FuQ0czmEEJSjZtdLFz1B7QB/JemNnbfigxM9mlg58AlBhVJqn8q64wd/kC/W/K
|
||||
JTLJuBiVf12ZiPoPfO4WSxAqD3opZ8gdbmK0KYQAhKjEto6ZrYGisfwU1gt3l8M7
|
||||
sCJSpEkOkpuQgJ8D+xzJS36VXBJQMMP9nAPps+x/rGFplsPMsXEFFiwvR1+FJZwz
|
||||
lg2sJ91bLGZQ7vn74MfsGrxpiJwllRThJyT7C9V0sjb5trT2lEqZlP2dRSJYt7aJ
|
||||
1crEcdGSl6RIKgxSV6Hk8dh/ZaTjrTwaKxVkPo2IeEXy5xrR7DyonOQ6Yes0KOCm
|
||||
JB5yHkFlIVEnLm/HZXEtm3bPHsFgTZuInyBCOMXpUESuVZIw8YK+Vd6AExGPPwZ4
|
||||
n5I/sCDxWII9owIj3LeLzdUG6JoroahhGmo8rgpbJpPnS+VgryQ/raUQjqDzDCuE
|
||||
9vKXKBlSUqK6H9A+NMc0mme7M8/GX7T7ewFGUB/xsdrcO4yXjqHnAe0yLf8epDjC
|
||||
hh76bYqwwinVrmfcNcRxFVJZW2z0gGdgkOkOLaVVb9ggPV2SNAHbN4A+St/iRYR5
|
||||
awIDAQABo1MwUTAdBgNVHQ4EFgQUzMaCqVM30EZFfTeNUIJ5fNPAhaQwHwYDVR0j
|
||||
BBgwFoAUzMaCqVM30EZFfTeNUIJ5fNPAhaQwDwYDVR0TAQH/BAUwAwEB/zANBgkq
|
||||
hkiG9w0BAQsFAAOCAgEAVmk1rXtVkYR1Vs2Va/xrUaGXlFznhPU/Fft44kiEkkLp
|
||||
mLVelWyAqvXYioqssZwuZnTjGz0DQPqzJjqwuGy4CHwPLmhCtfHplrbWo8a0ivYC
|
||||
cL20KfZsG941siUh7LGBjTsq6mWBf2ytlFmg/fg93SgmqcEUAUcdps0JpZD8lgWB
|
||||
ZMstfr6E3jaEus3OsvDD6hJNYZ5clJ5+ynLoWZ99A9JC0U46hmIZpRjbdSvasKpD
|
||||
XrXTdpzyL/Do3znXE/yfoHv4//Rj2CpPHJLYRCIzvuf1mo1fWd53FjHvrbUvaHFz
|
||||
CGuZROd4dC4Rx5nZw2ogIYvJ8m6HpIDkL3pBNSQJtIsvAYEQcotJoa5D/e9fu2Wr
|
||||
+og37oCY4OXzViEBQvyxKD4cajNco1fgGKEaFROADwr3JceGI7Anq5W+xdUvAGNM
|
||||
QuGeCueqNyrJ0CbQ1zEhwgpk/VYfB0u9m0bjMellRlKMdojby+FDCJtAJesx9no4
|
||||
SQXyx+aNHhj3qReysjGNwZvBk1IHL04HAT+ogNiYhTl1J/YON4MB5UN6Y2PxP6uG
|
||||
KvJGPigx4fAwfR/d78o5ngwoH9m+8FUg8+qllJ8XgIbl/VXKTk3G4ceOm4eBmrel
|
||||
DwWuBhELSjtXWPWhMlkiebgejDbAear53Lia2Cc43zx/KuhMHBTlKY/vY4F2YiI=
|
||||
-----END CERTIFICATE-----
|
||||
keyFile: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDn/rPsZ74oypiw
|
||||
CzLlx57zplTiCi/WLSF+MmLGuTvMEQnV+OND2zFgvDIV/vFs3brkd6rLVI4NcdgS
|
||||
j4YKULCMwwOl45hQPdCTEPJvUhCmM+FuQ0czmEEJSjZtdLFz1B7QB/JemNnbfigx
|
||||
M9mlg58AlBhVJqn8q64wd/kC/W/KJTLJuBiVf12ZiPoPfO4WSxAqD3opZ8gdbmK0
|
||||
KYQAhKjEto6ZrYGisfwU1gt3l8M7sCJSpEkOkpuQgJ8D+xzJS36VXBJQMMP9nAPp
|
||||
s+x/rGFplsPMsXEFFiwvR1+FJZwzlg2sJ91bLGZQ7vn74MfsGrxpiJwllRThJyT7
|
||||
C9V0sjb5trT2lEqZlP2dRSJYt7aJ1crEcdGSl6RIKgxSV6Hk8dh/ZaTjrTwaKxVk
|
||||
Po2IeEXy5xrR7DyonOQ6Yes0KOCmJB5yHkFlIVEnLm/HZXEtm3bPHsFgTZuInyBC
|
||||
OMXpUESuVZIw8YK+Vd6AExGPPwZ4n5I/sCDxWII9owIj3LeLzdUG6JoroahhGmo8
|
||||
rgpbJpPnS+VgryQ/raUQjqDzDCuE9vKXKBlSUqK6H9A+NMc0mme7M8/GX7T7ewFG
|
||||
UB/xsdrcO4yXjqHnAe0yLf8epDjChh76bYqwwinVrmfcNcRxFVJZW2z0gGdgkOkO
|
||||
LaVVb9ggPV2SNAHbN4A+St/iRYR5awIDAQABAoICAQCTxuixQ/wbW8IbEWcgeyHD
|
||||
LkaPndGO6jyVeF73GvL+MDRFuj558NvpNLfqzvTWVf9AnQGMd5Xs9oGegRHu7Csp
|
||||
3ucp+moBYv7DT14+jtXQKOgGJpDqSqfS1RUKb/TBRXNDLGy02UScziWoAdE33zmf
|
||||
UraVNwW8z1crxKA3yVw2Na++UqhGQlVLAbfXucqnJLVtNWKpkVQlezUgcfmFovsm
|
||||
Iut+9MjI6/sZAqdXTLKuCKo0XjWzNKwnRecE0CYsCwzc80MvFYEiwQi1C0kwoouC
|
||||
iOi8MKM/jDok+5/a3nQ7X+/ho5sbApNCJpfSXAK9YOJ3ju93+RjNuvORfp4/sW3W
|
||||
OGXw6X30Ym7WS/7oYuwEILyqdyNOvKU7a+17d/W/YA60NOdA4iJI3aTfYFMD3l14
|
||||
Da+D/wkTlEN3Ye7GN21A9AsZwWWiT9G5FOxWWVv7nTPG+Ix5ewehQWt/3DxhSizR
|
||||
inMBizL5xpwx9LRWHnXX277lChYmPFAAMXINl1hnX6s0EY9pSDHN0IddibJkNKBD
|
||||
m1CN37rqxoXQz4zoAyJGfQVkakqe16ayqI9yuQwO6AUkZcD5DYQdz9QYOTnYrQc6
|
||||
6haC3D0Fmqg1s4v+6gpxZA/qTri0gVl/v/NN4Mk2/qWtK33imOedgD+5LXhZdBgJ
|
||||
Mqn53AErG/AT622jvSb5UQKCAQEA/DTGLh0Ct97PCm+c+PxRFyieaHNJLWENKyxp
|
||||
HoWGHfp2Bvt2Vphoi7GpRCM/yta4vCZgZmeWTQ0yBg6iPVPRA6Ho5hqh9OkUYVoh
|
||||
prL3JsIU20jTutYjo2aefO4qXnJfkkXxNO2FElUHDTwtWdlGJQKvlUJwTv6xO19v
|
||||
bQQkhZSpri6gIpi5Nkm2SGEtDofRJ+F6ThbQibEatL6DR00dh39MYQz+tZP5olzn
|
||||
kX5bHEBWB7gy+YxTGF8FdlCSQTBBtNSKsAv3Cxj4qEHm+fu09vnH6fOZKenT2nXD
|
||||
5QE/RpgQzLV1TumCjqLzqwp7bbzH+4mjsXpF3KHBZwnhMnDIRwKCAQEA63wYzjBy
|
||||
no0GBBz0hOWrOwQ/AjUHfi47o3Xvl4RBjZclM171HKH7oMCnQvVKTNq8jvakCZjc
|
||||
UI6i+H4R6aokiFS2xGbC2H3ZlSMFNwhb2xUs/C4Nr7JSOWZBtDy5QBspUsp26f7m
|
||||
9VNVRzCmnxWV9be/1TxHDzDhslNlL5TMejbMorWnrtNG41KWwGtwvv2gApr3894j
|
||||
eJNOh0WGfsMkXUM6+4v4WcCGrdV8Cr6Nvu96ZZe2PWu2dANtAfnxqogXXCoFE6r1
|
||||
vie7hFSfJ2QR/vEbanED4pYGTtGYP1oseScx0u0hLhGLGccVBUNZlRbox4rIOELI
|
||||
v9MLuiOL4YX7vQKCAQAGzMl3HtMe8AP3DRFXaT4qeK7ktA8KCS7YtibTatg14LXj
|
||||
9E25gfx3n7+nlae3qVhrwkEhIbPcuflaTnSzYJonFet4oMkzGEGzakG0A+lEA0Ga
|
||||
s/j5daKaWj71sVo1F7JZ+EbLnYfT+bTp93BllsUcZFkllhf/GUDgD++qKc1uSJbW
|
||||
mm044ZNE0nH2u6ACX0kVYS/yAQ14WO0WaHiTqJGeQKFnkHkhni7B4O1hb923AkkP
|
||||
hjjhn5Xx90Xnbb6zwUBURtLCcmAjzXWO29AFd3Lmoc9xEF9V0PckUb6JYyI4ngr9
|
||||
6fqSuRsLC3u0ZeD0EX322zwtodVWYIodZBfNS1srAoIBAQCjTUPGeUKDQTjS0WGg
|
||||
Z8T/AErRtQSlNFqXWMn2QPlUv2RE460HVi2xpOhZPtFvyqDIY7IOFbtzAfdya7rw
|
||||
V9VN1bGJMdodV+jzy31qVJmerGit2SIUnYz30TnvS80L78oQZ+dfDi4MIuYYoFxs
|
||||
JgQAipS1wz9kAXoCuGKLRJ0og6gVjfPjARE/w55XgiqFyEyWgfFBZOMkUsM6e7Rx
|
||||
Y9Jr+puEpeRsGV9MXafPq6WQq3It0a/HmFLG0TlfDX3RzN6mQ12R7hTM8bDQa/6S
|
||||
yorQSVPB1O3kzDVDo4X5KQd+XPfoVhmUYQYdsjmZlMMi6Og0uMFwgp/Epw6S3uO6
|
||||
WbfhAoIBAQCOp4iIc87GyxWL8u6HrJaqmFlqkfou0hI+y9h6FfzsBYU6y3+gRYdF
|
||||
wr2S9EUAb80kEQ1v0pt9417NOGc1pmYjKCZmDZ7qeGCGk2PR0U59+xJetXBWWhbq
|
||||
5JxcwdRYoHyrmC/LINxzzqYOQbQevbW0zcEskeKfJsOtj9WJt6U9B1YZbE8pu2QV
|
||||
xjvb+YekD2R+n/umV6eiaGfDau+EWudYVTqY0mR7y9hTiFR/KnqSsy2BUjljpacS
|
||||
XBQO4ig7vY8+1+L3w2xpTN95/rXAvB4BbO/DLea9ArikePoSJ+bVTj0YwrKBghep
|
||||
kOvbvVANrpsunlSAcpXm1qkV+G+xPnyJ
|
||||
-----END PRIVATE KEY-----
|
||||
@@ -5,7 +5,19 @@ metadata:
|
||||
name: certs
|
||||
namespace: my-namespace
|
||||
stringData:
|
||||
certFile: |
|
||||
ca.crt: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBhzCCAS2gAwIBAgIUdsAtiX3gN0uk7ddxASWYE/tdv0wwCgYIKoZIzj0EAwIw
|
||||
GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMjUw
|
||||
NDE2MDgxODAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49
|
||||
AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr
|
||||
RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxijUzBRMA4GA1UdDwEB/wQE
|
||||
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQGyUiU1QEZiMAqjsnIYTwZ
|
||||
4yp5wzAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIQDzdtvKdE8O
|
||||
1+WRTZ9MuSiFYcrEz7Zne7VXouDEKqKEigIgM4WlbDeuNCKbqhqj+xZV0pa3rweb
|
||||
OD8EjjCMY69RMO0=
|
||||
-----END CERTIFICATE-----
|
||||
tls.crt: |
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIFazCCA1OgAwIBAgIUT84jeO/ncOrqI+FY05Fzbg8Ed7MwDQYJKoZIhvcNAQEL
|
||||
BQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNVBAoM
|
||||
@@ -37,7 +49,7 @@ stringData:
|
||||
KvJGPigx4fAwfR/d78o5ngwoH9m+8FUg8+qllJ8XgIbl/VXKTk3G4ceOm4eBmrel
|
||||
DwWuBhELSjtXWPWhMlkiebgejDbAear53Lia2Cc43zx/KuhMHBTlKY/vY4F2YiI=
|
||||
-----END CERTIFICATE-----
|
||||
keyFile: |
|
||||
tls.key: |
|
||||
-----BEGIN PRIVATE KEY-----
|
||||
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDn/rPsZ74oypiw
|
||||
CzLlx57zplTiCi/WLSF+MmLGuTvMEQnV+OND2zFgvDIV/vFs3brkd6rLVI4NcdgS
|
||||
@@ -90,3 +102,4 @@ stringData:
|
||||
XBQO4ig7vY8+1+L3w2xpTN95/rXAvB4BbO/DLea9ArikePoSJ+bVTj0YwrKBghep
|
||||
kOvbvVANrpsunlSAcpXm1qkV+G+xPnyJ
|
||||
-----END PRIVATE KEY-----
|
||||
type: kubernetes.io/tls
|
||||
|
||||
11
cmd/flux/testdata/create_secret/tls/test-ca.pem
vendored
Normal file
11
cmd/flux/testdata/create_secret/tls/test-ca.pem
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIBhzCCAS2gAwIBAgIUdsAtiX3gN0uk7ddxASWYE/tdv0wwCgYIKoZIzj0EAwIw
|
||||
GTEXMBUGA1UEAxMOZXhhbXBsZS5jb20gQ0EwHhcNMjAwNDE3MDgxODAwWhcNMjUw
|
||||
NDE2MDgxODAwWjAZMRcwFQYDVQQDEw5leGFtcGxlLmNvbSBDQTBZMBMGByqGSM49
|
||||
AgEGCCqGSM49AwEHA0IABK7h/5D8bV93MmEdhu02JsS6ugB8s6PzRl3PV4xs3Sbr
|
||||
RNkkM59+x3b0iWx/i76qPYpNLoiVUVXQmA9Y+4DbMxijUzBRMA4GA1UdDwEB/wQE
|
||||
AwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBQGyUiU1QEZiMAqjsnIYTwZ
|
||||
4yp5wzAPBgNVHREECDAGhwR/AAABMAoGCCqGSM49BAMCA0gAMEUCIQDzdtvKdE8O
|
||||
1+WRTZ9MuSiFYcrEz7Zne7VXouDEKqKEigIgM4WlbDeuNCKbqhqj+xZV0pa3rweb
|
||||
OD8EjjCMY69RMO0=
|
||||
-----END CERTIFICATE-----
|
||||
19
cmd/flux/testdata/diff-kustomization/flux-kustomization-multiobj.yaml
vendored
Normal file
19
cmd/flux/testdata/diff-kustomization/flux-kustomization-multiobj.yaml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: podinfo
|
||||
|
||||
---
|
||||
apiVersion: kustomize.toolkit.fluxcd.io/v1
|
||||
kind: Kustomization
|
||||
metadata:
|
||||
name: podinfo
|
||||
spec:
|
||||
interval: 5m0s
|
||||
path: ./kustomize
|
||||
force: true
|
||||
prune: true
|
||||
sourceRef:
|
||||
kind: GitRepository
|
||||
name: podinfo
|
||||
targetNamespace: default
|
||||
@@ -2,6 +2,10 @@
|
||||
✔ GitRepository annotated
|
||||
◎ waiting for GitRepository reconciliation
|
||||
✔ fetched revision 6.3.5@sha1:67e2c98a60dc92283531412a9e604dd4bae005a9
|
||||
► annotating HelmChart {{ .ns }}-thrfg in {{ .ns }} namespace
|
||||
✔ HelmChart annotated
|
||||
◎ waiting for HelmChart reconciliation
|
||||
✔ fetched revision 6.3.5
|
||||
► annotating HelmRelease thrfg in {{ .ns }} namespace
|
||||
✔ HelmRelease annotated
|
||||
◎ waiting for HelmRelease reconciliation
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
► resuming helmrelease thrfg in {{ .ns }} namespace
|
||||
✔ helmrelease resumed
|
||||
◎ waiting for HelmRelease reconciliation
|
||||
✔ HelmRelease reconciliation completed
|
||||
✔ HelmRelease thrfg reconciliation completed
|
||||
✔ applied revision 6.3.5
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
► resuming kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization resumed
|
||||
◎ waiting for Kustomization reconciliation
|
||||
✔ Kustomization reconciliation completed
|
||||
✔ Kustomization tkfg reconciliation completed
|
||||
✔ applied revision 6.3.5@sha1:67e2c98a60dc92283531412a9e604dd4bae005a9
|
||||
|
||||
2
cmd/flux/testdata/kustomization/resume_kustomization_from_git_multiple_args.golden
vendored
Normal file
2
cmd/flux/testdata/kustomization/resume_kustomization_from_git_multiple_args.golden
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
► resuming kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization resumed
|
||||
6
cmd/flux/testdata/kustomization/resume_kustomization_from_git_multiple_args_wait.golden
vendored
Normal file
6
cmd/flux/testdata/kustomization/resume_kustomization_from_git_multiple_args_wait.golden
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
► resuming kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization resumed
|
||||
✗ no Kustomization objects found in {{ .ns }} namespace
|
||||
◎ waiting for Kustomization reconciliation
|
||||
✔ Kustomization tkfg reconciliation completed
|
||||
✔ applied revision 6.3.5@sha1:67e2c98a60dc92283531412a9e604dd4bae005a9
|
||||
4
cmd/flux/testdata/kustomization/suspend_kustomization_from_git_multiple_args.golden
vendored
Normal file
4
cmd/flux/testdata/kustomization/suspend_kustomization_from_git_multiple_args.golden
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
► suspending kustomization tkfg in {{ .ns }} namespace
|
||||
✔ kustomization suspended
|
||||
✗ Kustomization foo not found in {{ .ns }} namespace
|
||||
✗ Kustomization bar not found in {{ .ns }} namespace
|
||||
2
cmd/flux/testdata/oci/resume_oci.golden
vendored
2
cmd/flux/testdata/oci/resume_oci.golden
vendored
@@ -1,5 +1,5 @@
|
||||
► resuming source oci thrfg in {{ .ns }} namespace
|
||||
✔ source oci resumed
|
||||
◎ waiting for OCIRepository reconciliation
|
||||
✔ OCIRepository reconciliation completed
|
||||
✔ OCIRepository thrfg reconciliation completed
|
||||
✔ fetched revision 6.3.5@sha256:6c959c51ccbb952e5fe4737563338a0aaf975675dcf812912cf09e5463181871
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/spf13/cobra"
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -119,12 +120,19 @@ func versionCmdRun(cmd *cobra.Command, args []string) error {
|
||||
}
|
||||
|
||||
func splitImageStr(image string) (string, string, error) {
|
||||
imageArr := strings.Split(image, ":")
|
||||
if len(imageArr) < 2 {
|
||||
ref, err := name.ParseReference(image)
|
||||
if err != nil {
|
||||
return "", "", fmt.Errorf("parsing image '%s' failed: %w", image, err)
|
||||
}
|
||||
|
||||
reg := ref.Context().RegistryStr()
|
||||
repo := strings.TrimPrefix(image, reg)
|
||||
parts := strings.Split(repo, ":")
|
||||
if len(parts) < 2 {
|
||||
return "", "", fmt.Errorf("missing image tag in image %s", image)
|
||||
}
|
||||
|
||||
name, tag := imageArr[0], imageArr[1]
|
||||
nameArr := strings.Split(name, "/")
|
||||
return nameArr[len(nameArr)-1], tag, nil
|
||||
n, t := parts[0], strings.TrimPrefix(repo, parts[0]+":")
|
||||
nameArr := strings.Split(n, "/")
|
||||
return nameArr[len(nameArr)-1], t, nil
|
||||
}
|
||||
|
||||
60
cmd/flux/version_test.go
Normal file
60
cmd/flux/version_test.go
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2021 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"
|
||||
|
||||
. "github.com/onsi/gomega"
|
||||
)
|
||||
|
||||
func TestSplitImageStr(t *testing.T) {
|
||||
tests := []struct {
|
||||
url string
|
||||
expectedName string
|
||||
expectedTag string
|
||||
}{
|
||||
{
|
||||
url: "fluxcd/notification-controller:v1.0.0",
|
||||
expectedName: "notification-controller",
|
||||
expectedTag: "v1.0.0",
|
||||
},
|
||||
{
|
||||
url: "ghcr.io/fluxcd/kustomize-controller:v1.0.0",
|
||||
expectedName: "kustomize-controller",
|
||||
expectedTag: "v1.0.0",
|
||||
},
|
||||
{
|
||||
url: "reg.internal:8080/fluxcd/source-controller:v1.0.0",
|
||||
expectedName: "source-controller",
|
||||
expectedTag: "v1.0.0",
|
||||
},
|
||||
{
|
||||
url: "fluxcd/source-controller:v1.0.1@sha256:49921d1c7b100650dd654a32df1f6e626b54dfe9707d7bb7bdf43fb7c81f1baf",
|
||||
expectedName: "source-controller",
|
||||
expectedTag: "v1.0.1@sha256:49921d1c7b100650dd654a32df1f6e626b54dfe9707d7bb7bdf43fb7c81f1baf",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
g := NewWithT(t)
|
||||
n, t, err := splitImageStr(tt.url)
|
||||
g.Expect(err).To(Not(HaveOccurred()))
|
||||
g.Expect(n).To(BeEquivalentTo(tt.expectedName))
|
||||
g.Expect(t).To(BeEquivalentTo(tt.expectedTag))
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
# Flux v2 Documentation
|
||||
|
||||
The documentation for `flux2` has moved to this repository: <https://github.com/fluxcd/website>.
|
||||
|
||||
[The Website's README](https://github.com/fluxcd/website/#readme) has information on how to
|
||||
|
||||
- modify and extend documentation
|
||||
- run the site <https://fluxcd.io> locally
|
||||
- publish changes
|
||||
|
||||
and where all the individual pieces of content come from.
|
||||
|
||||
It will be easier for us to maintain a coherent web presences (and merge all of Flux documentation) in one central repository. This was partly discussed in <https://github.com/fluxcd/flux2/discussions/367>.
|
||||
|
||||
## toolkit.fluxcd.io
|
||||
|
||||
For historical reasons we are keeping a `_redirects` file in this directory. It defines how redirects from the old site `toolkit.fluxcd.io` to our new website <https://fluxcd.io> work. Changes to this file need to be merged and a manual build triggered in the Netlify App.
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 61 KiB |
@@ -1,18 +0,0 @@
|
||||
# individual rules
|
||||
/core-concepts https://fluxcd.io/flux/concepts 301!
|
||||
/contributing https://fluxcd.io/contributing 301!
|
||||
/install.sh https://fluxcd.io/install.sh 301!
|
||||
|
||||
# refer to https://github.com/fluxcd/flux2/discussions/367
|
||||
/dev-guides/* https://fluxcd.io/flux/gitops-toolkit/:splat 301!
|
||||
|
||||
|
||||
# this is how things looked in the navbar anyway..?
|
||||
/guides/faq-migration https://fluxcd.io/flux/migration/faq-migration 301!
|
||||
/guides/flux-v1-automation-migration https://fluxcd.io/flux/migration/flux-v1-automation-migration 301!
|
||||
/guides/flux-v1-migration https://fluxcd.io/flux/migration/flux-v1-migration 301!
|
||||
/guides/helm-operator-migration https://fluxcd.io/flux/migration/helm-operator-migration 301!
|
||||
|
||||
|
||||
# catch all
|
||||
/* https://fluxcd.io/flux/:splat 301!
|
||||
@@ -1,83 +0,0 @@
|
||||
# Flux Diagrams
|
||||
|
||||
## Cluster sync from Git
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor me
|
||||
participant git as Git<br><br>repository
|
||||
participant sc as Flux<br><br>source-controller
|
||||
participant kc as Flux<br><br>kustomize-controller
|
||||
participant kube as Kubernetes<br><br>api-server
|
||||
participant nc as Flux<br><br>notification-controller
|
||||
me->>git: 1. git push
|
||||
sc->>git: 2. git pull
|
||||
sc->>sc: 3. build artifact for revision
|
||||
sc->>kube: 4. update status for revision
|
||||
sc-->>nc: 5. emit events
|
||||
kube->>kc: 6. notify about new revision
|
||||
kc->>sc: 7. fetch artifact for revision
|
||||
kc->>kc: 8. build manifests to objects
|
||||
kc-->>kc: 9. decrypt secrets
|
||||
kc->>kube: 10. validate objects
|
||||
kc->>kube: 11. apply objects
|
||||
kc-->>kube: 12. delete objects
|
||||
kc-->>kube: 13. wait for readiness
|
||||
kc->>kube: 14. update status for revision
|
||||
kc-->>nc: 15. emit events
|
||||
nc-->>me: 16. send alerts for revision
|
||||
```
|
||||
|
||||
## Helm release upgrade from Git
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor me
|
||||
participant git as Git<br><br>repository
|
||||
participant sc as Flux<br><br>source-controller
|
||||
participant hc as Flux<br><br>helm-controller
|
||||
participant kube as Kubernetes<br><br>api-server
|
||||
participant nc as Flux<br><br>notification-controller
|
||||
me->>git: 1. git push
|
||||
sc->>git: 2. git pull
|
||||
sc->>sc: 3. build chart for revision
|
||||
sc->>kube: 4. update chart status
|
||||
sc-->>nc: 5. emit events
|
||||
kube->>hc: 6. notify about new revision
|
||||
hc->>sc: 7. fetch chart
|
||||
hc->>kube: 8. get values
|
||||
hc->>hc: 9. render and customize manifests
|
||||
hc-->>kube: 10. apply CRDs
|
||||
hc->>kube: 11. upgrade release
|
||||
hc-->>kube: 12. run tests
|
||||
hc-->>kube: 13. wait for readiness
|
||||
hc->>kube: 14. update status
|
||||
hc-->>nc: 15. emit events
|
||||
nc-->>me: 16. send alerts
|
||||
```
|
||||
|
||||
## Image update to Git
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
actor me
|
||||
participant oci as Image<br><br>repository
|
||||
participant irc as Flux<br><br>image-reflector-controller
|
||||
participant iac as Flux<br><br>image-automation-controller
|
||||
participant kube as Kubernetes<br><br>api-server
|
||||
participant nc as Flux<br><br>notification-controller
|
||||
participant git as Git<br><br>repository
|
||||
me->>oci: 1. docker push
|
||||
irc->>oci: 2. list tags
|
||||
irc->>irc: 3. match tags to policies
|
||||
irc->>kube: 4. update status
|
||||
irc-->>nc: 5. emit events
|
||||
kube->>iac: 6. notify about new tags
|
||||
iac->>git: 7. git clone
|
||||
iac->>iac: 8. patch manifests with new tags
|
||||
iac->>git: 9. git push
|
||||
iac->>kube: 10. update status
|
||||
iac-->>nc: 11. emit events
|
||||
nc-->>me: 12. send alerts
|
||||
```
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
# Flux release procedure
|
||||
|
||||
The Flux Go modules and the GitOps Toolkit controllers are released by following the [semver](https://semver.org) conventions.
|
||||
|
||||
Repositories subject to semver releases:
|
||||
|
||||
1. [fluxcd/pkg](https://github.com/fluxcd/pkg)
|
||||
- modules: `apis/meta`, `runtime`, various utilities
|
||||
- dependencies: `k8s.io/*`, `sigs.k8s.io/controller-runtime`
|
||||
1. [fluxcd/source-controller](https://github.com/fluxcd/source-controller)
|
||||
- modules: `api`
|
||||
- dependencies: `github.com/fluxcd/pkg/*`
|
||||
1. [fluxcd/kustomize-controller](https://github.com/fluxcd/kustomize-controller)
|
||||
- modules: `api`
|
||||
- dependencies: `github.com/fluxcd/source-controller/api`, `github.com/fluxcd/pkg/*`
|
||||
1. [fluxcd/helm-controller](https://github.com/fluxcd/helm-controller)
|
||||
- modules: `api`
|
||||
- dependencies: `github.com/fluxcd/source-controller/api`, `github.com/fluxcd/pkg/*`
|
||||
1. [fluxcd/image-reflector-controller](https://github.com/fluxcd/image-reflector-controller)
|
||||
- modules: `api`
|
||||
- dependencies: `github.com/fluxcd/pkg/*`
|
||||
1. [fluxcd/image-automation-controller](https://github.com/fluxcd/image-automation-controller)
|
||||
- modules: `api`
|
||||
- dependencies: `github.com/fluxcd/source-controller/api`, `github.com/fluxcd/image-reflector-controller/api`, `github.com/fluxcd/pkg/*`
|
||||
1. [fluxcd/notification-controller](https://github.com/fluxcd/notification-controller)
|
||||
- modules: `api`
|
||||
- dependencies: `github.com/fluxcd/pkg/*`
|
||||
1. [fluxcd/flux2](https://github.com/fluxcd/flux2)
|
||||
- modules: `manifestgen`
|
||||
- dependencies: `github.com/fluxcd/source-controller/api`, `github.com/fluxcd/kustomize-controller/api`, `github.com/fluxcd/helm-controller/api`, `github.com/fluxcd/image-reflector-controller/api`, `github.com/fluxcd/image-automation-controller/api`, `github.com/fluxcd/notification-controller/api`, `github.com/fluxcd/pkg/*`
|
||||
1. [fluxcd/terraform-provider-flux](https://github.com/fluxcd/terraform-provider-flux)
|
||||
- dependencies: `github.com/fluxcd/flux2/pkg/manifestgen`
|
||||
|
||||
## Release procedure
|
||||
|
||||
### Go packages
|
||||
|
||||
The Go packages in [fluxcd/pkg](https://github.com/fluxcd/pkg) are dedicated modules,
|
||||
each module has its own set of dependencies and release cycle.
|
||||
|
||||
Release procedure for a package:
|
||||
|
||||
1. Checkout the `main` branch and pull changes from remote.
|
||||
1. Run `make release-<package name> VER=<next semver>`.
|
||||
|
||||
### Controllers
|
||||
|
||||
A toolkit controller has a dedicated module for its API, the API module
|
||||
has its own set of dependencies.
|
||||
|
||||
Release procedure for a controller and its API:
|
||||
|
||||
1. Checkout the `main` branch and pull changes from remote.
|
||||
1. Create a `api/<next semver>` tag and push it to remote.
|
||||
1. Create a new branch from `main` i.e. `release-<next semver>`. This
|
||||
will function as your release preparation branch.
|
||||
1. Update the `github.com/fluxcd/<NAME>-controller/api` version in `go.mod`
|
||||
1. Add an entry to the `CHANGELOG.md` for the new release and change the
|
||||
`newTag` value in ` config/manager/kustomization.yaml` to that of the
|
||||
semver release you are going to make. Commit and push your changes.
|
||||
1. Create a PR for your release branch and get it merged into `main`.
|
||||
1. Create a `<next semver>` tag for the merge commit in `main` and
|
||||
push it to remote.
|
||||
1. Confirm CI builds and releases the newly tagged version.
|
||||
|
||||
### Flux
|
||||
|
||||
Release procedure for Flux:
|
||||
|
||||
1. Checkout the `main` branch and pull changes from remote.
|
||||
1. Create a `<next semver>` tag form `main` and push it to remote.
|
||||
1. Confirm CI builds and releases the newly tagged version.
|
||||
|
||||
## Upgrade Kubernetes modules
|
||||
|
||||
Flux has the following Kubernetes dependencies:
|
||||
|
||||
- `k8s.io/api`
|
||||
- `k8s.io/apiextensions-apiserver`
|
||||
- `k8s.io/apimachinery`
|
||||
- `k8s.io/cli-runtime`
|
||||
- `k8s.io/client-go`
|
||||
- `sigs.k8s.io/controller-runtime`
|
||||
|
||||
**Note** that all `k8s.io/*` packages must have the same version in `go.mod` e.g.:
|
||||
|
||||
```
|
||||
k8s.io/api v0.20.2
|
||||
k8s.io/apiextensions-apiserver v0.20.2
|
||||
k8s.io/apimachinery v0.20.2
|
||||
k8s.io/cli-runtime v0.20.2
|
||||
k8s.io/client-go v0.20.2
|
||||
```
|
||||
|
||||
The specialised reconcilers depend on:
|
||||
|
||||
- kustomize-controller: `sigs.k8s.io/kustomize/api`
|
||||
- image-automation-controller: `sigs.k8s.io/kustomize/kyaml`
|
||||
- helm-controller: `helm.sh/helm/v3`
|
||||
|
||||
**Note** that the `k8s.io/*` version must be compatible with both `kustomize/api` and `helm/v3`.
|
||||
If there is a breaking change in `client-go` we have to wait for Kustomize and Helm to upgrade first.
|
||||
|
||||
### Upgrade procedure:
|
||||
|
||||
`fluxcd/pkg`:
|
||||
|
||||
1. Update the `k8s.io/*` version in `pkg/apis/meta/go.mod`
|
||||
1. Release the `apis/meta` package
|
||||
1. Update `apis/meta` version in `pkg/runtime/go.mod`
|
||||
1. Update the `k8s.io/*` version in `pkg/runtime/go.mod`
|
||||
1. Update `sigs.k8s.io/controller-runtime` version in `pkg/runtime/go.mod`
|
||||
1. Release the `runtime` package
|
||||
|
||||
`fluxcd/source-controller`:
|
||||
|
||||
1. Update the `github.com/fluxcd/pkg/apis/meta` version in `source-controller/api/go.mod` and `source-controller/go.mod`
|
||||
1. Update the `k8s.io/*` version in `source-controller/api/go.mod` and `source-controller/go.mod`
|
||||
1. Update the `sigs.k8s.io/controller-runtime` version in `source-controller/api/go.mod` and `source-controller/go.mod`
|
||||
1. Update the `github.com/fluxcd/pkg/runtime` version in `source-controller/go.mod`
|
||||
1. Release the `api` package
|
||||
|
||||
`fluxcd/<kustomize|helm|notification|image-automation>-controller`:
|
||||
|
||||
1. Update the `github.com/fluxcd/source-controller/api` version in `<NAME>-controller/api/go.mod` and `<NAME>-controller/go.mod`
|
||||
1. Update the `github.com/fluxcd/pkg/apis/meta` version in `<NAME>-controller/api/go.mod` and `<NAME>-controller/go.mod`
|
||||
1. Update the `k8s.io/*` version in `<NAME>-controller/api/go.mod` and `<NAME>-controller/go.mod`
|
||||
1. Update the `github.com/fluxcd/pkg/runtime` version in `<NAME>-controller/go.mod`
|
||||
1. Release the `api` package
|
||||
|
||||
`fluxcd/flux2`:
|
||||
|
||||
1. Update the `github.com/fluxcd/*-controller/api` version in `flux2/go.mod` (automated with [GitHub Actions](../../.github/workflows/update.yaml))
|
||||
1. Update the `github.com/fluxcd/pkg/*` version in `flux2/go.mod`
|
||||
1. Update the `k8s.io/*` and `github.com/fluxcd/pkg/runtime` version in `flux2/go.mod`
|
||||
|
||||
`fluxcd/terraform-provider-flux`:
|
||||
|
||||
1. Update the `github.com/fluxcd/flux2` version in `terraform-provider-flux/go.mod` (automated with [GitHub Actions](https://github.com/fluxcd/terraform-provider-flux/blob/main/.github/workflows/update.yaml))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user