1
0
mirror of synced 2026-03-01 11:16:56 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
Hidde Beydals
4c0987a9a6 Concept: encrypt init command for SOPS bootstrap
Signed-off-by: Hidde Beydals <hello@hidde.co>
2021-07-13 00:38:46 +02:00
141 changed files with 557 additions and 3031 deletions

46
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,46 @@
---
name: Bug report
about: Create a report to help us improve Flux v2
title: ''
assignees: ''
---
<!--
Find out more about your support options and getting help at
https://fluxcd.io/support/
-->
### Describe the bug
A clear and concise description of what the bug is.
### To Reproduce
Steps to reproduce the behaviour:
1. Provide Flux install instructions
2. Provide a GitHub repository with Kubernetes manifests
### Expected behavior
A clear and concise description of what you expected to happen.
### Additional context
- Kubernetes version:
- Git provider:
- Container registry provider:
Below please provide the output of the following commands:
```cli
flux --version
flux check
kubectl -n <namespace> get all
kubectl -n <namespace> logs deploy/source-controller
kubectl -n <namespace> logs deploy/kustomize-controller
```

View File

@@ -1,85 +0,0 @@
---
name: Bug report
description: Create a report to help us improve Flux
body:
- type: markdown
attributes:
value: |
## Support
Find out more about your support options and getting help at: https://fluxcd.io/support/
- type: textarea
validations:
required: true
attributes:
label: Describe the bug
description: A clear description of what the bug is.
- type: textarea
validations:
required: true
attributes:
label: Steps to reproduce
description: |
Steps to reproduce the problem.
placeholder: |
For example:
1. Install Flux with the additional image automation controllers
2. Run command '...'
3. See error
- type: textarea
validations:
required: true
attributes:
label: Expected behavior
description: A brief description of what you expected to happen.
- type: textarea
attributes:
label: Screenshots and recordings
description: |
If applicable, add screenshots to help explain your problem. You can also record an asciinema session: https://asciinema.org/
- type: input
validations:
required: true
attributes:
label: OS / Distro
description: The OS / distro you are executing `flux` on. If not applicable, write `N/A`.
placeholder: e.g. Windows 10, Ubuntu 20.04, Arch Linux, macOS 10.15...
- type: input
validations:
required: true
attributes:
label: Flux version
description: Run `flux --version` to check. If not applicable, write `N/A`.
placeholder: e.g. 0.16.1
- type: textarea
validations:
required: true
attributes:
label: Flux check
description: Run `flux check` to check. If not applicable, write `N/A`.
placeholder: |
For example:
► checking prerequisites
✔ kubectl 1.21.0 >=1.18.0-0
✔ Kubernetes 1.21.1 >=1.16.0-0
► checking controllers
✔ all checks passed
- type: input
attributes:
label: Git provider
description: If applicable, add the Git provider you are having problems with, e.g. GitHub (Enterprise), GitLab, etc.
- type: input
attributes:
label: Container Registry provider
description: If applicable, add the Container Registry provider you are having problems with, e.g. DockerHub, GitHub Packages, Quay.io, etc.
- type: textarea
attributes:
label: Additional context
description: Add any other context about the problem here. This can be logs (e.g. output from `flux logs`), environment specific caveats, etc.
- type: checkboxes
id: terms
attributes:
label: Code of Conduct
description: By submitting this issue, you agree to follow our [Code of Conduct](https://github.com/fluxcd/.github/blob/main/CODE_OF_CONDUCT.md)
options:
- label: I agree to follow this project's Code of Conduct
required: true

View File

@@ -1,42 +0,0 @@
# Flux GitHub runners
How to provision GitHub Actions self-hosted runners for Flux conformance testing.
## ARM64 Instance specs
In order to add a new runner to the GitHub Actions pool,
first create an instance on Oracle Cloud with the following configuration:
- OS: Canonical Ubuntu 20.04
- Shape: VM.Standard.A1.Flex
- OCPU Count: 2
- Memory (GB): 12
- Network Bandwidth (Gbps): 2
- Local Disk: Block Storage Only
Note that the instance image source must be **Canonical Ubuntu** instead of the default Oracle Linux.
## ARM64 Instance setup
- SSH into a newly created instance
```shell
ssh ubuntu@<instance-public-IP>
```
- Create the action runner dir
```shell
mkdir -p actions-runner && cd actions-runner
```
- Download the provisioning script
```shell
curl -sL https://raw.githubusercontent.com/fluxcd/flux2/main/.github/runners/arm64.sh > arm64.sh \
&& chmod +x ./arm64.sh
```
- Retrieve the GitHub runner token from the repository [settings page](https://github.com/fluxcd/flux2/settings/actions/runners/new?arch=arm64&os=linux)
- Run the provisioning script passing the token as the first argument
```shell
sudo ./arm64.sh <TOKEN>
```
- Reboot the instance
```shell
sudo reboot
```
- Navigate to the GitHub repository [runners page](https://github.com/fluxcd/flux2/settings/actions/runners) and check the runner status

View File

@@ -1,73 +0,0 @@
#!/usr/bin/env bash
# Copyright 2021 The Flux authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This script is meant to be run locally and in CI to validate the Kubernetes
# manifests (including Flux custom resources) before changes are merged into
# the branch synced by Flux in-cluster.
set -eu
REPOSITORY_TOKEN=$1
REPOSITORY_URL=${2:-https://github.com/fluxcd/flux2}
KIND_VERSION=0.11.1
KUBECTL_VERSION=1.21.2
KUSTOMIZE_VERSION=4.1.3
GITHUB_RUNNER_VERSION=2.278.0
PACKAGES="apt-transport-https ca-certificates software-properties-common build-essential libssl-dev gnupg lsb-release jq"
# install prerequisites
apt-get update \
&& apt-get install -y -q ${PACKAGES} \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
# install docker
curl -fsSL https://get.docker.com -o get-docker.sh \
&& chmod +x get-docker.sh
./get-docker.sh
systemctl enable docker.service
systemctl enable containerd.service
usermod -aG docker ubuntu
# install kind
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v${KIND_VERSION}/kind-linux-arm64
install -o root -g root -m 0755 kind /usr/local/bin/kind
# install kubectl
curl -LO "https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/linux/arm64/kubectl"
install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
# install kustomize
curl -Lo ./kustomize.tar.gz https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize%2Fv${KUSTOMIZE_VERSION}/kustomize_v${KUSTOMIZE_VERSION}_linux_arm64.tar.gz \
&& tar -zxvf kustomize.tar.gz \
&& rm kustomize.tar.gz
install -o root -g root -m 0755 kustomize /usr/local/bin/kustomize
# download runner
curl -o actions-runner-linux-arm64.tar.gz -L https://github.com/actions/runner/releases/download/v${GITHUB_RUNNER_VERSION}/actions-runner-linux-arm64-${GITHUB_RUNNER_VERSION}.tar.gz \
&& tar xzf actions-runner-linux-arm64.tar.gz \
&& rm actions-runner-linux-arm64.tar.gz
# install runner dependencies
./bin/installdependencies.sh
# register runner with GitHub
sudo -u ubuntu ./config.sh --unattended --url ${REPOSITORY_URL} --token ${REPOSITORY_TOKEN}
# start runner
./svc.sh install
./svc.sh start

View File

@@ -26,9 +26,6 @@ jobs:
go-version: 1.16.x
- name: Setup Kubernetes
uses: engineerd/setup-kind@v0.5.0
with:
version: v0.11.1
image: kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Build
@@ -64,13 +61,6 @@ jobs:
--team=team-z
env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: libgit2
run: |
/tmp/flux create source git test-libgit2 \
--url=ssh://git@github.com/fluxcd-testing/${{ steps.vars.outputs.test_repo_name }} \
--git-implementation=libgit2 \
--secret-ref=flux-system \
--branch=main
- name: uninstall
run: |
/tmp/flux uninstall -s --keep-namespace

View File

@@ -3,13 +3,15 @@ name: e2e-arm64
on:
workflow_dispatch:
push:
branches: [ main, update-components, arm64-e2e ]
branches: [ main, update-components ]
jobs:
ampere:
# Runner info
# Owner: Stefan Prodan
# Docs: https://github.com/fluxcd/flux2/tree/main/.github/runners
# VM: Oracle Cloud VM.Standard.A1.Flex 4CPU 24GB RAM
# OS: Linux 5.4.0-1045-oracle #49-Ubuntu SMP aarch64
# Packages: docker, kind, kubectl, kustomize
runs-on: [self-hosted, Linux, ARM64]
steps:
- name: Checkout
@@ -23,16 +25,85 @@ jobs:
run: |
echo ::set-output name=CLUSTER::arm64-${GITHUB_SHA:0:7}-$(date +%s)
echo ::set-output name=CONTEXT::kind-arm64-${GITHUB_SHA:0:7}-$(date +%s)
- name: Run unit tests
run: make test
- name: Check if working tree is dirty
run: |
if [[ $(git diff --stat) != '' ]]; then
git diff
echo 'run make test and commit changes'
exit 1
fi
- name: Build
run: |
make build
go build -o /tmp/flux ./cmd/flux
- name: Setup Kubernetes Kind
run: |
kind create cluster --name ${{ steps.prep.outputs.CLUSTER }} --kubeconfig=/tmp/${{ steps.prep.outputs.CLUSTER }}
- name: Run e2e tests
run: TEST_KUBECONFIG=/tmp/${{ steps.prep.outputs.CLUSTER }} make e2e
kind create cluster --name ${{ steps.prep.outputs.CLUSTER }}
- name: flux check --pre
run: |
/tmp/flux check --pre \
--context ${{ steps.prep.outputs.CONTEXT }}
- name: flux install
run: |
/tmp/flux install \
--components-extra=image-reflector-controller,image-automation-controller \
--context ${{ steps.prep.outputs.CONTEXT }}
- name: flux create source git
run: |
/tmp/flux create source git podinfo-gogit \
--git-implementation=go-git \
--url https://github.com/stefanprodan/podinfo \
--tag-semver=">1.0.0" \
--context ${{ steps.prep.outputs.CONTEXT }}
/tmp/flux create source git podinfo-libgit2 \
--git-implementation=libgit2 \
--url https://github.com/stefanprodan/podinfo \
--branch="master" \
--context ${{ steps.prep.outputs.CONTEXT }}
- name: flux create kustomization
run: |
/tmp/flux create kustomization podinfo \
--source=podinfo-gogit \
--path="./deploy/overlays/dev" \
--prune=true \
--interval=5m \
--validation=client \
--health-check="Deployment/frontend.dev" \
--health-check="Deployment/backend.dev" \
--health-check-timeout=3m \
--context ${{ steps.prep.outputs.CONTEXT }}
- name: flux create tenant
run: |
/tmp/flux create tenant dev-team \
--with-namespace=apps \
--context ${{ steps.prep.outputs.CONTEXT }}
- name: flux create helmrelease
run: |
/tmp/flux -n apps create source helm podinfo \
--url https://stefanprodan.github.io/podinfo \
--context ${{ steps.prep.outputs.CONTEXT }}
/tmp/flux -n apps create hr podinfo-helm \
--source=HelmRepository/podinfo \
--chart=podinfo \
--chart-version="6.0.x" \
--service-account=dev-team \
--context ${{ steps.prep.outputs.CONTEXT }}
- name: flux get all
run: |
/tmp/flux get all --all-namespaces \
--context ${{ steps.prep.outputs.CONTEXT }}
- name: flux uninstall
run: |
/tmp/flux uninstall -s \
--context ${{ steps.prep.outputs.CONTEXT }}
- name: Debug failure
if: failure()
run: |
kubectl --context ${{ steps.prep.outputs.CONTEXT }} -n flux-system get all
/tmp/flux logs --all-namespaces
- name: Cleanup
if: always()
run: |
kind delete cluster --name ${{ steps.prep.outputs.CLUSTER }}
rm /tmp/${{ steps.prep.outputs.CLUSTER }}

View File

@@ -26,23 +26,17 @@ jobs:
- name: Setup Kubernetes
uses: engineerd/setup-kind@v0.5.0
with:
version: v0.11.1
image: kindest/node:v1.21.1@sha256:69860bda5563ac81e3c0057d654b5253219618a22ec3a346306239bba8cfa1a6
version: "v0.10.0"
image: kindest/node:v1.20.2@sha256:8f7ea6e7642c0da54f04a7ee10431549c0257315b3a634f6ef2fecaaedb19bab
config: .github/kind/config.yaml # disable KIND-net
- name: Setup envtest
uses: fluxcd/pkg/actions/envtest@main
with:
version: "1.21.x"
- name: Setup Calico for network policy
run: |
kubectl apply -f https://docs.projectcalico.org/v3.16/manifests/calico.yaml
kubectl -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true
- name: Setup Kustomize
uses: fluxcd/pkg//actions/kustomize@main
- name: Run tests
- name: Run test
run: make test
- name: Run e2e tests
run: TEST_KUBECONFIG=$HOME/.kube/config make e2e
- name: Check if working tree is dirty
run: |
if [[ $(git diff --stat) != '' ]]; then
@@ -97,12 +91,6 @@ jobs:
--health-check="Deployment/frontend.dev" \
--health-check="Deployment/backend.dev" \
--health-check-timeout=3m
- name: flux trace
run: |
/tmp/flux trace frontend \
--kind=deployment \
--api-version=apps/v1 \
--namespace=dev
- name: flux reconcile kustomization --with-source
run: |
/tmp/flux reconcile kustomization podinfo --with-source
@@ -176,6 +164,26 @@ jobs:
--chart=podinfo \
--chart-version="5.0.x" \
--service-account=dev-team
- name: flux create image repository
run: |
/tmp/flux create image repository podinfo \
--image=ghcr.io/stefanprodan/podinfo \
--interval=1m
- name: flux create image policy
run: |
/tmp/flux create image policy podinfo \
--image-ref=podinfo \
--interval=1m \
--select-semver=5.0.x
- name: flux create image policy podinfo-select-alpha
run: |
/tmp/flux create image policy podinfo-alpha \
--image-ref=podinfo \
--interval=1m \
--select-alpha=desc
- name: flux get image policy
run: |
/tmp/flux get image policy podinfo | grep '5.0.3'
- name: flux2-kustomize-helm-example
run: |
/tmp/flux create source git flux-system \
@@ -185,7 +193,7 @@ jobs:
/tmp/flux create kustomization flux-system \
--source=flux-system \
--path=./clusters/staging
kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=5m
kubectl -n flux-system wait kustomization/apps --for=condition=ready --timeout=2m
- name: flux check
run: |
/tmp/flux check
@@ -197,7 +205,6 @@ jobs:
run: |
kubectl version --client --short
kubectl -n flux-system get all
kubectl -n flux-system describe pods
kubectl -n flux-system get kustomizations -oyaml
kubectl -n flux-system logs deploy/source-controller
kubectl -n flux-system logs deploy/kustomize-controller

View File

@@ -77,16 +77,6 @@ You can run the unit tests by simply doing
make test
```
The e2e test suite uses [kind](https://kind.sigs.k8s.io/) for running kubernetes cluster inside docker containers. You can run the e2e tests by simply doing
```bash
make setup-kind
make e2e
# When done
make cleanup-kind
```
## Acceptance policy
These things will make a PR more likely to be accepted:

View File

@@ -1,15 +1,5 @@
VERSION?=$(shell grep 'VERSION' cmd/flux/main.go | awk '{ print $$4 }' | tr -d '"')
EMBEDDED_MANIFESTS_TARGET=cmd/flux/manifests
TEST_KUBECONFIG?=/tmp/flux-e2e-test-kubeconfig
ENVTEST_BIN_VERSION?=latest
KUBEBUILDER_ASSETS?="$(shell $(SETUP_ENVTEST) use -i $(ENVTEST_BIN_VERSION) -p path)"
# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (,$(shell go env GOBIN))
GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif
rwildcard=$(foreach d,$(wildcard $(addsuffix *,$(1))),$(call rwildcard,$(d)/,$(2)) $(filter $(subst *,%,$(2)),$(d)))
@@ -24,25 +14,8 @@ fmt:
vet:
go vet ./...
setup-kind:
kind create cluster --name=flux-e2e-test --kubeconfig=$(TEST_KUBECONFIG) --config=.github/kind/config.yaml
kubectl --kubeconfig=$(TEST_KUBECONFIG) apply -f https://docs.projectcalico.org/v3.16/manifests/calico.yaml
kubectl --kubeconfig=$(TEST_KUBECONFIG) -n kube-system set env daemonset/calico-node FELIX_IGNORELOOSERPF=true
cleanup-kind:
kind delete cluster --name=flux-e2e-test
rm $(TEST_KUBECONFIG)
test: $(EMBEDDED_MANIFESTS_TARGET) tidy fmt vet setup-envtest
KUBEBUILDER_ASSETS=$(KUBEBUILDER_ASSETS) go test ./... -coverprofile cover.out --tags=unit
e2e: $(EMBEDDED_MANIFESTS_TARGET) tidy fmt vet
TEST_KUBECONFIG=$(TEST_KUBECONFIG) go test ./cmd/flux/... -coverprofile e2e.cover.out --tags=e2e -v -failfast
test-with-kind: setup-envtest
make setup-kind
make e2e
make cleanup-kind
test: $(EMBEDDED_MANIFESTS_TARGET) tidy fmt vet
go test ./... -coverprofile cover.out
$(EMBEDDED_MANIFESTS_TARGET): $(call rwildcard,manifests/,*.yaml *.json)
./manifests/scripts/bundle.sh
@@ -55,19 +28,3 @@ install:
install-dev:
CGO_ENABLED=0 go build -o /usr/local/bin ./cmd/flux
# Find or download setup-envtest
setup-envtest:
ifeq (, $(shell which setup-envtest))
@{ \
set -e ;\
SETUP_ENVTEST_TMP_DIR=$$(mktemp -d) ;\
cd $$SETUP_ENVTEST_TMP_DIR ;\
go mod init tmp ;\
go get sigs.k8s.io/controller-runtime/tools/setup-envtest@latest ;\
rm -rf $$SETUP_ENVTEST_TMP_DIR ;\
}
SETUP_ENVTEST=$(GOBIN)/setup-envtest
else
SETUP_ENVTEST=$(shell which setup-envtest)
endif

View File

@@ -133,9 +133,7 @@ new contributors and there are a multitude of ways to get involved.
### Events
Check out our **[events calendar](https://fluxcd.io/#calendar)**,
both with upcoming talks, events and meetings you can attend.
Or view the **[resources section](https://fluxcd.io/resources)**
with past events videos you can watch.
Check out our **[events calendar](https://fluxcd.io/community/#talks)**,
both with upcoming talks you can attend or past events videos you can watch.
We look forward to seeing you with us!

View File

@@ -10,21 +10,11 @@ Usage:
run: flux -v
```
Note that this action can only be used on GitHub **Linux AMD64** runners.
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`.
Note that this action can only be used on GitHub **Linux** runners.
You can change the arch (defaults to `amd64`) with:
```yaml
steps:
- name: Setup Flux CLI
uses: fluxcd/flux2/action@main
with:
arch: arm64 # can be amd64, arm64 or arm
```
You can download a specific version with:
```yaml

View File

@@ -8,24 +8,19 @@ inputs:
version:
description: "Flux version e.g. 0.8.0 (defaults to latest stable release)"
required: false
arch:
description: "arch can be amd64, arm64 or arm"
required: true
default: "amd64"
runs:
using: composite
steps:
- name: "Download flux binary to tmp"
shell: bash
run: |
ARCH=${{ inputs.arch }}
VERSION=${{ inputs.version }}
if [ -z $VERSION ]; then
VERSION=$(curl https://api.github.com/repos/fluxcd/flux2/releases/latest -sL | grep tag_name | sed -E 's/.*"([^"]+)".*/\1/' | cut -c 2-)
fi
BIN_URL="https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_${ARCH}.tar.gz"
BIN_URL="https://github.com/fluxcd/flux2/releases/download/v${VERSION}/flux_${VERSION}_linux_amd64.tar.gz"
curl -sL ${BIN_URL} -o /tmp/flux.tar.gz
mkdir -p /tmp/flux
tar -C /tmp/flux/ -zxvf /tmp/flux.tar.gz

View File

@@ -37,10 +37,6 @@ func (a alertAdapter) asClientObject() client.Object {
return a.Alert
}
func (a alertAdapter) deepCopyClientObject() client.Object {
return a.Alert.DeepCopy()
}
// notificationv1.Alert
type alertListAdapter struct {

View File

@@ -37,10 +37,6 @@ func (a alertProviderAdapter) asClientObject() client.Object {
return a.Provider
}
func (a alertProviderAdapter) deepCopyClientObject() client.Object {
return a.Provider.DeepCopy()
}
// notificationv1.Provider
type alertProviderListAdapter struct {

View File

@@ -19,7 +19,7 @@ package main
import (
"crypto/elliptic"
"fmt"
"os"
"io/ioutil"
"github.com/spf13/cobra"
@@ -145,7 +145,7 @@ func buildEmbeddedManifestBase() (string, error) {
if !isEmbeddedVersion(bootstrapArgs.version) {
return "", nil
}
tmpBaseDir, err := os.MkdirTemp("", "flux-manifests-")
tmpBaseDir, err := ioutil.TempDir("", "flux-manifests-")
if err != nil {
return "", err
}

View File

@@ -19,6 +19,7 @@ package main
import (
"context"
"fmt"
"io/ioutil"
"net/url"
"os"
"strings"
@@ -117,7 +118,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
defer os.RemoveAll(manifestsBase)
// Lazy go-git repository
tmpDir, err := os.MkdirTemp("", "flux-bootstrap-")
tmpDir, err := ioutil.TempDir("", "flux-bootstrap-")
if err != nil {
return fmt.Errorf("failed to create temporary working dir: %w", err)
}

View File

@@ -19,6 +19,7 @@ package main
import (
"context"
"fmt"
"io/ioutil"
"os"
"time"
@@ -145,7 +146,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
}
// Lazy go-git repository
tmpDir, err := os.MkdirTemp("", "flux-bootstrap-")
tmpDir, err := ioutil.TempDir("", "flux-bootstrap-")
if err != nil {
return fmt.Errorf("failed to create temporary working dir: %w", err)
}

View File

@@ -19,6 +19,7 @@ package main
import (
"context"
"fmt"
"io/ioutil"
"os"
"regexp"
"strings"
@@ -158,7 +159,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
}
// Lazy go-git repository
tmpDir, err := os.MkdirTemp("", "flux-bootstrap-")
tmpDir, err := ioutil.TempDir("", "flux-bootstrap-")
if err != nil {
return fmt.Errorf("failed to create temporary working dir: %w", err)
}

View File

@@ -1,37 +0,0 @@
// +build e2e
package main
import (
"context"
"encoding/json"
"strings"
"testing"
"github.com/fluxcd/flux2/internal/utils"
"k8s.io/apimachinery/pkg/version"
)
func TestCheckPre(t *testing.T) {
jsonOutput, err := utils.ExecKubectlCommand(context.TODO(), utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, "version", "--output", "json")
if err != nil {
t.Fatalf("Error running utils.ExecKubectlCommand: %v", err.Error())
}
var versions map[string]version.Info
if err := json.Unmarshal([]byte(jsonOutput), &versions); err != nil {
t.Fatalf("Error unmarshalling: %v", err.Error())
}
clientVersion := strings.TrimPrefix(versions["clientVersion"].GitVersion, "v")
serverVersion := strings.TrimPrefix(versions["serverVersion"].GitVersion, "v")
cmd := cmdTestCase{
args: "check --pre",
assert: assertGoldenTemplateFile("testdata/check/check_pre.golden", map[string]string{
"clientVersion": clientVersion,
"serverVersion": serverVersion,
}),
}
cmd.runTestCmd(t)
}

View File

@@ -20,7 +20,7 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"io/ioutil"
"github.com/fluxcd/flux2/internal/flags"
"github.com/fluxcd/flux2/internal/utils"
@@ -201,7 +201,7 @@ func createHelmReleaseCmdRun(cmd *cobra.Command, args []string) error {
if len(helmReleaseArgs.valuesFiles) > 0 {
valuesMap := make(map[string]interface{})
for _, v := range helmReleaseArgs.valuesFiles {
data, err := os.ReadFile(v)
data, err := ioutil.ReadFile(v)
if err != nil {
return fmt.Errorf("reading values from %s failed: %w", v, err)
}

View File

@@ -28,7 +28,7 @@ import (
"github.com/fluxcd/pkg/apis/meta"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var createImagePolicyCmd = &cobra.Command{

View File

@@ -26,7 +26,7 @@ import (
"github.com/fluxcd/pkg/apis/meta"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var createImageRepositoryCmd = &cobra.Command{

View File

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

View File

@@ -183,7 +183,7 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
if err := upsertSecret(ctx, kubeClient, s); err != nil {
return err
}
logger.Actionf("git secret '%s' created in '%s' namespace", name, rootArgs.namespace)
logger.Actionf("secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil
}

View File

@@ -112,6 +112,5 @@ func createSecretHelmCmdRun(cmd *cobra.Command, args []string) error {
return err
}
logger.Actionf("helm secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil
}

View File

@@ -109,6 +109,5 @@ func createSecretTLSCmdRun(cmd *cobra.Command, args []string) error {
return err
}
logger.Actionf("tls secret '%s' created in '%s' namespace", name, rootArgs.namespace)
return nil
}

View File

@@ -19,6 +19,7 @@ package main
import (
"context"
"fmt"
"io/ioutil"
"os"
"github.com/spf13/cobra"
@@ -111,7 +112,7 @@ func createSourceBucketCmdRun(cmd *cobra.Command, args []string) error {
return err
}
tmpDir, err := os.MkdirTemp("", name)
tmpDir, err := ioutil.TempDir("", name)
if err != nil {
return err
}

View File

@@ -20,6 +20,7 @@ import (
"context"
"crypto/elliptic"
"fmt"
"io/ioutil"
"net/url"
"os"
@@ -177,7 +178,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
return fmt.Errorf("recurse submodules requires --git-implementation=%s", sourcev1.GoGitImplementation)
}
tmpDir, err := os.MkdirTemp("", name)
tmpDir, err := ioutil.TempDir("", name)
if err != nil {
return err
}

View File

@@ -19,6 +19,7 @@ package main
import (
"context"
"fmt"
"io/ioutil"
"net/url"
"os"
@@ -105,7 +106,7 @@ func createSourceHelmCmdRun(cmd *cobra.Command, args []string) error {
return err
}
tmpDir, err := os.MkdirTemp("", name)
tmpDir, err := ioutil.TempDir("", name)
if err != nil {
return err
}

View File

@@ -148,7 +148,7 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
}
if createArgs.export {
for i := range tenantArgs.namespaces {
for i, _ := range tenantArgs.namespaces {
if err := exportTenant(namespaces[i], accounts[i], roleBindings[i]); err != nil {
return err
}
@@ -164,7 +164,7 @@ func createTenantCmdRun(cmd *cobra.Command, args []string) error {
return err
}
for i := range tenantArgs.namespaces {
for i, _ := range tenantArgs.namespaces {
logger.Actionf("applying namespace %s", namespaces[i].Name)
if err := upsertNamespace(ctx, kubeClient, namespaces[i]); err != nil {
return err

View File

@@ -19,7 +19,7 @@ package main
import (
"github.com/spf13/cobra"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var deleteImagePolicyCmd = &cobra.Command{

View File

@@ -19,7 +19,7 @@ package main
import (
"github.com/spf13/cobra"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var deleteImageRepositoryCmd = &cobra.Command{

View File

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

39
cmd/flux/encrypt.go Normal file
View File

@@ -0,0 +1,39 @@
/*
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 (
"github.com/spf13/cobra"
)
var encryptCmd = &cobra.Command{
Use: "encrypt",
Short: "Encrypt secrets using SOPS",
Long: "The encrypt sub-commands initialise and manage Secret encryption using SOPS.",
}
type encryptFlags struct {
export bool
}
var encryptArgs encryptFlags
func init() {
encryptCmd.PersistentFlags().BoolVar(&encryptArgs.export, "export", false, "export in YAML format to stdout")
rootCmd.AddCommand(encryptCmd)
}

113
cmd/flux/encrypt_init.go Normal file
View File

@@ -0,0 +1,113 @@
/*
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 (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"filippo.io/age"
"github.com/fluxcd/flux2/internal/utils"
"github.com/go-git/go-git/v5"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
var encryptInitCmd = &cobra.Command{
Use: "init",
Short: "Init SOPS encryption with age identity",
Long: "The encryption init command creates a new age identity and writes a .sops.yaml file to the current working directory.",
Example: ` # Init SOPS encryption with a new age identity
flux encryption init`,
RunE: encryptInitCmdRun,
}
func init() {
encryptCmd.AddCommand(encryptInitCmd)
}
func encryptInitCmdRun(cmd *cobra.Command, args []string) error {
// Confirm our current path is in a Git repository
path, err := os.Getwd()
if err != nil {
return err
}
if _, err := git.PlainOpen(path); err != nil {
if err == git.ErrRepositoryNotExists {
err = fmt.Errorf("'%s' is not in a Git repository", path)
}
return err
}
// Abort early if .sops.yaml already exists
sopsCfgPath := filepath.Join(path, ".sops.yaml")
if _, err := os.Stat(sopsCfgPath); err == nil || os.IsExist(err) {
return fmt.Errorf("'%s' already contains a .sops.yaml config", path)
}
// Generate a new identity
i, err := age.GenerateX25519Identity()
if err != nil {
return err
}
logger.Successf("Generated identity %s", i.Recipient().String())
// Attempt to configure identity in .sops.yaml
const sopsCfg = `creation_rules:
- path_regex: .*.yaml
encrypted_regex: ^(data|stringData)$
age: %s
`
if err := ioutil.WriteFile(sopsCfgPath, []byte(fmt.Sprintf(sopsCfg, i.Recipient().String())), 0644); err != nil {
logger.Failuref("Failed to write recipient to .sops.yaml file")
return err
}
logger.Successf("Configured recipient in .sops.yaml file")
// Init client
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
}
// Create a secret
secret := &corev1.Secret{
ObjectMeta: v1.ObjectMeta{
Name: "sops-age",
Namespace: rootArgs.namespace,
},
StringData: map[string]string{
"flux-auto.age": i.String(),
},
}
if err := kubeClient.Create(ctx, secret); err != nil {
return err
}
logger.Successf(`Secret '%s' with private key created`, secret.Name)
// TODO(hidde): lookup kustomize based on path ref? Do direct cluster mutation? (Preferably not!)
// Feels something is missing in general to provide a user experience improving bridge between "die hard"
// `--export` and "please do not do this" direct-apply-to-cluster.
return nil
}

View File

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

View File

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

View File

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

View File

@@ -25,9 +25,6 @@ import (
"github.com/spf13/cobra"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
watchtools "k8s.io/client-go/tools/watch"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/fluxcd/pkg/apis/meta"
@@ -35,26 +32,6 @@ import (
"github.com/fluxcd/flux2/internal/utils"
)
type deriveType func(runtime.Object) (summarisable, error)
type typeMap map[string]deriveType
func (m typeMap) registerCommand(t string, f deriveType) error {
if _, ok := m[t]; ok {
return fmt.Errorf("duplicate type function %s", t)
}
m[t] = f
return nil
}
func (m typeMap) execute(t string, obj runtime.Object) (summarisable, error) {
f, ok := m[t]
if !ok {
return nil, fmt.Errorf("unsupported type %s", t)
}
return f(obj)
}
var getCmd = &cobra.Command{
Use: "get",
Short: "Get the resources and their status",
@@ -62,10 +39,7 @@ var getCmd = &cobra.Command{
}
type GetFlags struct {
allNamespaces bool
noHeader bool
statusSelector string
watch bool
allNamespaces bool
}
var getArgs GetFlags
@@ -73,10 +47,6 @@ var getArgs GetFlags
func init() {
getCmd.PersistentFlags().BoolVarP(&getArgs.allNamespaces, "all-namespaces", "A", false,
"list the requested object(s) across all namespaces")
getCmd.PersistentFlags().BoolVarP(&getArgs.noHeader, "no-header", "", false, "skip the header when printing the results")
getCmd.PersistentFlags().BoolVarP(&getArgs.watch, "watch", "w", false, "After listing/getting the requested object, watch for changes.")
getCmd.PersistentFlags().StringVar(&getArgs.statusSelector, "status-selector", "",
"specify the status condition name and the desired state to filter the get result, e.g. ready=false")
rootCmd.AddCommand(getCmd)
}
@@ -84,7 +54,6 @@ type summarisable interface {
listAdapter
summariseItem(i int, includeNamespace bool, includeKind bool) []string
headers(includeNamespace bool) []string
statusSelectorMatches(i int, conditionType, conditionStatus string) bool
}
// --- these help with implementations of summarisable
@@ -96,20 +65,6 @@ func statusAndMessage(conditions []metav1.Condition) (string, string) {
return string(metav1.ConditionFalse), "waiting to be reconciled"
}
func statusMatches(conditionType, conditionStatus string, conditions []metav1.Condition) bool {
// we don't use apimeta.FindStatusCondition because we'd like to use EqualFold to compare two strings
var c *metav1.Condition
for i := range conditions {
if strings.EqualFold(conditions[i].Type, conditionType) {
c = &conditions[i]
}
}
if c != nil {
return strings.EqualFold(string(c.Status), conditionStatus)
}
return false
}
func nameColumns(item named, includeNamespace bool, includeKind bool) []string {
name := item.GetName()
if includeKind {
@@ -127,8 +82,7 @@ var namespaceHeader = []string{"Namespace"}
type getCommand struct {
apiType
list summarisable
funcMap typeMap
list summarisable
}
func (get getCommand) run(cmd *cobra.Command, args []string) error {
@@ -149,17 +103,13 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
listOpts = append(listOpts, client.MatchingFields{"metadata.name": args[0]})
}
getAll := cmd.Use == "all"
if getArgs.watch {
return get.watch(ctx, kubeClient, cmd, args, listOpts)
}
err = kubeClient.List(ctx, get.list.asClientList(), listOpts...)
if err != nil {
return err
}
getAll := cmd.Use == "all"
if get.list.len() == 0 {
if !getAll {
logger.Failuref("no %s objects found in %s namespace", get.kind, rootArgs.namespace)
@@ -167,97 +117,16 @@ func (get getCommand) run(cmd *cobra.Command, args []string) error {
return nil
}
var header []string
if !getArgs.noHeader {
header = get.list.headers(getArgs.allNamespaces)
header := get.list.headers(getArgs.allNamespaces)
var rows [][]string
for i := 0; i < get.list.len(); i++ {
row := get.list.summariseItem(i, getArgs.allNamespaces, getAll)
rows = append(rows, row)
}
rows, err := getRowsToPrint(getAll, get.list)
if err != nil {
return err
}
utils.PrintTable(cmd.OutOrStderr(), header, rows)
utils.PrintTable(os.Stdout, header, rows)
if getAll {
fmt.Println()
}
return nil
}
func getRowsToPrint(getAll bool, list summarisable) ([][]string, error) {
noFilter := true
var conditionType, conditionStatus string
if getArgs.statusSelector != "" {
parts := strings.SplitN(getArgs.statusSelector, "=", 2)
if len(parts) != 2 {
return nil, fmt.Errorf("expected status selector in type=status format, but found: %s", getArgs.statusSelector)
}
conditionType = parts[0]
conditionStatus = parts[1]
noFilter = false
}
var rows [][]string
for i := 0; i < list.len(); i++ {
if noFilter || list.statusSelectorMatches(i, conditionType, conditionStatus) {
row := list.summariseItem(i, getArgs.allNamespaces, getAll)
rows = append(rows, row)
}
}
return rows, nil
}
//
// watch starts a client-side watch of one or more resources.
func (get *getCommand) watch(ctx context.Context, kubeClient client.WithWatch, cmd *cobra.Command, args []string, listOpts []client.ListOption) error {
w, err := kubeClient.Watch(ctx, get.list.asClientList(), listOpts...)
if err != nil {
return err
}
_, err = watchUntil(ctx, w, get)
if err != nil {
return err
}
return nil
}
func watchUntil(ctx context.Context, w watch.Interface, get *getCommand) (bool, error) {
firstIteration := true
_, error := watchtools.UntilWithoutRetry(ctx, w, func(e watch.Event) (bool, error) {
objToPrint := e.Object
sink, err := get.funcMap.execute(get.apiType.kind, objToPrint)
if err != nil {
return false, err
}
var header []string
if !getArgs.noHeader {
header = sink.headers(getArgs.allNamespaces)
}
rows, err := getRowsToPrint(false, sink)
if err != nil {
return false, err
}
if firstIteration {
utils.PrintTable(os.Stdout, header, rows)
firstIteration = false
} else {
utils.PrintTable(os.Stdout, []string{}, rows)
}
return false, nil
})
return false, error
}
func validateWatchOption(cmd *cobra.Command, toMatch string) error {
w, _ := cmd.Flags().GetBool("watch")
if cmd.Use == toMatch && w {
return fmt.Errorf("expected a single resource type, but found %s", cmd.Use)
}
return nil
}

View File

@@ -17,12 +17,10 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
)
@@ -34,39 +32,10 @@ var getAlertCmd = &cobra.Command{
Long: "The get alert command prints the statuses of the resources.",
Example: ` # List all Alerts and their status
flux get alerts`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: alertType,
list: &alertListAdapter{&notificationv1.AlertList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*notificationv1.Alert)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v alert", obj)
}
sink := alertListAdapter{
&notificationv1.AlertList{
Items: []notificationv1.Alert{
*o,
},
},
}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: alertType,
list: &alertListAdapter{&notificationv1.AlertList{}},
}.run,
}
func init() {
@@ -86,8 +55,3 @@ func (s alertListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (s alertListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := s.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -17,10 +17,7 @@ limitations under the License.
package main
import (
"fmt"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
)
@@ -32,39 +29,10 @@ var getAlertProviderCmd = &cobra.Command{
Long: "The get alert-provider command prints the statuses of the resources.",
Example: ` # List all Providers and their status
flux get alert-providers`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: alertProviderType,
list: alertProviderListAdapter{&notificationv1.ProviderList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*notificationv1.Provider)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v alert-provider", obj)
}
sink := alertProviderListAdapter{
&notificationv1.ProviderList{
Items: []notificationv1.Provider{
*o,
},
},
}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: alertProviderType,
list: alertProviderListAdapter{&notificationv1.ProviderList{}},
}.run,
}
func init() {
@@ -84,8 +52,3 @@ func (s alertProviderListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (s alertProviderListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := s.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -36,12 +36,7 @@ var getAllCmd = &cobra.Command{
# List all resources in all namespaces
flux get all --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
err := validateWatchOption(cmd, "all")
if err != nil {
return err
}
err = getSourceAllCmd.RunE(cmd, args)
err := getSourceAllCmd.RunE(cmd, args)
if err != nil {
logError(err)
}

View File

@@ -17,13 +17,11 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
)
var getHelmReleaseCmd = &cobra.Command{
@@ -33,36 +31,10 @@ var getHelmReleaseCmd = &cobra.Command{
Long: "The get helmreleases command prints the statuses of the resources.",
Example: ` # List all Helm releases and their status
flux get helmreleases`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: helmReleaseType,
list: &helmReleaseListAdapter{&helmv2.HelmReleaseList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*helmv2.HelmRelease)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v helmrelease", obj)
}
sink := helmReleaseListAdapter{&helmv2.HelmReleaseList{
Items: []helmv2.HelmRelease{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: helmReleaseType,
list: &helmReleaseListAdapter{&helmv2.HelmReleaseList{}},
}.run,
}
func init() {
@@ -84,8 +56,3 @@ func (a helmReleaseListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (a helmReleaseListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := a.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -25,9 +25,6 @@ var getImageCmd = &cobra.Command{
Aliases: []string{"image"},
Short: "Get image automation object status",
Long: "The get image sub-commands print the status of image automation objects.",
RunE: func(cmd *cobra.Command, args []string) error {
return validateWatchOption(cmd, "images")
},
}
func init() {

View File

@@ -21,8 +21,8 @@ import (
"github.com/spf13/cobra"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var getImageAllCmd = &cobra.Command{
@@ -35,11 +35,6 @@ var getImageAllCmd = &cobra.Command{
# List all image objects in all namespaces
flux get images all --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
err := validateWatchOption(cmd, "all")
if err != nil {
return err
}
var allImageCmd = []getCommand{
{
apiType: imageRepositoryType,

View File

@@ -17,12 +17,9 @@ limitations under the License.
package main
import (
"fmt"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var getImagePolicyCmd = &cobra.Command{
@@ -34,36 +31,10 @@ var getImagePolicyCmd = &cobra.Command{
# List image policies from all namespaces
flux get image policy --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: imagePolicyType,
list: &imagePolicyListAdapter{&imagev1.ImagePolicyList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*imagev1.ImagePolicy)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v policy", obj)
}
sink := imagePolicyListAdapter{&imagev1.ImagePolicyList{
Items: []imagev1.ImagePolicy{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: imagePolicyType,
list: &imagePolicyListAdapter{&imagev1.ImagePolicyList{}},
}.run,
}
func init() {
@@ -83,8 +54,3 @@ func (s imagePolicyListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (s imagePolicyListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := s.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -17,15 +17,13 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var getImageRepositoryCmd = &cobra.Command{
@@ -37,36 +35,10 @@ var getImageRepositoryCmd = &cobra.Command{
# List image repositories from all namespaces
flux get image repository --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: imageRepositoryType,
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*imagev1.ImageRepository)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v repository", obj)
}
sink := imageRepositoryListAdapter{&imagev1.ImageRepositoryList{
Items: []imagev1.ImageRepository{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: imageRepositoryType,
list: imageRepositoryListAdapter{&imagev1.ImageRepositoryList{}},
}.run,
}
func init() {
@@ -91,8 +63,3 @@ func (s imageRepositoryListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (s imageRepositoryListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := s.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -17,15 +17,13 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
)
var getImageUpdateCmd = &cobra.Command{
@@ -37,36 +35,10 @@ var getImageUpdateCmd = &cobra.Command{
# List image update automations from all namespaces
flux get image update --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: imageUpdateAutomationType,
list: &imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*autov1.ImageUpdateAutomation)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v update", obj)
}
sink := imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{
Items: []autov1.ImageUpdateAutomation{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: imageUpdateAutomationType,
list: &imageUpdateAutomationListAdapter{&autov1.ImageUpdateAutomationList{}},
}.run,
}
func init() {
@@ -90,8 +62,3 @@ func (s imageUpdateAutomationListAdapter) headers(includeNamespace bool) []strin
}
return headers
}
func (s imageUpdateAutomationListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := s.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -17,12 +17,10 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta1"
)
@@ -34,39 +32,10 @@ var getKsCmd = &cobra.Command{
Long: "The get kustomizations command prints the statuses of the resources.",
Example: ` # List all kustomizations and their status
flux get kustomizations`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: kustomizationType,
list: &kustomizationListAdapter{&kustomizev1.KustomizationList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*kustomizev1.Kustomization)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v kustomization", obj)
}
sink := kustomizationListAdapter{
&kustomizev1.KustomizationList{
Items: []kustomizev1.Kustomization{
*o,
},
},
}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: kustomizationType,
list: &kustomizationListAdapter{&kustomizev1.KustomizationList{}},
}.run,
}
func init() {
@@ -88,8 +57,3 @@ func (a kustomizationListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (a kustomizationListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := a.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -17,12 +17,10 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
notificationv1 "github.com/fluxcd/notification-controller/api/v1beta1"
)
@@ -34,36 +32,10 @@ var getReceiverCmd = &cobra.Command{
Long: "The get receiver command prints the statuses of the resources.",
Example: ` # List all Receiver and their status
flux get receivers`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: receiverType,
list: receiverListAdapter{&notificationv1.ReceiverList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*notificationv1.Receiver)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v receiver", obj)
}
sink := receiverListAdapter{&notificationv1.ReceiverList{
Items: []notificationv1.Receiver{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: receiverType,
list: receiverListAdapter{&notificationv1.ReceiverList{}},
}.run,
}
func init() {
@@ -83,8 +55,3 @@ func (s receiverListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (s receiverListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := s.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -25,10 +25,6 @@ var getSourceCmd = &cobra.Command{
Aliases: []string{"source"},
Short: "Get source statuses",
Long: "The get source sub-commands print the statuses of the sources.",
RunE: func(cmd *cobra.Command, args []string) error {
return validateWatchOption(cmd, "sources")
},
}
func init() {

View File

@@ -34,11 +34,6 @@ var getSourceAllCmd = &cobra.Command{
# List all sources in all namespaces
flux get sources all --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
err := validateWatchOption(cmd, "all")
if err != nil {
return err
}
var allSourceCmd = []getCommand{
{
apiType: bucketType,

View File

@@ -17,12 +17,10 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
@@ -36,36 +34,10 @@ var getSourceBucketCmd = &cobra.Command{
# List buckets from all namespaces
flux get sources helm --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: bucketType,
list: &bucketListAdapter{&sourcev1.BucketList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*sourcev1.Bucket)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v bucket", obj)
}
sink := &bucketListAdapter{&sourcev1.BucketList{
Items: []sourcev1.Bucket{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: bucketType,
list: &bucketListAdapter{&sourcev1.BucketList{}},
}.run,
}
func init() {
@@ -90,8 +62,3 @@ func (a bucketListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (a bucketListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := a.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -17,12 +17,10 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
@@ -36,36 +34,10 @@ var getSourceHelmChartCmd = &cobra.Command{
# List Helm charts from all namespaces
flux get sources chart --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: helmChartType,
list: &helmChartListAdapter{&sourcev1.HelmChartList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*sourcev1.HelmChart)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v chart", obj)
}
sink := &helmChartListAdapter{&sourcev1.HelmChartList{
Items: []sourcev1.HelmChart{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: helmChartType,
list: &helmChartListAdapter{&sourcev1.HelmChartList{}},
}.run,
}
func init() {
@@ -90,8 +62,3 @@ func (a helmChartListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (a helmChartListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := a.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -17,12 +17,10 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
@@ -36,36 +34,10 @@ var getSourceGitCmd = &cobra.Command{
# List Git repositories from all namespaces
flux get sources git --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: gitRepositoryType,
list: &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*sourcev1.GitRepository)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v git", obj)
}
sink := &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{
Items: []sourcev1.GitRepository{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: gitRepositoryType,
list: &gitRepositoryListAdapter{&sourcev1.GitRepositoryList{}},
}.run,
}
func init() {
@@ -90,8 +62,3 @@ func (a gitRepositoryListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (a gitRepositoryListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := a.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -17,12 +17,10 @@ limitations under the License.
package main
import (
"fmt"
"strconv"
"strings"
"github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime"
sourcev1 "github.com/fluxcd/source-controller/api/v1beta1"
)
@@ -36,36 +34,10 @@ var getSourceHelmCmd = &cobra.Command{
# List Helm repositories from all namespaces
flux get sources helm --all-namespaces`,
RunE: func(cmd *cobra.Command, args []string) error {
get := getCommand{
apiType: helmRepositoryType,
list: &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
funcMap: make(typeMap),
}
err := get.funcMap.registerCommand(get.apiType.kind, func(obj runtime.Object) (summarisable, error) {
o, ok := obj.(*sourcev1.HelmRepository)
if !ok {
return nil, fmt.Errorf("Impossible to cast type %#v helm", obj)
}
sink := &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{
Items: []sourcev1.HelmRepository{
*o,
}}}
return sink, nil
})
if err != nil {
return err
}
if err := get.run(cmd, args); err != nil {
return err
}
return nil
},
RunE: getCommand{
apiType: helmRepositoryType,
list: &helmRepositoryListAdapter{&sourcev1.HelmRepositoryList{}},
}.run,
}
func init() {
@@ -90,8 +62,3 @@ func (a helmRepositoryListAdapter) headers(includeNamespace bool) []string {
}
return headers
}
func (a helmRepositoryListAdapter) statusSelectorMatches(i int, conditionType, conditionStatus string) bool {
item := a.Items[i]
return statusMatches(conditionType, conditionStatus, item.Status.Conditions)
}

View File

@@ -37,10 +37,6 @@ func (h helmReleaseAdapter) asClientObject() client.Object {
return h.HelmRelease
}
func (h helmReleaseAdapter) deepCopyClientObject() client.Object {
return h.HelmRelease.DeepCopy()
}
// helmv2.HelmReleaseList
type helmReleaseListAdapter struct {

View File

@@ -1,56 +0,0 @@
// +build e2e
package main
import "testing"
func TestHelmReleaseFromGit(t *testing.T) {
cases := []struct {
args string
goldenFile string
}{
{
"create source git thrfg --url=https://github.com/stefanprodan/podinfo --branch=main --tag=6.0.0",
"testdata/helmrelease/create_source_git.golden",
},
{
"create helmrelease thrfg --source=GitRepository/thrfg --chart=./charts/podinfo",
"testdata/helmrelease/create_helmrelease_from_git.golden",
},
{
"get helmrelease thrfg",
"testdata/helmrelease/get_helmrelease_from_git.golden",
},
{
"reconcile helmrelease thrfg --with-source",
"testdata/helmrelease/reconcile_helmrelease_from_git.golden",
},
{
"suspend helmrelease thrfg",
"testdata/helmrelease/suspend_helmrelease_from_git.golden",
},
{
"resume helmrelease thrfg",
"testdata/helmrelease/resume_helmrelease_from_git.golden",
},
{
"delete helmrelease thrfg --silent",
"testdata/helmrelease/delete_helmrelease_from_git.golden",
},
}
namespace := allocateNamespace("thrfg")
del, err := setupTestNamespace(namespace)
if err != nil {
t.Fatal(err)
}
defer del()
for _, tc := range cases {
cmd := cmdTestCase{
args: tc.args + " -n=" + namespace,
assert: assertGoldenTemplateFile(tc.goldenFile, map[string]string{"ns": namespace}),
}
cmd.runTestCmd(t)
}
}

View File

@@ -19,8 +19,8 @@ package main
import (
"sigs.k8s.io/controller-runtime/pkg/client"
autov1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
autov1 "github.com/fluxcd/image-automation-controller/api/v1alpha2"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
// These are general-purpose adapters for attaching methods to, for
@@ -42,10 +42,6 @@ func (a imageRepositoryAdapter) asClientObject() client.Object {
return a.ImageRepository
}
func (a imageRepositoryAdapter) deepCopyClientObject() client.Object {
return a.ImageRepository.DeepCopy()
}
// imagev1.ImageRepositoryList
type imageRepositoryListAdapter struct {
@@ -104,10 +100,6 @@ func (a imageUpdateAutomationAdapter) asClientObject() client.Object {
return a.ImageUpdateAutomation
}
func (a imageUpdateAutomationAdapter) deepCopyClientObject() client.Object {
return a.ImageUpdateAutomation.DeepCopy()
}
// autov1.ImageUpdateAutomationList
type imageUpdateAutomationListAdapter struct {

View File

@@ -1,48 +0,0 @@
// +build e2e
package main
import "testing"
func TestImageScanning(t *testing.T) {
cases := []struct {
args string
goldenFile string
}{
{
"create image repository podinfo --image=ghcr.io/stefanprodan/podinfo --interval=10m",
"testdata/image/create_image_repository.golden",
},
{
"create image policy podinfo-semver --image-ref=podinfo --interval=10m --select-semver=5.0.x",
"testdata/image/create_image_policy.golden",
},
{
"get image policy podinfo-semver",
"testdata/image/get_image_policy_semver.golden",
},
{
`create image policy podinfo-regex --image-ref=podinfo --interval=10m --select-semver=">4.0.0" --filter-regex="5\.0\.0"`,
"testdata/image/create_image_policy.golden",
},
{
"get image policy podinfo-regex",
"testdata/image/get_image_policy_regex.golden",
},
}
namespace := allocateNamespace("tis")
del, err := setupTestNamespace(namespace)
if err != nil {
t.Fatal(err)
}
defer del()
for _, tc := range cases {
cmd := cmdTestCase{
args: tc.args + " -n=" + namespace,
assert: assertGoldenFile(tc.goldenFile),
}
cmd.runTestCmd(t)
}
}

View File

@@ -19,6 +19,7 @@ package main
import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
@@ -131,7 +132,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
logger.Generatef("generating manifests")
}
tmpDir, err := os.MkdirTemp("", rootArgs.namespace)
tmpDir, err := ioutil.TempDir("", rootArgs.namespace)
if err != nil {
return err
}

View File

@@ -37,10 +37,6 @@ func (a kustomizationAdapter) asClientObject() client.Object {
return a.Kustomization
}
func (a kustomizationAdapter) deepCopyClientObject() client.Object {
return a.Kustomization.DeepCopy()
}
// kustomizev1.KustomizationList
type kustomizationListAdapter struct {

View File

@@ -1,56 +0,0 @@
// +build e2e
package main
import "testing"
func TestKustomizationFromGit(t *testing.T) {
cases := []struct {
args string
goldenFile string
}{
{
"create source git tkfg --url=https://github.com/stefanprodan/podinfo --branch=main --tag=6.0.0",
"testdata/kustomization/create_source_git.golden",
},
{
"create kustomization tkfg --source=tkfg --path=./deploy/overlays/dev --prune=true --interval=5m --validation=client --health-check=Deployment/frontend.dev --health-check=Deployment/backend.dev --health-check-timeout=3m",
"testdata/kustomization/create_kustomization_from_git.golden",
},
{
"get kustomization tkfg",
"testdata/kustomization/get_kustomization_from_git.golden",
},
{
"reconcile kustomization tkfg --with-source",
"testdata/kustomization/reconcile_kustomization_from_git.golden",
},
{
"suspend kustomization tkfg",
"testdata/kustomization/suspend_kustomization_from_git.golden",
},
{
"resume kustomization tkfg",
"testdata/kustomization/resume_kustomization_from_git.golden",
},
{
"delete kustomization tkfg --silent",
"testdata/kustomization/delete_kustomization_from_git.golden",
},
}
namespace := allocateNamespace("tkfg")
del, err := setupTestNamespace(namespace)
if err != nil {
t.Fatal(err)
}
defer del()
for _, tc := range cases {
cmd := cmdTestCase{
args: tc.args + " -n=" + namespace,
assert: assertGoldenTemplateFile(tc.goldenFile, map[string]string{"ns": namespace}),
}
cmd.runTestCmd(t)
}
}

View File

@@ -26,14 +26,12 @@ import (
"os"
"strings"
"sync"
"time"
"github.com/spf13/cobra"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/kubectl/pkg/util"
"github.com/fluxcd/flux2/internal/flags"
"github.com/fluxcd/flux2/internal/utils"
@@ -44,19 +42,16 @@ var logsCmd = &cobra.Command{
Short: "Display formatted logs for Flux components",
Long: "The logs command displays formatted logs from various Flux components.",
Example: ` # Print the reconciliation logs of all Flux custom resources in your cluster
flux logs --all-namespaces
# Print all logs of all Flux custom resources newer than 2 minutes
flux logs --all-namespaces --since=2m
flux logs --all-namespaces
# Stream logs for a particular log level
flux logs --follow --level=error --all-namespaces
# Stream logs for a particular log level
flux logs --follow --level=error --all-namespaces
# Filter logs by kind, name and namespace
flux logs --kind=Kustomization --name=podinfo --namespace=default
# Filter logs by kind, name and namespace
flux logs --kind=Kustomization --name=podinfo --namespace=default
# Print logs when Flux is installed in a different namespace than flux-system
flux logs --flux-namespace=my-namespace
# Print logs when Flux is installed in a different namespace than flux-system
flux logs --flux-namespace=my-namespace
`,
RunE: logsCmdRun,
}
@@ -69,8 +64,6 @@ type logsFlags struct {
name string
fluxNamespace string
allNamespaces bool
sinceTime string
sinceSeconds time.Duration
}
var logsArgs = &logsFlags{
@@ -85,8 +78,6 @@ func init() {
logsCmd.Flags().Int64VarP(&logsArgs.tail, "tail", "", logsArgs.tail, "lines of recent log file to display")
logsCmd.Flags().StringVarP(&logsArgs.fluxNamespace, "flux-namespace", "", rootArgs.defaults.Namespace, "the namespace where the Flux components are running")
logsCmd.Flags().BoolVarP(&logsArgs.allNamespaces, "all-namespaces", "A", false, "displays logs for objects across all namespaces")
logsCmd.Flags().DurationVar(&logsArgs.sinceSeconds, "since", logsArgs.sinceSeconds, "Only return logs newer than a relative duration like 5s, 2m, or 3h. Defaults to all logs. Only one of since-time / since may be used.")
logsCmd.Flags().StringVar(&logsArgs.sinceTime, "since-time", logsArgs.sinceTime, "Only return logs after a specific date (RFC3339). Defaults to all logs. Only one of since-time / since may be used.")
rootCmd.AddCommand(logsCmd)
}
@@ -96,6 +87,7 @@ func logsCmdRun(cmd *cobra.Command, args []string) error {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
var pods []corev1.Pod
cfg, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return err
@@ -110,7 +102,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, fluxSelector)
if err != nil {
return err
}
@@ -123,24 +115,6 @@ func logsCmdRun(cmd *cobra.Command, args []string) error {
logOpts.TailLines = &logsArgs.tail
}
if len(logsArgs.sinceTime) > 0 && logsArgs.sinceSeconds != 0 {
return fmt.Errorf("at most one of `sinceTime` or `sinceSeconds` may be specified")
}
if len(logsArgs.sinceTime) > 0 {
t, err := util.ParseRFC3339(logsArgs.sinceTime, metav1.Now)
if err != nil {
return fmt.Errorf("%s is not a valid (RFC3339) time", logsArgs.sinceTime)
}
logOpts.SinceTime = &t
}
if logsArgs.sinceSeconds != 0 {
// round up to the nearest second
sec := int64(logsArgs.sinceSeconds.Round(time.Second).Seconds())
logOpts.SinceSeconds = &sec
}
var requests []rest.ResponseWrapper
for _, pod := range pods {
req := clientset.CoreV1().Pods(logsArgs.fluxNamespace).GetLogs(pod.Name, logOpts)

View File

@@ -1,63 +0,0 @@
// +build unit
package main
import (
"testing"
)
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)
}

View File

@@ -1,62 +0,0 @@
// +build e2e
package main
import (
"context"
"fmt"
"os"
"testing"
"github.com/fluxcd/flux2/internal/utils"
)
func TestMain(m *testing.M) {
// Ensure tests print consistent timestamps regardless of timezone
os.Setenv("TZ", "UTC")
testEnv, err := NewTestEnvKubeManager(ExistingClusterMode)
if err != nil {
panic(fmt.Errorf("error creating kube manager: '%w'", err))
}
rootArgs.kubeconfig = testEnv.kubeConfigPath
// 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))
}
// Run tests
code := m.Run()
// Uninstall Flux
output, err = executeCommand("uninstall -s --keep-namespace")
if err != nil {
panic(fmt.Errorf("uninstall falied: %s error:'%w'", output, err))
}
// Delete namespace and wait for finalisation
kubectlArgs := []string{"delete", "namespace", "flux-system"}
_, err = utils.ExecKubectlCommand(context.TODO(), utils.ModeStderrOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
if err != nil {
panic(fmt.Errorf("delete namespace error:'%w'", err))
}
testEnv.Stop()
os.Exit(code)
}
func setupTestNamespace(namespace string) (func(), error) {
kubectlArgs := []string{"create", "namespace", namespace}
_, err := utils.ExecKubectlCommand(context.TODO(), utils.ModeStderrOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
if err != nil {
return nil, err
}
return func() {
kubectlArgs := []string{"delete", "namespace", namespace}
utils.ExecKubectlCommand(context.TODO(), utils.ModeCapture, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...)
}, nil
}

View File

@@ -1,310 +0,0 @@
package main
import (
"bufio"
"bytes"
"context"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"sync/atomic"
"testing"
"text/template"
"time"
"github.com/google/go-cmp/cmp"
"github.com/mattn/go-shellwords"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/envtest"
)
var nextNamespaceId int64
// Return a unique namespace with the specified prefix, for tests to create
// objects that won't collide with each other.
func allocateNamespace(prefix string) string {
id := atomic.AddInt64(&nextNamespaceId, 1)
return fmt.Sprintf("%s-%d", prefix, id)
}
func readYamlObjects(rdr io.Reader) ([]unstructured.Unstructured, error) {
objects := []unstructured.Unstructured{}
reader := k8syaml.NewYAMLReader(bufio.NewReader(rdr))
for {
doc, err := reader.Read()
if err != nil {
if err == io.EOF {
break
}
}
unstructuredObj := &unstructured.Unstructured{}
decoder := k8syaml.NewYAMLOrJSONDecoder(bytes.NewBuffer(doc), len(doc))
err = decoder.Decode(unstructuredObj)
if err != nil {
return nil, err
}
objects = append(objects, *unstructuredObj)
}
return objects, nil
}
// A KubeManager that can create objects that are subject to a test.
type testEnvKubeManager struct {
client client.WithWatch
testEnv *envtest.Environment
kubeConfigPath string
}
func (m *testEnvKubeManager) CreateObjectFile(objectFile string, templateValues map[string]string, t *testing.T) {
buf, err := os.ReadFile(objectFile)
if err != nil {
t.Fatalf("Error reading file '%s': %v", objectFile, err)
}
content, err := executeTemplate(string(buf), templateValues)
if err != nil {
t.Fatalf("Error evaluating template file '%s': '%v'", objectFile, err)
}
clientObjects, err := readYamlObjects(strings.NewReader(content))
if err != nil {
t.Fatalf("Error decoding yaml file '%s': %v", objectFile, err)
}
err = m.CreateObjects(clientObjects, t)
if err != nil {
t.Logf("Error creating test objects: '%v'", err)
}
}
func (m *testEnvKubeManager) CreateObjects(clientObjects []unstructured.Unstructured, t *testing.T) error {
for _, obj := range clientObjects {
// First create the object then set its status if present in the
// yaml file. Make a copy first since creating an object may overwrite
// the status.
createObj := obj.DeepCopy()
err := m.client.Create(context.Background(), createObj)
if err != nil {
return err
}
obj.SetResourceVersion(createObj.GetResourceVersion())
err = m.client.Status().Update(context.Background(), &obj)
if err != nil {
return err
}
}
return nil
}
func (m *testEnvKubeManager) Stop() error {
if m.testEnv == nil {
return fmt.Errorf("do nothing because testEnv is nil")
}
return m.testEnv.Stop()
}
func NewTestEnvKubeManager(testClusterMode TestClusterMode) (*testEnvKubeManager, error) {
switch testClusterMode {
case TestEnvClusterMode:
useExistingCluster := false
testEnv := &envtest.Environment{
UseExistingCluster: &useExistingCluster,
CRDDirectoryPaths: []string{"manifests"},
}
cfg, err := testEnv.Start()
if err != nil {
return nil, err
}
user, err := testEnv.ControlPlane.AddUser(envtest.User{
Name: "envtest-admin",
Groups: []string{"system:masters"},
}, nil)
if err != nil {
return nil, err
}
kubeConfig, err := user.KubeConfig()
if err != nil {
return nil, err
}
tmpFilename := filepath.Join("/tmp", "kubeconfig-"+time.Nanosecond.String())
os.WriteFile(tmpFilename, kubeConfig, 0644)
k8sClient, err := client.NewWithWatch(cfg, client.Options{})
if err != nil {
return nil, err
}
return &testEnvKubeManager{
testEnv: testEnv,
client: k8sClient,
kubeConfigPath: tmpFilename,
}, nil
case ExistingClusterMode:
// TEST_KUBECONFIG is mandatory to prevent destroying a current cluster accidentally.
testKubeConfig := os.Getenv("TEST_KUBECONFIG")
if testKubeConfig == "" {
return nil, fmt.Errorf("environment variable TEST_KUBECONFIG is required to run tests against an existing cluster")
}
useExistingCluster := true
config, err := clientcmd.BuildConfigFromFlags("", testKubeConfig)
testEnv := &envtest.Environment{
UseExistingCluster: &useExistingCluster,
Config: config,
}
cfg, err := testEnv.Start()
if err != nil {
return nil, err
}
k8sClient, err := client.NewWithWatch(cfg, client.Options{})
if err != nil {
return nil, err
}
return &testEnvKubeManager{
testEnv: testEnv,
client: k8sClient,
kubeConfigPath: testKubeConfig,
}, nil
}
return nil, nil
}
// Function that sets an expectation on the output of a command. Tests can
// either implement this directly or use a helper below.
type assertFunc func(output string, err error) error
// Assemble multiple assertFuncs into a single assertFunc
func assert(fns ...assertFunc) assertFunc {
return func(output string, err error) error {
for _, fn := range fns {
if assertErr := fn(output, err); assertErr != nil {
return assertErr
}
}
return nil
}
}
// Expect the command to run without error
func assertSuccess() assertFunc {
return func(output string, err error) error {
if err != nil {
return fmt.Errorf("Expected success but was error: %v", err)
}
return nil
}
}
// Expect the command to fail with the specified error
func assertError(expected string) assertFunc {
return func(output string, err error) error {
if err == nil {
return fmt.Errorf("Expected error but was success")
}
if expected != err.Error() {
return fmt.Errorf("Expected error '%v' but got '%v'", expected, err.Error())
}
return nil
}
}
// Expect the command to succeed with the expected test output.
func assertGoldenValue(expected string) assertFunc {
return assert(
assertSuccess(),
func(output string, err error) error {
diff := cmp.Diff(expected, output)
if diff != "" {
return fmt.Errorf("Mismatch from expected value (-want +got):\n%s", diff)
}
return nil
})
}
// Filename that contains the expected test output.
func assertGoldenFile(goldenFile string) assertFunc {
return assertGoldenTemplateFile(goldenFile, map[string]string{})
}
// Filename that contains the expected test output. The golden file is a template that
// is pre-processed with the specified templateValues.
func assertGoldenTemplateFile(goldenFile string, templateValues map[string]string) assertFunc {
goldenFileContents, fileErr := os.ReadFile(goldenFile)
return func(output string, err error) error {
if fileErr != nil {
return fmt.Errorf("Error reading golden file '%s': %s", goldenFile, fileErr)
}
var expectedOutput string
if len(templateValues) > 0 {
expectedOutput, err = executeTemplate(string(goldenFileContents), templateValues)
if err != nil {
return fmt.Errorf("Error executing golden template file '%s': %s", goldenFile, err)
}
} else {
expectedOutput = string(goldenFileContents)
}
if assertErr := assertGoldenValue(expectedOutput)(output, err); assertErr != nil {
return fmt.Errorf("Mismatch from golden file '%s': %v", goldenFile, assertErr)
}
return nil
}
}
type TestClusterMode int
const (
TestEnvClusterMode = TestClusterMode(iota + 1)
ExistingClusterMode
)
// Structure used for each test to load objects into kubernetes, run
// commands and assert on the expected output.
type cmdTestCase struct {
// The command line arguments to test.
args string
// Tests use assertFunc to assert on an output, success or failure. This
// can be a function defined by the test or existing function above.
assert assertFunc
// Filename that contains yaml objects to load into Kubernetes
objectFile string
}
func (cmd *cmdTestCase) runTestCmd(t *testing.T) {
actual, testErr := executeCommand(cmd.args)
if assertErr := cmd.assert(actual, testErr); assertErr != nil {
t.Error(assertErr)
}
}
func executeTemplate(content string, templateValues map[string]string) (string, error) {
tmpl := template.Must(template.New("golden").Parse(content))
var out bytes.Buffer
if err := tmpl.Execute(&out, templateValues); err != nil {
return "", err
}
return out.String(), nil
}
// Run the command and return the captured output.
func executeCommand(cmd string) (string, error) {
args, err := shellwords.Parse(cmd)
if err != nil {
return "", err
}
buf := new(bytes.Buffer)
rootCmd.SetOut(buf)
rootCmd.SetErr(buf)
rootCmd.SetArgs(args)
logger.stderr = rootCmd.ErrOrStderr()
_, err = rootCmd.ExecuteC()
result := buf.String()
return result, err
}

View File

@@ -1,34 +0,0 @@
// +build unit
package main
import (
"fmt"
"os"
"testing"
)
// The test environment is long running process shared between tests, initialized
// by a `TestMain` function depending on how the test is involved and which tests
// are a part of the build.
var testEnv *testEnvKubeManager
func TestMain(m *testing.M) {
// Ensure tests print consistent timestamps regardless of timezone
os.Setenv("TZ", "UTC")
// Creating the test env manager sets rootArgs client flags
km, err := NewTestEnvKubeManager(TestEnvClusterMode)
if err != nil {
panic(fmt.Errorf("error creating kube manager: '%w'", err))
}
testEnv = km
rootArgs.kubeconfig = testEnv.kubeConfigPath
// Run tests
code := m.Run()
km.Stop()
os.Exit(code)
}

View File

@@ -39,13 +39,6 @@ type adapter interface {
asClientObject() client.Object
}
// copyable is an interface for a wrapper or alias from which we can
// get a deep copied client.Object, required when you e.g. want to
// calculate a patch.
type copyable interface {
deepCopyClientObject() client.Object
}
// listAdapater is the analogue to adapter, but for lists; the
// controller runtime distinguishes between methods dealing with
// objects and lists.

View File

@@ -37,10 +37,6 @@ func (a receiverAdapter) asClientObject() client.Object {
return a.Receiver
}
func (a receiverAdapter) deepCopyClientObject() client.Object {
return a.Receiver.DeepCopy()
}
// notificationv1.Receiver
type receiverListAdapter struct {

View File

@@ -52,7 +52,6 @@ type reconcileCommand struct {
type reconcilable interface {
adapter // to be able to load from the cluster
copyable // to be able to calculate patches
suspendable // to tell if it's suspended
// these are implemented by anything embedding metav1.ObjectMeta
@@ -143,7 +142,6 @@ func requestReconciliation(ctx context.Context, kubeClient client.Client,
if err := kubeClient.Get(ctx, namespacedName, obj.asClientObject()); err != nil {
return err
}
patch := client.MergeFrom(obj.deepCopyClientObject())
if ann := obj.GetAnnotations(); ann == nil {
obj.SetAnnotations(map[string]string{
meta.ReconcileRequestAnnotation: time.Now().Format(time.RFC3339Nano),
@@ -152,7 +150,7 @@ func requestReconciliation(ctx context.Context, kubeClient client.Client,
ann[meta.ReconcileRequestAnnotation] = time.Now().Format(time.RFC3339Nano)
obj.SetAnnotations(ann)
}
return kubeClient.Patch(ctx, obj.asClientObject(), patch)
return kubeClient.Update(ctx, obj.asClientObject())
})
}

View File

@@ -21,7 +21,7 @@ import (
"github.com/spf13/cobra"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var reconcileImageRepositoryCmd = &cobra.Command{

View File

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

View File

@@ -19,7 +19,7 @@ package main
import (
"github.com/spf13/cobra"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var resumeImageRepositoryCmd = &cobra.Command{

View File

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

View File

@@ -41,10 +41,6 @@ func (a bucketAdapter) asClientObject() client.Object {
return a.Bucket
}
func (a bucketAdapter) deepCopyClientObject() client.Object {
return a.Bucket.DeepCopy()
}
// sourcev1.BucketList
type bucketListAdapter struct {
@@ -74,10 +70,6 @@ func (a helmChartAdapter) asClientObject() client.Object {
return a.HelmChart
}
func (a helmChartAdapter) deepCopyClientObject() client.Object {
return a.HelmChart.DeepCopy()
}
// sourcev1.HelmChartList
type helmChartListAdapter struct {
@@ -107,10 +99,6 @@ func (a gitRepositoryAdapter) asClientObject() client.Object {
return a.GitRepository
}
func (a gitRepositoryAdapter) deepCopyClientObject() client.Object {
return a.GitRepository.DeepCopy()
}
// sourcev1.GitRepositoryList
type gitRepositoryListAdapter struct {
@@ -140,10 +128,6 @@ func (a helmRepositoryAdapter) asClientObject() client.Object {
return a.HelmRepository
}
func (a helmRepositoryAdapter) deepCopyClientObject() client.Object {
return a.HelmRepository.DeepCopy()
}
// sourcev1.HelmRepositoryList
type helmRepositoryListAdapter struct {

View File

@@ -19,7 +19,7 @@ package main
import (
"github.com/spf13/cobra"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1beta1"
imagev1 "github.com/fluxcd/image-reflector-controller/api/v1alpha2"
)
var suspendImageRepositoryCmd = &cobra.Command{

View File

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

View File

@@ -1,4 +0,0 @@
► checking prerequisites
✔ kubectl {{ .clientVersion }} >=1.18.0-0
✔ Kubernetes {{ .serverVersion }} >=1.16.0-0
✔ prerequisites checks passed

View File

@@ -1,6 +0,0 @@
✚ generating HelmRelease
► applying HelmRelease
✔ HelmRelease created
◎ waiting for HelmRelease reconciliation
✔ HelmRelease thrfg is ready
✔ applied revision 6.0.0

View File

@@ -1,6 +0,0 @@
✚ generating GitRepository source
► applying GitRepository source
✔ GitRepository source created
◎ waiting for GitRepository source reconciliation
✔ GitRepository source reconciliation completed
✔ fetched revision: 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951

View File

@@ -1,2 +0,0 @@
► deleting helmreleases thrfg in {{ .ns }} namespace
✔ helmreleases deleted

View File

@@ -1,2 +0,0 @@
NAME READY MESSAGE REVISION SUSPENDED
thrfg True Release reconciliation succeeded 6.0.0 False

View File

@@ -1,10 +0,0 @@
► annotating GitRepository thrfg in {{ .ns }} namespace
✔ GitRepository annotated
◎ waiting for GitRepository reconciliation
✔ GitRepository reconciliation completed
✔ fetched revision 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951
► annotating HelmRelease thrfg in {{ .ns }} namespace
✔ HelmRelease annotated
◎ waiting for HelmRelease reconciliation
✔ HelmRelease reconciliation completed
✔ applied revision 6.0.0

View File

@@ -1,5 +0,0 @@
► resuming helmreleases thrfg in {{ .ns }} namespace
✔ helmreleases resumed
◎ waiting for HelmRelease reconciliation
✔ HelmRelease reconciliation completed
✔ applied revision 6.0.0

View File

@@ -1,2 +0,0 @@
► suspending helmreleases thrfg in {{ .ns }} namespace
✔ helmreleases suspended

View File

@@ -1,5 +0,0 @@
✚ generating ImagePolicy
► applying ImagePolicy
✔ ImageRepository created
◎ waiting for ImagePolicy reconciliation
✔ ImagePolicy reconciliation completed

View File

@@ -1,5 +0,0 @@
✚ generating ImageRepository
► applying ImageRepository
✔ ImageRepository created
◎ waiting for ImageRepository reconciliation
✔ ImageRepository reconciliation completed

View File

@@ -1,2 +0,0 @@
NAME READY MESSAGE LATEST IMAGE
podinfo-regex True Latest image tag for 'ghcr.io/stefanprodan/podinfo' resolved to: 5.0.0 ghcr.io/stefanprodan/podinfo:5.0.0

View File

@@ -1,2 +0,0 @@
NAME READY MESSAGE LATEST IMAGE
podinfo-semver True Latest image tag for 'ghcr.io/stefanprodan/podinfo' resolved to: 5.0.3 ghcr.io/stefanprodan/podinfo:5.0.3

View File

@@ -1,6 +0,0 @@
✚ generating Kustomization
► applying Kustomization
✔ Kustomization created
◎ waiting for Kustomization reconciliation
✔ Kustomization tkfg is ready
✔ applied revision 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951

View File

@@ -1,6 +0,0 @@
✚ generating GitRepository source
► applying GitRepository source
✔ GitRepository source created
◎ waiting for GitRepository source reconciliation
✔ GitRepository source reconciliation completed
✔ fetched revision: 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951

View File

@@ -1,2 +0,0 @@
► deleting kustomizations tkfg in {{ .ns }} namespace
✔ kustomizations deleted

View File

@@ -1,2 +0,0 @@
NAME READY MESSAGE REVISION SUSPENDED
tkfg True Applied revision: 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951 False

View File

@@ -1,10 +0,0 @@
► annotating GitRepository tkfg in {{ .ns }} namespace
✔ GitRepository annotated
◎ waiting for GitRepository reconciliation
✔ GitRepository reconciliation completed
✔ fetched revision 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951
► annotating Kustomization tkfg in {{ .ns }} namespace
✔ Kustomization annotated
◎ waiting for Kustomization reconciliation
✔ Kustomization reconciliation completed
✔ applied revision 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951

View File

@@ -1,5 +0,0 @@
► resuming kustomizations tkfg in {{ .ns }} namespace
✔ kustomizations resumed
◎ waiting for Kustomization reconciliation
✔ Kustomization reconciliation completed
✔ applied revision 6.0.0/627d5c4bb67b77185f37e31d734b085019ff2951

View File

@@ -1,2 +0,0 @@
► suspending kustomizations tkfg in {{ .ns }} namespace
✔ kustomizations suspended

View File

@@ -1,25 +0,0 @@
Object: deployment/podinfo
Namespace: {{ .ns }}
Status: Managed by Flux
---
HelmRelease: podinfo
Namespace: {{ .ns }}
Revision: 6.0.0
Status: Last reconciled at 2021-07-16 15:42:20 +0000 UTC
Message: Release reconciliation succeeded
---
HelmChart: podinfo-podinfo
Namespace: {{ .fluxns }}
Chart: podinfo
Version: 6.0.0
Revision: 6.0.0
Status: Last reconciled at 2021-07-16 15:32:09 +0000 UTC
Message: Fetched revision: 6.0.0
---
HelmRepository: podinfo
Namespace: {{ .fluxns }}
URL: https://stefanprodan.github.io/podinfo
Revision: 8411f23d07d3701f0e96e7d9e503b7936d7e1d56
Status: Last reconciled at 2021-07-11 00:25:46 +0000 UTC
Message: Fetched revision: 8411f23d07d3701f0e96e7d9e503b7936d7e1d56

View File

@@ -1,155 +0,0 @@
---
apiVersion: v1
kind: Namespace
metadata:
name: {{ .fluxns }}
---
apiVersion: v1
kind: Namespace
metadata:
name: {{ .ns }}
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/name: podinfo
app.kubernetes.io/managed-by: Helm
helm.toolkit.fluxcd.io/name: podinfo
helm.toolkit.fluxcd.io/namespace: {{ .ns }}
name: podinfo
namespace: {{ .ns }}
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: podinfo
template:
metadata:
labels:
app.kubernetes.io/name: podinfo
spec:
containers:
- name: hello
command: [ "echo hello world" ]
image: busybox
---
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
labels:
kustomize.toolkit.fluxcd.io/name: infrastructure
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
name: podinfo
namespace: {{ .ns }}
spec:
chart:
spec:
chart: podinfo
sourceRef:
kind: HelmRepository
name: podinfo
namespace: {{ .fluxns }}
interval: 5m
status:
conditions:
- lastTransitionTime: "2021-07-16T15:42:20Z"
message: Release reconciliation succeeded
reason: ReconciliationSucceeded
status: "True"
type: Ready
helmChart: {{ .fluxns }}/podinfo-podinfo
lastAppliedRevision: 6.0.0
lastAttemptedRevision: 6.0.0
lastAttemptedValuesChecksum: c31db75d05b7515eba2eef47bd71038c74b2e531
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmChart
metadata:
name: podinfo-podinfo
namespace: {{ .fluxns }}
spec:
chart: podinfo
sourceRef:
kind: HelmRepository
name: podinfo
version: 6.0.0
interval: 5m
status:
artifact:
checksum: cf13ba96773d9a879cd052c86e73199b3f96c854
lastUpdateTime: "2021-08-01T04:42:55Z"
revision: 6.0.0
path: "example"
url: "example"
conditions:
- lastTransitionTime: "2021-07-16T15:32:09Z"
message: 'Fetched revision: 6.0.0'
reason: ChartPullSucceeded
status: "True"
type: Ready
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: HelmRepository
metadata:
labels:
kustomize.toolkit.fluxcd.io/name: infrastructure
kustomize.toolkit.fluxcd.io/namespace: flux-system
name: podinfo
namespace: {{ .fluxns }}
spec:
interval: 5m
timeout: 1m0s
url: https://stefanprodan.github.io/podinfo
status:
artifact:
checksum: 8411f23d07d3701f0e96e7d9e503b7936d7e1d56
lastUpdateTime: "2021-07-11T00:25:46Z"
revision: 8411f23d07d3701f0e96e7d9e503b7936d7e1d56
path: "example"
url: "example"
conditions:
- lastTransitionTime: "2021-07-11T00:25:46Z"
message: 'Fetched revision: 8411f23d07d3701f0e96e7d9e503b7936d7e1d56'
reason: IndexationSucceed
status: "True"
type: Ready
---
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
name: infrastructure
namespace: {{ .fluxns }}
spec:
path: ./infrastructure/
sourceRef:
kind: GitRepository
name: flux-system
validation: client
interval: 5m
prune: true
status:
conditions:
- lastTransitionTime: "2021-08-01T04:52:56Z"
message: 'Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f'
reason: ReconciliationSucceeded
status: "True"
type: Ready
---
apiVersion: source.toolkit.fluxcd.io/v1beta1
kind: GitRepository
metadata:
labels:
kustomize.toolkit.fluxcd.io/name: flux-system
kustomize.toolkit.fluxcd.io/namespace: {{ .fluxns }}
name: flux-system
namespace: {{ .fluxns }}
spec:
gitImplementation: go-git
ref:
branch: main
secretRef:
name: flux-system
interval: 5m
url: ssh://git@github.com/example/repo

View File

@@ -1,19 +0,0 @@
Object: HelmRelease/podinfo
Namespace: {{ .ns }}
Status: Managed by Flux
---
Kustomization: infrastructure
Namespace: {{ .fluxns }}
Path: ./infrastructure
Revision: main/696f056df216eea4f9401adbee0ff744d4df390f
Status: Last reconciled at 2021-08-01 04:52:56 +0000 UTC
Message: Applied revision: main/696f056df216eea4f9401adbee0ff744d4df390f
---
GitRepository: flux-system
Namespace: {{ .fluxns }}
URL: ssh://git@github.com/example/repo
Branch: main
Revision: main/696f056df216eea4f9401adbee0ff744d4df390f
Status: Last reconciled at 2021-07-20 00:48:16 +0000 UTC
Message: Fetched revision: main/696f056df216eea4f9401adbee0ff744d4df390f

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