Merge branch 'main' into patch-1

pull/1091/head
Joe Bowbeer 4 years ago committed by GitHub
commit 02fb8d9958
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -34,12 +34,18 @@ jobs:
go build -o /tmp/flux ./cmd/flux
- name: Set outputs
id: vars
run: echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
run: |
REPOSITORY_NAME=${{ github.event.repository.name }}
BRANCH_NAME=${GITHUB_REF##*/}
COMMIT_SHA=$(git rev-parse HEAD)
PSEUDO_RAND_SUFFIX=$(echo "${BRANCH_NAME}-${COMMIT_SHA}" | shasum | awk '{print $1}')
TEST_REPO_NAME="${REPOSITORY_NAME}-${PSEUDO_RAND_SUFFIX}"
echo "::set-output name=test_repo_name::$TEST_REPO_NAME"
- name: bootstrap init
run: |
/tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--repository=${{ steps.vars.outputs.test_repo_name }} \
--branch=main \
--path=test-cluster
env:
@ -48,7 +54,7 @@ jobs:
run: |
/tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--repository=${{ steps.vars.outputs.test_repo_name }} \
--branch=main \
--path=test-cluster
env:
@ -61,19 +67,19 @@ jobs:
run: |
/tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--repository=${{ steps.vars.outputs.test_repo_name }} \
--branch=main \
--path=test-cluster
env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: delete repository
run: |
/tmp/flux bootstrap github --manifests ./manifests/install/ \
--owner=fluxcd-testing \
--repository=flux-test-${{ steps.vars.outputs.sha_short }} \
--branch=main \
--path=test-cluster \
--delete
curl \
-X DELETE \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: token ${GITHUB_TOKEN}" \
--fail --silent \
https://api.github.com/repos/fluxcd-testing/${{ steps.vars.outputs.test_repo_name }}
env:
GITHUB_TOKEN: ${{ secrets.GITPROVIDER_BOT_TOKEN }}
- name: Debug failure

@ -30,7 +30,7 @@ jobs:
# bump kustomize
sed -i "s/\($1\/releases\/download\/\)v.*\(\/.*\)/\1${RELEASE_VERSION}\2/g" "manifests/bases/$1/kustomization.yaml"
if [[ ! -z $(go list -m all | grep "github.com/fluxcd/$1/api" | awk '{print $2}') ]]; then
if [[ ! -z $(grep "github.com/fluxcd/$1/api" go.mod | awk '{print $2}') ]]; then
# bump go mod
go mod edit -require="github.com/fluxcd/$1/api@${RELEASE_VERSION}"
fi

@ -36,6 +36,7 @@ import (
"github.com/fluxcd/flux2/pkg/manifestgen/install"
kus "github.com/fluxcd/flux2/pkg/manifestgen/kustomization"
"github.com/fluxcd/flux2/pkg/manifestgen/sync"
"github.com/fluxcd/flux2/pkg/status"
)
var bootstrapCmd = &cobra.Command{
@ -176,19 +177,24 @@ func generateInstallManifests(targetPath, namespace, tmpDir string, localManifes
func applyInstallManifests(ctx context.Context, manifestPath string, components []string) error {
kubectlArgs := []string{"apply", "-f", manifestPath}
if _, err := utils.ExecKubectlCommand(ctx, utils.ModeOS, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed")
return fmt.Errorf("install failed: %w", err)
}
statusChecker, err := NewStatusChecker(time.Second, rootArgs.timeout)
kubeConfig, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return fmt.Errorf("install failed: %w", err)
}
statusChecker, err := status.NewStatusChecker(kubeConfig, time.Second, rootArgs.timeout, logger)
if err != nil {
return fmt.Errorf("install failed: %w", err)
}
componentRefs, err := buildComponentObjectRefs(components...)
if err != nil {
return fmt.Errorf("install failed: %w", err)
}
logger.Waitingf("verifying installation")
if err := statusChecker.Assess(components...); err != nil {
if err := statusChecker.Assess(componentRefs...); err != nil {
return fmt.Errorf("install failed")
}
return nil
}

@ -80,7 +80,6 @@ type githubFlags struct {
hostname string
path flags.SafeRelativePath
teams []string
delete bool
sshHostname string
}
@ -101,9 +100,6 @@ func init() {
bootstrapGitHubCmd.Flags().StringVar(&githubArgs.sshHostname, "ssh-hostname", "", "GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one")
bootstrapGitHubCmd.Flags().Var(&githubArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path")
bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.delete, "delete", false, "delete repository (used for testing only)")
bootstrapGitHubCmd.Flags().MarkHidden("delete")
bootstrapCmd.AddCommand(bootstrapGitHubCmd)
}
@ -163,14 +159,6 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
}
defer os.RemoveAll(tmpDir)
if githubArgs.delete {
if err := provider.DeleteRepository(ctx, repository); err != nil {
return err
}
logger.Successf("repository deleted")
return nil
}
// create GitHub repository if doesn't exists
logger.Actionf("connecting to %s", githubArgs.hostname)
changed, err := provider.CreateRepository(ctx, repository)
@ -260,7 +248,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("git URL parse failed: %w", err)
}
secretOpts.SSHHostname = u.Hostname()
secretOpts.SSHHostname = u.Host
secretOpts.PrivateKeyAlgorithm = sourcesecret.RSAPrivateKeyAlgorithm
secretOpts.RSAKeyBits = 2048
}

@ -235,7 +235,7 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("git URL parse failed: %w", err)
}
secretOpts.SSHHostname = u.Hostname()
secretOpts.SSHHostname = u.Host
secretOpts.PrivateKeyAlgorithm = sourcesecret.RSAPrivateKeyAlgorithm
secretOpts.RSAKeyBits = 2048
}

@ -34,6 +34,7 @@ import (
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/flux2/pkg/manifestgen/install"
"github.com/fluxcd/flux2/pkg/status"
)
var checkCmd = &cobra.Command{
@ -205,12 +206,17 @@ func componentsCheck() bool {
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout)
defer cancel()
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
kubeConfig, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return false
}
statusChecker, err := status.NewStatusChecker(kubeConfig, time.Second, rootArgs.timeout, logger)
if err != nil {
return false
}
statusChecker, err := NewStatusChecker(time.Second, rootArgs.timeout)
kubeClient, err := utils.KubeClient(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return false
}
@ -220,10 +226,10 @@ func componentsCheck() bool {
var list v1.DeploymentList
if err := kubeClient.List(ctx, &list, client.InNamespace(rootArgs.namespace), selector); err == nil {
for _, d := range list.Items {
if err := statusChecker.Assess(d.Name); err != nil {
ok = false
} else {
logger.Successf("%s: healthy", d.Name)
if ref, err := buildComponentObjectRefs(d.Name); err == nil {
if err := statusChecker.Assess(ref...); err != nil {
ok = false
}
}
for _, c := range d.Spec.Template.Spec.Containers {
logger.Actionf(c.Image)

@ -129,7 +129,7 @@ func createSecretGitCmdRun(cmd *cobra.Command, args []string) error {
}
switch u.Scheme {
case "ssh":
opts.SSHHostname = u.Hostname()
opts.SSHHostname = u.Host
opts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(secretGitArgs.keyAlgorithm)
opts.RSAKeyBits = int(secretGitArgs.rsaBits)
opts.ECDSACurve = secretGitArgs.ecdsaCurve.Curve

@ -215,7 +215,7 @@ func createSourceGitCmdRun(cmd *cobra.Command, args []string) error {
}
switch u.Scheme {
case "ssh":
secretOpts.SSHHostname = u.Hostname()
secretOpts.SSHHostname = u.Host
secretOpts.PrivateKeyAlgorithm = sourcesecret.PrivateKeyAlgorithm(sourceGitArgs.keyAlgorithm)
secretOpts.RSAKeyBits = int(sourceGitArgs.keyRSABits)
secretOpts.ECDSACurve = sourceGitArgs.keyECDSACurve.Curve

@ -30,6 +30,7 @@ import (
"github.com/fluxcd/flux2/internal/flags"
"github.com/fluxcd/flux2/internal/utils"
"github.com/fluxcd/flux2/pkg/manifestgen/install"
"github.com/fluxcd/flux2/pkg/status"
)
var installCmd = &cobra.Command{
@ -200,7 +201,7 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
applyOutput = utils.ModeOS
}
if _, err := utils.ExecKubectlCommand(ctx, applyOutput, rootArgs.kubeconfig, rootArgs.kubecontext, kubectlArgs...); err != nil {
return fmt.Errorf("install failed")
return fmt.Errorf("install failed: %w", err)
}
if installArgs.dryRun {
@ -208,13 +209,20 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
return nil
}
statusChecker, err := NewStatusChecker(time.Second, time.Minute)
kubeConfig, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return fmt.Errorf("install failed: %w", err)
}
statusChecker, err := status.NewStatusChecker(kubeConfig, time.Second, rootArgs.timeout, logger)
if err != nil {
return fmt.Errorf("install failed: %w", err)
}
componentRefs, err := buildComponentObjectRefs(components...)
if err != nil {
return fmt.Errorf("install failed: %w", err)
}
logger.Waitingf("verifying installation")
if err := statusChecker.Assess(components...); err != nil {
if err := statusChecker.Assess(componentRefs...); err != nil {
return fmt.Errorf("install failed")
}

@ -0,0 +1,262 @@
/*
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 (
"bufio"
"context"
"encoding/json"
"fmt"
"github.com/fluxcd/flux2/internal/flags"
"github.com/fluxcd/flux2/internal/utils"
"github.com/spf13/cobra"
"html/template"
"io"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"os"
"strings"
"sync"
)
var logsCmd = &cobra.Command{
Use: "logs",
Short: "Display formatted logs for toolkit components",
Long: "The logs command displays formatted logs from various toolkit components.",
Example: `# Get logs from toolkit components
flux logs
# Stream logs from toolkit components
flux logs --follow
# Get logs from toolkit components in a particular namespace
flux logs --flux-namespace my-namespace
# Get logs for a particular log level
flux logs --level=info
# Filter logs by kind, name, or namespace
flux logs --kind=kustomization --name podinfo --namespace default
`,
RunE: logsCmdRun,
}
type logsFlags struct {
logLevel flags.LogLevel
follow bool
tail int64
kind string
name string
fluxNamespace string
allNamespaces bool
}
var logsArgs = &logsFlags{
tail: -1,
}
func init() {
logsCmd.Flags().Var(&logsArgs.logLevel, "level", logsArgs.logLevel.Description())
logsCmd.Flags().StringVarP(&logsArgs.kind, "kind", "", logsArgs.kind, "displays errors of a particular toolkit kind e.g GitRepository")
logsCmd.Flags().StringVarP(&logsArgs.name, "name", "", logsArgs.name, "specifies the name of the object logs to be displayed")
logsCmd.Flags().BoolVarP(&logsArgs.follow, "follow", "f", logsArgs.follow, "Specifies if the logs should be streamed")
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")
rootCmd.AddCommand(logsCmd)
}
func logsCmdRun(cmd *cobra.Command, args []string) error {
fluxSelector := fmt.Sprintf("app.kubernetes.io/instance=%s", logsArgs.fluxNamespace)
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
}
clientset, err := kubernetes.NewForConfig(cfg)
if err != nil {
return err
}
if len(args) > 0 {
return fmt.Errorf("no argument required")
}
pods, err = getPods(ctx, clientset, fluxSelector)
if err != nil {
return err
}
logOpts := &corev1.PodLogOptions{
Follow: logsArgs.follow,
}
if logsArgs.tail > -1 {
logOpts.TailLines = &logsArgs.tail
}
var requests []rest.ResponseWrapper
for _, pod := range pods {
req := clientset.CoreV1().Pods(logsArgs.fluxNamespace).GetLogs(pod.Name, logOpts)
requests = append(requests, req)
}
if logsArgs.follow && len(requests) > 1 {
return parallelPodLogs(ctx, requests)
}
return podLogs(ctx, requests)
}
func getPods(ctx context.Context, c *kubernetes.Clientset, label string) ([]corev1.Pod, error) {
var ret []corev1.Pod
opts := metav1.ListOptions{
LabelSelector: label,
}
deployList, err := c.AppsV1().Deployments(logsArgs.fluxNamespace).List(ctx, opts)
if err != nil {
return ret, err
}
for _, deploy := range deployList.Items {
label := deploy.Spec.Template.Labels
opts := metav1.ListOptions{
LabelSelector: createLabelStringFromMap(label),
}
podList, err := c.CoreV1().Pods(logsArgs.fluxNamespace).List(ctx, opts)
if err != nil {
return ret, err
}
ret = append(ret, podList.Items...)
}
return ret, nil
}
func parallelPodLogs(ctx context.Context, requests []rest.ResponseWrapper) error {
reader, writer := io.Pipe()
wg := &sync.WaitGroup{}
wg.Add(len(requests))
var mutex = &sync.Mutex{}
for _, request := range requests {
go func(req rest.ResponseWrapper) {
defer wg.Done()
if err := logRequest(mutex, ctx, req, os.Stdout); err != nil {
writer.CloseWithError(err)
return
}
}(request)
}
go func() {
wg.Wait()
writer.Close()
}()
_, err := io.Copy(os.Stdout, reader)
return err
}
func podLogs(ctx context.Context, requests []rest.ResponseWrapper) error {
mutex := &sync.Mutex{}
for _, req := range requests {
if err := logRequest(mutex, ctx, req, os.Stdout); err != nil {
return err
}
}
return nil
}
func createLabelStringFromMap(m map[string]string) string {
var strArr []string
for key, val := range m {
pair := fmt.Sprintf("%v=%v", key, val)
strArr = append(strArr, pair)
}
return strings.Join(strArr, ",")
}
func logRequest(mu *sync.Mutex, ctx context.Context, request rest.ResponseWrapper, w io.Writer) error {
stream, err := request.Stream(ctx)
if err != nil {
return err
}
defer stream.Close()
scanner := bufio.NewScanner(stream)
const logTmpl = "{{.Timestamp}} {{.Level}} {{.Kind}}{{if .Name}}/{{.Name}}.{{.Namespace}}{{end}} - {{.Message}} {{.Error}}\n"
t, err := template.New("log").Parse(logTmpl)
if err != nil {
return fmt.Errorf("unable to create template, err: %s", err)
}
for scanner.Scan() {
line := scanner.Text()
if !strings.HasPrefix(line, "{") {
continue
}
var l ControllerLogEntry
if err := json.Unmarshal([]byte(line), &l); err != nil {
logger.Failuref("parse error: %s", err)
break
}
mu.Lock()
filterPrintLog(t, &l)
mu.Unlock()
}
return nil
}
func filterPrintLog(t *template.Template, l *ControllerLogEntry) {
if logsArgs.logLevel != "" && logsArgs.logLevel != l.Level ||
logsArgs.kind != "" && strings.ToLower(logsArgs.kind) != strings.ToLower(l.Kind) ||
logsArgs.name != "" && strings.ToLower(logsArgs.name) != strings.ToLower(l.Name) ||
!logsArgs.allNamespaces && strings.ToLower(rootArgs.namespace) != strings.ToLower(l.Namespace) {
return
}
err := t.Execute(os.Stdout, l)
if err != nil {
logger.Failuref("log template error: %s", err)
}
}
type ControllerLogEntry struct {
Timestamp string `json:"ts"`
Level flags.LogLevel `json:"level"`
Message string `json:"msg"`
Error string `json:"error,omitempty"`
Logger string `json:"logger"`
Kind string `json:"reconciler kind,omitempty"`
Name string `json:"name,omitempty"`
Namespace string `json:"namespace,omitempty"`
}

@ -19,26 +19,16 @@ package main
import (
"context"
"fmt"
"time"
appsv1 "k8s.io/api/apps/v1"
apimeta "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/aggregator"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/collector"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/event"
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
"sigs.k8s.io/cli-utils/pkg/object"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/flux2/internal/utils"
)
// statusable is used to see if a resource is considered ready in the usual way
@ -51,13 +41,6 @@ type statusable interface {
GetStatusConditions() *[]metav1.Condition
}
type StatusChecker struct {
pollInterval time.Duration
timeout time.Duration
client client.Client
statusPoller *polling.StatusPoller
}
func isReady(ctx context.Context, kubeClient client.Client,
namespacedName types.NamespacedName, object statusable) wait.ConditionFunc {
return func() (bool, error) {
@ -83,74 +66,7 @@ func isReady(ctx context.Context, kubeClient client.Client,
}
}
func NewStatusChecker(pollInterval time.Duration, timeout time.Duration) (*StatusChecker, error) {
kubeConfig, err := utils.KubeConfig(rootArgs.kubeconfig, rootArgs.kubecontext)
if err != nil {
return nil, err
}
restMapper, err := apiutil.NewDynamicRESTMapper(kubeConfig)
if err != nil {
return nil, err
}
client, err := client.New(kubeConfig, client.Options{Mapper: restMapper})
if err != nil {
return nil, err
}
return &StatusChecker{
pollInterval: pollInterval,
timeout: timeout,
client: client,
statusPoller: polling.NewStatusPoller(client, restMapper),
}, nil
}
func (sc *StatusChecker) Assess(components ...string) error {
ctx, cancel := context.WithTimeout(context.Background(), sc.timeout)
defer cancel()
objRefs, err := sc.getObjectRefs(components)
if err != nil {
return err
}
opts := polling.Options{PollInterval: sc.pollInterval, UseCache: true}
eventsChan := sc.statusPoller.Poll(ctx, objRefs, opts)
coll := collector.NewResourceStatusCollector(objRefs)
done := coll.ListenWithObserver(eventsChan, collector.ObserverFunc(
func(statusCollector *collector.ResourceStatusCollector, e event.Event) {
var rss []*event.ResourceStatus
for _, rs := range statusCollector.ResourceStatuses {
rss = append(rss, rs)
}
desired := status.CurrentStatus
aggStatus := aggregator.AggregateStatus(rss, desired)
if aggStatus == desired {
cancel()
return
}
}),
)
<-done
if coll.Error != nil || ctx.Err() == context.DeadlineExceeded {
for _, rs := range coll.ResourceStatuses {
if rs.Status != status.CurrentStatus {
if !sc.deploymentExists(rs.Identifier) {
logger.Failuref("%s: deployment not found", rs.Identifier.Name)
} else {
logger.Failuref("%s: unhealthy (timed out waiting for rollout)", rs.Identifier.Name)
}
}
}
return fmt.Errorf("timed out waiting for condition")
}
return nil
}
func (sc *StatusChecker) getObjectRefs(components []string) ([]object.ObjMetadata, error) {
func buildComponentObjectRefs(components ...string) ([]object.ObjMetadata, error) {
var objRefs []object.ObjMetadata
for _, deployment := range components {
objMeta, err := object.CreateObjMetadata(rootArgs.namespace, deployment, schema.GroupKind{Group: "apps", Kind: "Deployment"})
@ -161,20 +77,3 @@ func (sc *StatusChecker) getObjectRefs(components []string) ([]object.ObjMetadat
}
return objRefs, nil
}
func (sc *StatusChecker) objMetadataToString(om object.ObjMetadata) string {
return fmt.Sprintf("%s '%s/%s'", om.GroupKind.Kind, om.Namespace, om.Name)
}
func (sc *StatusChecker) deploymentExists(om object.ObjMetadata) bool {
ctx, cancel := context.WithTimeout(context.Background(), sc.timeout)
defer cancel()
namespacedName := types.NamespacedName{
Namespace: om.Namespace,
Name: om.Name,
}
var existing appsv1.Deployment
err := sc.client.Get(ctx, namespacedName, &existing)
return err == nil
}

@ -94,4 +94,29 @@ body {
.progress-0plus .progress-bar {
background-color: #ff1744;
}
}
/* Custom admonitions */
/* See https://squidfunk.github.io/mkdocs-material/reference/admonitions */
:root {
--md-admonition-icon--heart: url('data:image/svg+xml;charset=utf-8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M14 20.408c-.492.308-.903.546-1.192.709-.153.086-.308.17-.463.252h-.002a.75.75 0 0 1-.686 0 16.709 16.709 0 0 1-.465-.252 31.147 31.147 0 0 1-4.803-3.34C3.8 15.572 1 12.331 1 8.513 1 5.052 3.829 2.5 6.736 2.5 9.03 2.5 10.881 3.726 12 5.605 13.12 3.726 14.97 2.5 17.264 2.5 20.17 2.5 23 5.052 23 8.514c0 3.818-2.801 7.06-5.389 9.262A31.146 31.146 0 0 1 14 20.408z"/></svg>')
}
.md-typeset .admonition.heart,
.md-typeset details.heart {
border-color: rgb(233, 30, 99);
}
.md-typeset .heart > .admonition-title,
.md-typeset .heart > summary {
background-color: rgba(233, 30, 99, 0.1);
}
.md-typeset .heart > .admonition-title::before,
.md-typeset .heart > summary::before {
background-color: rgb(233, 30, 99);
-webkit-mask-image: var(--md-admonition-icon--heart);
mask-image: var(--md-admonition-icon--heart);
}
.timetable-explicit-col-widths th:nth-child(1) { width: 4%; }
.timetable-explicit-col-widths th:nth-child(2) { width: 32%; }
.timetable-explicit-col-widths th:nth-child(3) { width: 32%; }
.timetable-explicit-col-widths th:nth-child(4) { width: 32%; }

@ -85,6 +85,7 @@ Command line utility for assembling Kubernetes CD pipelines the GitOps way.
* [flux export](flux_export.md) - Export resources in YAML format
* [flux get](flux_get.md) - Get sources and resources
* [flux install](flux_install.md) - Install or upgrade Flux
* [flux logs](flux_logs.md) - Display formatted logs for toolkit components
* [flux reconcile](flux_reconcile.md) - Reconcile sources and resources
* [flux resume](flux_resume.md) - Resume suspended resources
* [flux suspend](flux_suspend.md) - Suspend resources

@ -0,0 +1,59 @@
## flux logs
Display formatted logs for toolkit components
### Synopsis
The logs command displays formatted logs from various toolkit components.
```
flux logs [flags]
```
### Examples
```
# Get logs from toolkit components
flux logs
# Stream logs from toolkit components
flux logs --follow
# Get logs from toolkit components in a particular namespace
flux logs --flux-namespace my-namespace
# Get logs for a particular log level
flux logs --level=info
# Filter logs by kind, name, or namespace
flux logs --kind=kustomization --name podinfo --namespace default
```
### Options
```
-A, --all-namespaces displays logs for objects across all namespaces
--flux-namespace string the namespace where the Flux components are running. (default "flux-system")
-f, --follow Specifies if the logs should be streamed
-h, --help help for logs
--kind string displays errors of a particular toolkit kind e.g GitRepository
--level logLevel log level, available options are: (debug, info, error)
--name string specifies the name of the object logs to be displayed
--tail int lines of recent log file to display (default -1)
```
### Options inherited from parent commands
```
--context string kubernetes context to use
--kubeconfig string path to the kubeconfig file (default "~/.kube/config")
-n, --namespace string the namespace scope for this operation (default "flux-system")
--timeout duration timeout for this operation (default 5m0s)
--verbose print generated objects
```
### SEE ALSO
* [flux](flux.md) - Command line utility for assembling Kubernetes CD pipelines

@ -431,8 +431,8 @@ spec:
```
!!! hint
If you are using the same image repository in several manifests, you only need one
`ImageRepository` object for it.
If you are using the same image repository in several manifests, you only need one
`ImageRepository` object for it.
##### Using image registry credentials for scanning

@ -0,0 +1,38 @@
---
hide:
# The table data on this page is easier to read when wider
# The TOC right column is already blank anyway
- toc
---
# Migration and Support Timetable
!!! heart "Flux Migration Commitment"
This public timetable clarifies our commitment to end users.
Its purpose is to help improve your experience in deciding how and when to plan infra decisions related to Flux versions.
Please refer to the [Roadmap](../roadmap/index.md) for additional details.
<!-- Note: this div allows us to set fixed column widths in custom.css -->
<!-- See: https://github.com/squidfunk/mkdocs-material/issues/118 -->
<div markdown="1" class="timetable-explicit-col-widths">
<!-- Requires mkdocs markdown_extensions footnotes and pymdownx.caret -->
<!-- markdownlint-disable-file MD033 -->
| Date | Flux 1 | Flux 2 CLI | GOTK[^1] |
| -- | -- | -- | -- |
| Oct 6, 2020 | ^^[Maintenance Mode](https://github.com/fluxcd/website/pull/25)^^<br><ul><li>Flux 1 releases only include critical bug fixes (which dont require changing Flux 1 architecture), and security patches (for OS packages, Go runtime, and kubectl). No new features</li><li>Existing projects encouraged to test migration to Flux 2 pre-releases in non-production</li></ul> | ^^Development Mode^^<br><ul><li>Working to finish parity with Flux 1</li><li>New projects encouraged to test Flux 2 pre-releases in non-production</li></ul> | ^^All Alpha^^[^2] |
Feb 18, 2021 | ^^Partial Migration Mode^^<br><ul><li>Existing projects encouraged to migrate to `v1beta1`/`v2beta1` if you only use those features (Flux 1 read-only mode, and Helm Operator)</li><li>Existing projects encouraged to test image automation Alpha in non-production</li></ul> | ^^Feature Parity^^ | ^^Image Automation Alpha. All others reached Feature Parity, Beta^^ |
| TBD | ^^Superseded^^<br><ul><li>All existing projects encouraged to [migrate to Flux 2](https://toolkit.fluxcd.io/guides/flux-v1-migration/), and [report any bugs](https://github.com/fluxcd/flux2/issues/new/choose)</li><li>Flux 1 Helm Operator archived no further updates due to unsupported dependencies</li></ul> | ^^Needs further testing, may get breaking changes^^<br><ul><li>CLI needs further user testing during this migration period</li></ul> | ^^All Beta, Production Ready^^[^3]<br><ul><li>All Flux 1 features stable and supported in Flux 2</li><li>Promoting Alpha versions to Beta makes this Production Ready</li></ul> |
| TBD | ^^Migration and security support only^^<br><ul><li>Flux 1 releases only include security patches (no bug fixes)</li><li>Maintainers support users with migration to Flux 2 only, no longer with Flux 1 issues</li><li>Flux 1 archive date announced</li></ul> | ^^Public release (GA), Production Ready^^<br><ul><li>CLI commits to backwards compatibility moving forward</li><li>CLI follows kubectl style backwards compatibility support: +1 -1 MINOR version for server components (e.g., APIs, Controllers, validation webhooks)</li></ul> | ^^All Beta, Production Ready^^ |
| TBD | ^^Archived^^<br><ul><li>Flux 1 obsolete, no further releases or maintainer support</li><li>Flux 1 repo archived</li></ul> | ^^Continued active development^^ | ^^Continued active development^^ |
<!-- end .timetable-explicit-col-widths -->
</div>
[^1]: GOTK is shorthand for the [GitOps Toolkit](https://toolkit.fluxcd.io/components/) APIs and Controllers
[^2]: Versioning: Flux 2 is a multi-service architecture, so requires a more complex explanation than Flux 1:
- Flux 2 CLI follows [Semantic Versioning](https://semver.org/) scheme
- The GitOps Toolkit APIs follow the [Kubernetes API versioning](https://kubernetes.io/docs/reference/using-api/#api-versioning) pattern. See [Roadmap](https://toolkit.fluxcd.io/roadmap/) for component versions.
- These are coordinated for cross-compatibility: For each Flux 2 CLI tag, CLI and GOTK versions are end-to-end tested together, so you may safely upgrade from one MINOR/PATCH version to another.
[^3]: The GOTK Custom Resource Definitions which are at `v1beta1` and `v2beta1` and their controllers are considered stable and production ready. Going forward, breaking changes to the beta CRDs will be accompanied by a conversion mechanism.

@ -4,6 +4,7 @@
The Flux custom resource definitions which are at `v1beta1` and `v2beta1`
and their controllers are considered stable and production ready.
Going forward, breaking changes to the beta CRDs will be accompanied by a conversion mechanism.
Please see the [Migration and Suport Timetable](../migration/timetable.md) for our commitment to end users.
The following components (included by default in [flux bootstrap](../guides/installation.md#bootstrap))
are considered production ready:

@ -5,18 +5,18 @@ go 1.16
require (
github.com/Masterminds/semver/v3 v3.1.0
github.com/cyphar/filepath-securejoin v0.2.2
github.com/fluxcd/helm-controller/api v0.8.1
github.com/fluxcd/image-automation-controller/api v0.6.1
github.com/fluxcd/image-reflector-controller/api v0.7.0
github.com/fluxcd/kustomize-controller/api v0.9.1
github.com/fluxcd/notification-controller/api v0.9.0
github.com/fluxcd/helm-controller/api v0.8.2
github.com/fluxcd/image-automation-controller/api v0.7.0
github.com/fluxcd/image-reflector-controller/api v0.7.1
github.com/fluxcd/kustomize-controller/api v0.9.3
github.com/fluxcd/notification-controller/api v0.10.0
github.com/fluxcd/pkg/apis/meta v0.8.0
github.com/fluxcd/pkg/git v0.3.0
github.com/fluxcd/pkg/runtime v0.8.3
github.com/fluxcd/pkg/runtime v0.8.5
github.com/fluxcd/pkg/ssh v0.0.5
github.com/fluxcd/pkg/untar v0.0.5
github.com/fluxcd/pkg/version v0.0.1
github.com/fluxcd/source-controller/api v0.9.0
github.com/fluxcd/source-controller/api v0.9.1
github.com/google/go-containerregistry v0.2.0
github.com/manifoldco/promptui v0.7.0
github.com/olekukonko/tablewriter v0.0.4
@ -29,7 +29,7 @@ require (
k8s.io/cli-runtime v0.20.2 // indirect
k8s.io/client-go v0.20.2
sigs.k8s.io/cli-utils v0.22.2
sigs.k8s.io/controller-runtime v0.8.2
sigs.k8s.io/controller-runtime v0.8.3
sigs.k8s.io/kustomize/api v0.7.4
sigs.k8s.io/yaml v1.2.0
)

@ -188,33 +188,33 @@ github.com/evanphx/json-patch/v5 v5.1.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fluxcd/helm-controller/api v0.8.1 h1:AEmw/xaRi2y9lD6TB+2w1Govj7OhD5oxoDx6HGty1yM=
github.com/fluxcd/helm-controller/api v0.8.1/go.mod h1:cFceNc/mOBa+Qi3NE8NDY2w3FAEectauTm8c10mcBis=
github.com/fluxcd/image-automation-controller/api v0.6.1 h1:LgjjNYXrVojfgjit37GA0SDYre3AaDabYzT7L6lWO7I=
github.com/fluxcd/image-automation-controller/api v0.6.1/go.mod h1:8Q/baOONPrSJFMq7+zxp/t2WGrqVFRUx4HnTrg37pNE=
github.com/fluxcd/image-reflector-controller/api v0.7.0 h1:Mlu9ybrL+MtWcaIex4+FOcYuk+0vA/7bYj8MxVvLR1A=
github.com/fluxcd/image-reflector-controller/api v0.7.0/go.mod h1:KHWknF2xu/GZ4uLSQcAmfONZYjsbwNqyk3OvMQTmMsA=
github.com/fluxcd/kustomize-controller/api v0.9.1 h1:o6cxtLiXUdEeTJMxoeoLdld7hsgf7L4mNO6+i2MD2U8=
github.com/fluxcd/kustomize-controller/api v0.9.1/go.mod h1:VhUwaSsgrXVgO8Qcx6ZO0isqb5TpDgbyyitCeXYqSM4=
github.com/fluxcd/notification-controller/api v0.9.0 h1:aEIZu01EHlDH7I8/TyOkvMknlDV8NBNhuZ9cMQ8Kp0Q=
github.com/fluxcd/notification-controller/api v0.9.0/go.mod h1:nJqSGiecNkJLxuO2KWMu5YUTLaYT/A57854FMm4oX9Q=
github.com/fluxcd/helm-controller/api v0.8.2 h1:ELSC6dal01jtzn8B6ffArNklbul9/k9lpEd6msefVAE=
github.com/fluxcd/helm-controller/api v0.8.2/go.mod h1:WDVuo3g6n3eZy8l5U/Zqo0aL+LcFV1C/HoNAUzWLtzU=
github.com/fluxcd/image-automation-controller/api v0.7.0 h1:mLaELYT52/FpZ93Mr+QMSK8UT0OBVQT4oA9kxO8NiEk=
github.com/fluxcd/image-automation-controller/api v0.7.0/go.mod h1:7E2dCvoxmTkDttp+Hk8v9eoSK/CdFmFhRKInEXC3yVY=
github.com/fluxcd/image-reflector-controller/api v0.7.1 h1:Cng36D1J25WYZ0ZB6dwzDtGR9MIyIcSUMYxHpb0IYXA=
github.com/fluxcd/image-reflector-controller/api v0.7.1/go.mod h1:J18L71jiHYrAu2dg0tgOkOjP+GtQldC1oslhTeX0jqc=
github.com/fluxcd/kustomize-controller/api v0.9.3 h1:VbeU97pmx3vmgverqZIRyyBm1IKyPBZZAIo7mc3fZ+8=
github.com/fluxcd/kustomize-controller/api v0.9.3/go.mod h1:MDTwohIXqbId3qbhVNF7lAYLSBMzxq5MHINFN4bqDRs=
github.com/fluxcd/notification-controller/api v0.10.0 h1:7mxeBPnFzpL4Z+X5YiytQRzaDKrryb6TIQkC9ASJO28=
github.com/fluxcd/notification-controller/api v0.10.0/go.mod h1:CA02ixmq+kFN9eBkruvJClkMqffgRjYBMxym3AfhO6c=
github.com/fluxcd/pkg/apis/kustomize v0.0.1 h1:TkA80R0GopRY27VJqzKyS6ifiKIAfwBd7OHXtV3t2CI=
github.com/fluxcd/pkg/apis/kustomize v0.0.1/go.mod h1:JAFPfnRmcrAoG1gNiA8kmEXsnOBuDyZ/F5X4DAQcVV0=
github.com/fluxcd/pkg/apis/meta v0.7.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po=
github.com/fluxcd/pkg/apis/meta v0.8.0 h1:wqWpUsxhKHB1ZztcvOz+vnyhdKW9cWmjFp8Vci/XOdk=
github.com/fluxcd/pkg/apis/meta v0.8.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po=
github.com/fluxcd/pkg/git v0.3.0 h1:nrKZWZ/ymDevud3Wf1LEieO/QcNPnqz1/MrkZBFcg9o=
github.com/fluxcd/pkg/git v0.3.0/go.mod h1:ZwG0iLOqNSyNw6lsPIAO+v6+BqqCXyV+r1Oq6Lm+slg=
github.com/fluxcd/pkg/runtime v0.8.3 h1:Zjk4fyAfBdBQ4GTokjisab7KyHHczCqKSpJi8+oVrNw=
github.com/fluxcd/pkg/runtime v0.8.3/go.mod h1:AM/hMD0mKtRqhKPU7NGDzm+3UXPpdnX8oBlcxLt11AY=
github.com/fluxcd/pkg/runtime v0.8.4/go.mod h1:JD0eZIn5xkTeHHQUWXSqJPIh/ecO0d0qrUKbSVHnpnw=
github.com/fluxcd/pkg/runtime v0.8.5 h1:ynh8fszbLQ3QSisQBNOABEUTnvt+/QfCdaL6gOJQcoQ=
github.com/fluxcd/pkg/runtime v0.8.5/go.mod h1:JD0eZIn5xkTeHHQUWXSqJPIh/ecO0d0qrUKbSVHnpnw=
github.com/fluxcd/pkg/ssh v0.0.5 h1:rnbFZ7voy2JBlUfMbfyqArX2FYaLNpDhccGFC3qW83A=
github.com/fluxcd/pkg/ssh v0.0.5/go.mod h1:7jXPdXZpc0ttMNz2kD9QuMi3RNn/e0DOFbj0Tij/+Hs=
github.com/fluxcd/pkg/untar v0.0.5 h1:UGI3Ch1UIEIaqQvMicmImL1s9npQa64DJ/ozqHKB7gk=
github.com/fluxcd/pkg/untar v0.0.5/go.mod h1:O6V9+rtl8c1mHBafgqFlJN6zkF1HS5SSYn7RpQJ/nfw=
github.com/fluxcd/pkg/version v0.0.1 h1:/8asQoDXSThz3csiwi4Qo8Zb6blAxLXbtxNgeMJ9bCg=
github.com/fluxcd/pkg/version v0.0.1/go.mod h1:WAF4FEEA9xyhngF8TDxg3UPu5fA1qhEYV8Pmi2Il01Q=
github.com/fluxcd/source-controller/api v0.9.0 h1:ohV8AvmvkUK0N7+YKPIOlMSLaNG0SpFcNLtlmW18xuM=
github.com/fluxcd/source-controller/api v0.9.0/go.mod h1:68+cPuz1G45f0SDRwEfTL419011ffveLIDA9nssLlkU=
github.com/fluxcd/source-controller/api v0.9.1 h1:kaL+tBflccsuj3NDESPPQyKXlZXlAgyNoT2nYY02JAE=
github.com/fluxcd/source-controller/api v0.9.1/go.mod h1:Vuw+7UqEUUOdkKBfTUPHwaQgbn6LL2FwqPDx2UAk7NE=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
@ -1205,8 +1205,8 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyz
sigs.k8s.io/cli-utils v0.22.2 h1:xPD02b++uK990/dAg/rM0LKDOb2sTWZPI1v8IZPfCn0=
sigs.k8s.io/cli-utils v0.22.2/go.mod h1:unl8itcwGPqo41QSyksbXTWFbfMqap1o/4oiUxPnQfw=
sigs.k8s.io/controller-runtime v0.6.0/go.mod h1:CpYf5pdNY/B352A1TFLAS2JVSlnGQ5O2cftPHndTroo=
sigs.k8s.io/controller-runtime v0.8.2 h1:SBWmI0b3uzMIUD/BIXWNegrCeZmPJ503pOtwxY0LPHM=
sigs.k8s.io/controller-runtime v0.8.2/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU=
sigs.k8s.io/controller-runtime v0.8.3 h1:GMHvzjTmaWHQB8HadW+dIvBoJuLvZObYJ5YoZruPRao=
sigs.k8s.io/controller-runtime v0.8.3/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU=
sigs.k8s.io/kind v0.9.0/go.mod h1:cxKQWwmbtRDzQ+RNKnR6gZG6fjbeTtItp5cGf+ww+1Y=
sigs.k8s.io/kustomize v2.0.3+incompatible h1:JUufWFNlI44MdtnjUqVnvh29rR37PQFzPbLXqhyOyX0=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/helm-controller/releases/download/v0.8.1/helm-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v0.8.1/helm-controller.deployment.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v0.8.2/helm-controller.crds.yaml
- https://github.com/fluxcd/helm-controller/releases/download/v0.8.2/helm-controller.deployment.yaml
- account.yaml
patchesJson6902:
- target:

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.6.1/image-automation-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.6.1/image-automation-controller.deployment.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.7.0/image-automation-controller.crds.yaml
- https://github.com/fluxcd/image-automation-controller/releases/download/v0.7.0/image-automation-controller.deployment.yaml
- account.yaml
patchesJson6902:
- target:

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.7.0/image-reflector-controller.crds.yaml
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.7.0/image-reflector-controller.deployment.yaml
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.7.1/image-reflector-controller.crds.yaml
- https://github.com/fluxcd/image-reflector-controller/releases/download/v0.7.1/image-reflector-controller.deployment.yaml
- account.yaml
patchesJson6902:
- target:

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.9.2/kustomize-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.9.2/kustomize-controller.deployment.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.9.3/kustomize-controller.crds.yaml
- https://github.com/fluxcd/kustomize-controller/releases/download/v0.9.3/kustomize-controller.deployment.yaml
- account.yaml
patchesJson6902:
- target:

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/notification-controller/releases/download/v0.9.0/notification-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v0.9.0/notification-controller.deployment.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v0.10.0/notification-controller.crds.yaml
- https://github.com/fluxcd/notification-controller/releases/download/v0.10.0/notification-controller.deployment.yaml
- account.yaml
patchesJson6902:
- target:

@ -1,8 +1,8 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- https://github.com/fluxcd/source-controller/releases/download/v0.9.0/source-controller.crds.yaml
- https://github.com/fluxcd/source-controller/releases/download/v0.9.0/source-controller.deployment.yaml
- https://github.com/fluxcd/source-controller/releases/download/v0.9.1/source-controller.crds.yaml
- https://github.com/fluxcd/source-controller/releases/download/v0.9.1/source-controller.deployment.yaml
- account.yaml
patchesJson6902:
- target:

@ -26,31 +26,34 @@ plugins:
markdown_extensions:
- admonition
- meta
- codehilite:
guess_lang: false
- toc:
permalink: true
- footnotes
- meta
- pymdownx.caret
- pymdownx.emoji:
emoji_generator: !!python/name:materialx.emoji.to_svg
emoji_index: !!python/name:materialx.emoji.twemoji
- pymdownx.extra
- pymdownx.progressbar
- pymdownx.superfences:
highlight_code: true
- pymdownx.tabbed
- pymdownx.tilde
- pymdownx.progressbar
- pymdownx.tasklist
- pymdownx.superfences
- pymdownx.emoji:
emoji_index: !!python/name:materialx.emoji.twemoji
emoji_generator: !!python/name:materialx.emoji.to_svg
- pymdownx.tilde
- toc:
permalink: true
nav:
- Introduction: index.md
- Core Concepts: core-concepts/index.md
- Get Started: get-started/index.md
- Migration:
- Migrate from Flux v1: guides/flux-v1-migration.md
- Migrate from Flux v1 image update automation: guides/flux-v1-automation-migration.md
- Migrate from the Helm Operator: guides/helm-operator-migration.md
- FAQ: guides/faq-migration.md
- Migration and Support Timetable: migration/timetable.md
- Migrate from Flux v1: guides/flux-v1-migration.md
- Migrate from Flux v1 image update automation: guides/flux-v1-automation-migration.md
- Migrate from the Helm Operator: guides/helm-operator-migration.md
- FAQ: guides/faq-migration.md
- Guides:
- Installation: guides/installation.md
- Manage Helm Releases: guides/helmreleases.md
@ -158,6 +161,7 @@ nav:
- Get images repository: cmd/flux_get_images_repository.md
- Get images update: cmd/flux_get_images_update.md
- Install: cmd/flux_install.md
- Logs: cmd/flux_logs.md
- Resume: cmd/flux_resume.md
- Resume kustomization: cmd/flux_resume_kustomization.md
- Resume helmrelease: cmd/flux_resume_helmrelease.md

@ -22,7 +22,7 @@ type Logger interface {
Generatef(format string, a ...interface{})
// Waitingf logs a formatted waiting message.
Waitingf(format string, a ...interface{})
// Waitingf logs a formatted success message.
// Successf logs a formatted success message.
Successf(format string, a ...interface{})
// Failuref logs a formatted failure message.
Failuref(format string, a ...interface{})

@ -0,0 +1,109 @@
/*
Copyright 2020, 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 status
import (
"context"
"fmt"
"strings"
"time"
"k8s.io/client-go/rest"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/aggregator"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/collector"
"sigs.k8s.io/cli-utils/pkg/kstatus/polling/event"
"sigs.k8s.io/cli-utils/pkg/kstatus/status"
"sigs.k8s.io/cli-utils/pkg/object"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
"github.com/fluxcd/flux2/pkg/log"
)
type StatusChecker struct {
pollInterval time.Duration
timeout time.Duration
client client.Client
statusPoller *polling.StatusPoller
logger log.Logger
}
func NewStatusChecker(kubeConfig *rest.Config, pollInterval time.Duration, timeout time.Duration, log log.Logger) (*StatusChecker, error) {
restMapper, err := apiutil.NewDynamicRESTMapper(kubeConfig)
if err != nil {
return nil, err
}
c, err := client.New(kubeConfig, client.Options{Mapper: restMapper})
if err != nil {
return nil, err
}
return &StatusChecker{
pollInterval: pollInterval,
timeout: timeout,
client: c,
statusPoller: polling.NewStatusPoller(c, restMapper),
logger: log,
}, nil
}
func (sc *StatusChecker) Assess(identifiers ...object.ObjMetadata) error {
ctx, cancel := context.WithTimeout(context.Background(), sc.timeout)
defer cancel()
opts := polling.Options{PollInterval: sc.pollInterval, UseCache: true}
eventsChan := sc.statusPoller.Poll(ctx, identifiers, opts)
coll := collector.NewResourceStatusCollector(identifiers)
done := coll.ListenWithObserver(eventsChan, desiredStatusNotifierFunc(cancel, status.CurrentStatus))
<-done
for _, rs := range coll.ResourceStatuses {
switch rs.Status {
case status.CurrentStatus:
sc.logger.Successf("%s: %s ready", rs.Identifier.Name, strings.ToLower(rs.Identifier.GroupKind.Kind))
case status.NotFoundStatus:
sc.logger.Failuref("%s: %s not found", rs.Identifier.Name, strings.ToLower(rs.Identifier.GroupKind.Kind))
default:
sc.logger.Failuref("%s: %s not ready", rs.Identifier.Name, strings.ToLower(rs.Identifier.GroupKind.Kind))
}
}
if coll.Error != nil || ctx.Err() == context.DeadlineExceeded {
return fmt.Errorf("timed out waiting for condition")
}
return nil
}
// desiredStatusNotifierFunc returns an Observer function for the
// ResourceStatusCollector that will cancel the context (using the cancelFunc)
// when all resources have reached the desired status.
func desiredStatusNotifierFunc(cancelFunc context.CancelFunc,
desired status.Status) collector.ObserverFunc {
return func(rsc *collector.ResourceStatusCollector, _ event.Event) {
var rss []*event.ResourceStatus
for _, rs := range rsc.ResourceStatuses {
rss = append(rss, rs)
}
aggStatus := aggregator.AggregateStatus(rss, desired)
if aggStatus == desired {
cancelFunc()
}
}
}
Loading…
Cancel
Save