`
-* **Secret**: use the `token` string
-
-With the above settings, when you push a commit to the repository, the following happens:
-
-* GitHub sends the Git push event to the receiver address
-* Notification controller validates the authenticity of the payload using HMAC
-* Source controller is notified about the changes
-* Source controller pulls the changes into the cluster and updates the `GitRepository` revision
-* Kustomize controller is notified about the revision change
-* Kustomize controller reconciles all the `Kustomizations` that reference the `GitRepository` object
diff --git a/docs/migration/timetable.md b/docs/migration/timetable.md
deleted file mode 100644
index 537028a7..00000000
--- a/docs/migration/timetable.md
+++ /dev/null
@@ -1,38 +0,0 @@
----
-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.
-
-
-
-
-
-[^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.
diff --git a/docs/proposals/go-git-providers.md b/docs/proposals/go-git-providers.md
deleted file mode 100644
index 661b5094..00000000
--- a/docs/proposals/go-git-providers.md
+++ /dev/null
@@ -1,510 +0,0 @@
-# go-git-providers
-
-## Abstract
-
-This proposal aims to create a library with the import path `github.com/fluxcd/go-git-providers`'
-(import name: `gitprovider`), which provides an abstraction layer for talking to Git providers
-like GitHub, GitLab and Bitbucket.
-
-This would become a new repository, specifically targeted at being a general-purpose Git provider
-client for multiple providers and domains.
-
-## Goals
-
-- Support multiple Git provider backends (e.g. GitHub, GitLab, Bitbucket, etc.) using the same interface
-- Support talking to multiple domains at once, including custom domains (e.g. talking to "gitlab.com" and "version.aalto.fi" from the same client)
-- Support both no authentication (for public repos), basic auth, and OAuth2 for authentication
-- Manipulating the following resources:
- - **Organizations**: `GET`, `LIST` (both all accessible top-level orgs and sub-orgs)
- - For a given **Organization**:
- - **Teams**: `GET` and `LIST`
- - **Repositories**: `GET`, `LIST` and `POST`
- - **Team Access**: `LIST`, `POST` and `DELETE`
- - **Credentials**: `LIST`, `POST` and `DELETE`
-- Support sub-organizations (or "sub-groups" in GitLab) if possible
-- Support reconciling an object for idempotent operations
-- Pagination is automatically handled for `LIST` requests
-- Transparently can manage teams (collections of users, sub-groups in Gitlab) with varying access to repos
-- Follow library best practices in order to be easy to vendor (e.g. use major `vX` versioning & go.mod)
-
-## Non-goals
-
-- Support for features not mentioned above
-
-## Design decisions
-
-- A `context.Context` should be passed to every request as the first argument
-- There should be two interfaces per resource, if applicable:
- - one collection-specific interface, with a plural name (e.g. `OrganizationsClient`), that has methods like `Get()` and `List()`
- - one instance-specific interface, with a singular name (e.g. `OrganizationClient`), that operates on that instance, e.g. allowing access to child resources, e.g. `Teams()`
-- Every `Create()` signature shall have a `{Resource}CreateOptions` struct as the last argument.
- - `Delete()` and similar methods may use the same pattern if needed
-- All `*Options` structs shall be passed by value (i.e. non-nillable) and contain only nillable, optional fields
-- All optional fields in the type structs shall be nillable
-- It should be possible to create a fake API client for testing, implementing the same interfaces
-- All type structs shall have a `Validate()` method, and optionally a `Default()` one
-- All type structs shall expose their internal representation (from the underlying library) through the `InternalGetter` interface with a method `GetInternal() interface{}`
-- Typed errors shall be returned, wrapped using Go 1.14's new features
-- Go-style enums are used when there are only a few supported values for a field
-- Every field is documented using Godoc comment, including `+required` or `+optional` to clearly signify its importance
-- Support serializing the types to JSON (if needed for e.g. debugging) by adding tags
-
-## Implementation
-
-### Provider package
-
-The provider package, e.g. at `github.com/fluxcd/go-git-providers/github`, will have constructor methods so a client can be created, e.g. as follows:
-
-```go
-// Create a client for github.com without any authentication
-c := github.NewClient()
-
-// Create a client for an enterprise GitHub account, without any authentication
-c = github.NewClient(github.WithBaseURL("enterprise.github.com"))
-
-// Create a client for github.com using a personal oauth2 token
-c = github.NewClient(github.WithOAuth2(""))
-```
-
-### Client
-
-The definition of a `Client` is as follows:
-
-```go
-// Client is an interface that allows talking to a Git provider
-type Client interface {
- // The Client allows accessing all known resources
- ResourceClient
-
- // SupportedDomain returns the supported domain
- // This field is set at client creation time, and can't be changed
- SupportedDomain() string
-
- // ProviderID returns the provider ID (e.g. "github", "gitlab") for this client
- // This field is set at client creation time, and can't be changed
- ProviderID() ProviderID
-
- // Raw returns the Go client used under the hood for accessing the Git provider
- Raw() interface{}
-}
-```
-
-As one can see, the `Client` is scoped for a single backing domain. `ProviderID` is a typed string, and every
-implementation package defines their own constant, e.g. `const ProviderName = gitprovider.ProviderID("github")`.
-
-The `ResourceClient` actually allows talking to resources of the API, both for single objects, and collections:
-
-```go
-// ResourceClient allows access to resource-specific clients
-type ResourceClient interface {
- // Organization gets the OrganizationClient for the specific top-level organization
- // ErrNotTopLevelOrganization will be returned if the organization is not top-level when using
- Organization(o OrganizationRef) OrganizationClient
-
- // Organizations returns the OrganizationsClient handling sets of organizations
- Organizations() OrganizationsClient
-
- // Repository gets the RepositoryClient for the specified RepositoryRef
- Repository(r RepositoryRef) RepositoryClient
-
- // Repositories returns the RepositoriesClient handling sets of organizations
- Repositories() RepositoriesClient
-}
-```
-
-In order to reference organizations and repositories, there are the `OrganizationRef` and `RepositoryRef`
-interfaces:
-
-```go
-// OrganizationRef references an organization in a Git provider
-type OrganizationRef interface {
- // String returns the HTTPS URL
- fmt.Stringer
-
- // GetDomain returns the URL-domain for the Git provider backend, e.g. gitlab.com or version.aalto.fi
- GetDomain() string
- // GetOrganization returns the top-level organization, i.e. "weaveworks" or "kubernetes-sigs"
- GetOrganization() string
- // GetSubOrganizations returns the names of sub-organizations (or sub-groups),
- // e.g. ["engineering", "frontend"] would be returned for gitlab.com/weaveworks/engineering/frontend
- GetSubOrganizations() []string
-}
-
-// RepositoryRef references a repository hosted by a Git provider
-type RepositoryRef interface {
- // RepositoryRef requires an OrganizationRef to fully-qualify a repo reference
- OrganizationRef
-
- // GetRepository returns the name of the repository
- GetRepository() string
-}
-```
-
-Along with these, there is `OrganizationInfo` and `RepositoryInfo` which implement the above mentioned interfaces in a straightforward way.
-
-If you want to create an `OrganizationRef` or `RepositoryRef`, you can either use `NewOrganizationInfo()` or `NewRepositoryInfo()`, filling in all parts of the reference, or use the `ParseRepositoryURL(r string) (RepositoryRef, error)` or `ParseOrganizationURL(o string) (OrganizationRef, error)` methods.
-
-As mentioned above, only one target domain is supported by the `Client`. This means e.g. that if the `Client` is configured for GitHub, and you feed it a GitLab URL to parse, `ErrDomainUnsupported` will be returned.
-
-This brings us to a higher-level client abstraction, `MultiClient`.
-
-### MultiClient
-
-In order to automatically support multiple domains and providers using the same interface, `MultiClient` is introduced.
-
-The user would use the `MultiClient` as follows:
-
-```go
-// Create a client to github.com without authentication
-gh := github.NewClient()
-
-// Create a client to gitlab.com, authenticating with basic auth
-gl := gitlab.NewClient(gitlab.WithBasicAuth("", ""))
-
-// Create a MultiClient which supports talking to any of these backends
-client := gitprovider.NewMultiClient(gh, gl, aalto)
-```
-
-The interface definition of `MultiClient` is similar to that one of `Client`, both embedding `ResourceClient`, but it also allows access to domain-specific underlying `Client`'s:
-
-```go
-// MultiClient allows talking to multiple Git providers at once
-type MultiClient interface {
- // The MultiClient allows accessing all known resources, automatically choosing the right underlying
- // Client based on the resource's domain
- ResourceClient
-
- // SupportedDomains returns a list of known domains
- SupportedDomains() []string
-
- // ClientForDomain returns the Client used for a specific domain
- ClientForDomain(domain string) (Client, bool)
-}
-```
-
-### OrganizationsClient
-
-The `OrganizationsClient` provides access to a set of organizations, as follows:
-
-```go
-// OrganizationsClient operates on organizations the user has access to
-type OrganizationsClient interface {
- // Get a specific organization the user has access to
- // This might also refer to a sub-organization
- // ErrNotFound is returned if the resource does not exist
- Get(ctx context.Context, o OrganizationRef) (*Organization, error)
-
- // List all top-level organizations the specific user has access to
- // List should return all available organizations, using multiple paginated requests if needed
- List(ctx context.Context) ([]Organization, error)
-
- // Children returns the immediate child-organizations for the specific OrganizationRef o.
- // The OrganizationRef may point to any sub-organization that exists
- // This is not supported in GitHub
- // Children should return all available organizations, using multiple paginated requests if needed
- Children(ctx context.Context, o OrganizationRef) ([]Organization, error)
-
- // Possibly add Create/Update/Delete methods later
-}
-```
-
-The `Organization` struct is fairly straightforward for now:
-
-```go
-// Organization represents an (top-level- or sub-) organization
-type Organization struct {
- // OrganizationInfo provides the required fields
- // (Domain, Organization and SubOrganizations) required for being an OrganizationRef
- OrganizationInfo `json:",inline"`
- // InternalHolder implements the InternalGetter interface
- // +optional
- InternalHolder `json:",inline"`
-
- // Name is the human-friendly name of this organization, e.g. "Weaveworks" or "Kubernetes SIGs"
- // +required
- Name string `json:"name"`
-
- // Description returns a description for the organization
- // No default value at POST-time
- // +optional
- Description *string `json:"description"`
-}
-```
-
-The `OrganizationInfo` struct is a straightforward struct just implementing the `OrganizationRef` interface
-with basic fields & getters. `InternalHolder` is implementing the `InternalGetter` interface as follows, and is
-embedded into all main structs:
-
-```go
-// InternalGetter allows access to the underlying object
-type InternalGetter interface {
- // GetInternal returns the underlying struct that's used
- GetInternal() interface{}
-}
-
-// InternalHolder can be embedded into other structs to implement the InternalGetter interface
-type InternalHolder struct {
- // Internal contains the underlying object.
- // +optional
- Internal interface{} `json:"-"`
-}
-```
-
-### OrganizationClient
-
-`OrganizationClient` allows access to a specific organization's underlying resources as follows:
-
-```go
-// OrganizationClient operates on a given/specific organization
-type OrganizationClient interface {
- // Teams gives access to the TeamsClient for this specific organization
- Teams() OrganizationTeamsClient
-}
-```
-
-#### Organization Teams
-
-Teams belonging to a certain organization can at this moment be fetched on an individual basis, or listed.
-
-```go
-// OrganizationTeamsClient handles teams organization-wide
-type OrganizationTeamsClient interface {
- // Get a team within the specific organization
- // teamName may include slashes, to point to e.g. "sub-teams" i.e. subgroups in Gitlab
- // teamName must not be an empty string
- // ErrNotFound is returned if the resource does not exist
- Get(ctx context.Context, teamName string) (*Team, error)
-
- // List all teams (recursively, in terms of subgroups) within the specific organization
- // List should return all available organizations, using multiple paginated requests if needed
- List(ctx context.Context) ([]Team, error)
-
- // Possibly add Create/Update/Delete methods later
-}
-```
-
-The `Team` struct is defined as follows:
-
-```go
-// Team is a representation for a team of users inside of an organization
-type Team struct {
- // Team embeds OrganizationInfo which makes it automatically comply with OrganizationRef
- OrganizationInfo `json:",inline"`
- // Team embeds InternalHolder for accessing the underlying object
- // +optional
- InternalHolder `json:",inline"`
-
- // Name describes the name of the team. The team name may contain slashes
- // +required
- Name string `json:"name"`
-
- // Members points to a set of user names (logins) of the members of this team
- // +required
- Members []string `json:"members"`
-}
-```
-
-In GitLab, teams could be modelled as users in a sub-group. Those users can later be added as a single unit
-to access a given repository.
-
-### RepositoriesClient
-
-`RepositoriesClient` provides access to a set of repositories for the user.
-
-```go
-// RepositoriesClient operates on repositories the user has access to
-type RepositoriesClient interface {
- // Get returns the repository at the given path
- // ErrNotFound is returned if the resource does not exist
- Get(ctx context.Context, r RepositoryRef) (*Repository, error)
-
- // List all repositories in the given organization
- // List should return all available organizations, using multiple paginated requests if needed
- List(ctx context.Context, o OrganizationRef) ([]Repository, error)
-
- // Create creates a repository at the given organization path, with the given URL-encoded name and options
- // ErrAlreadyExists will be returned if the resource already exists
- Create(ctx context.Context, r *Repository, opts RepositoryCreateOptions) (*Repository, error)
-
- // Reconcile makes sure r is the actual state in the backing Git provider. If r doesn't exist
- // under the hood, it is created. If r is already the actual state, this is a no-op. If r isn't
- // the actual state, the resource will either be updated or deleted/recreated.
- Reconcile(ctx context.Context, r *Repository) error
-}
-```
-
-`RepositoryCreateOptions` has options like `AutoInit *bool`, `LicenseTemplate *string` and so forth to allow an
-one-time initialization step.
-
-The `Repository` struct is defined as follows:
-
-```go
-// Repository represents a Git repository provided by a Git provider
-type Repository struct {
- // RepositoryInfo provides the required fields
- // (Domain, Organization, SubOrganizations and RepositoryName)
- // required for being an RepositoryRef
- RepositoryInfo `json:",inline"`
- // InternalHolder implements the InternalGetter interface
- // +optional
- InternalHolder `json:",inline"`
-
- // Description returns a description for the repository
- // No default value at POST-time
- // +optional
- Description *string `json:"description"`
-
- // Visibility returns the desired visibility for the repository
- // Default value at POST-time: RepoVisibilityPrivate
- // +optional
- Visibility *RepoVisibility
-}
-
-// GetCloneURL gets the clone URL for the specified transport type
-func (r *Repository) GetCloneURL(transport TransportType) string {
- return GetCloneURL(r, transport)
-}
-```
-
-As can be seen, there is also a `GetCloneURL` function for the repository which allows
-resolving the URL from which to clone the repo, for a given transport method (`ssh` and `https`
-are supported `TransportType`s)
-
-### RepositoryClient
-
-`RepositoryClient` allows access to a given repository's underlying resources, like follows:
-
-```go
-// RepositoryClient operates on a given/specific repository
-type RepositoryClient interface {
- // TeamAccess gives access to what teams have access to this specific repository
- TeamAccess() RepositoryTeamAccessClient
-
- // Credentials gives access to manipulating credentials for accessing this specific repository
- Credentials() RepositoryCredentialsClient
-}
-```
-
-#### Repository Teams
-
-`RepositoryTeamAccessClient` allows adding & removing teams from the list of authorized persons to access a repository.
-
-```go
-// RepositoryTeamAccessClient operates on the teams list for a specific repository
-type RepositoryTeamAccessClient interface {
- // Create adds a given team to the repo's team access control list
- // ErrAlreadyExists will be returned if the resource already exists
- // The embedded RepositoryInfo of ta does not need to be populated, but if it is,
- // it must equal to the RepositoryRef given to the RepositoryClient.
- Create(ctx context.Context, ta *TeamAccess, opts RepositoryAddTeamOptions) error
-
- // Lists the team access control list for this repo
- List(ctx context.Context) ([]TeamAccess, error)
-
- // Reconcile makes sure ta is the actual state in the backing Git provider. If ta doesn't exist
- // under the hood, it is created. If ta is already the actual state, this is a no-op. If ta isn't
- // the actual state, the resource will either be updated or deleted/recreated.
- // The embedded RepositoryInfo of ta does not need to be populated, but if it is,
- // it must equal to the RepositoryRef given to the RepositoryClient.
- Reconcile(ctx context.Context, ta *TeamAccess) error
-
- // Delete removes the given team from the repo's team access control list
- // ErrNotFound is returned if the resource does not exist
- Delete(ctx context.Context, teamName string) error
-}
-```
-
-The `TeamAccess` struct looks as follows:
-
-```go
-// TeamAccess describes a binding between a repository and a team
-type TeamAccess struct {
- // TeamAccess embeds RepositoryInfo which makes it automatically comply with RepositoryRef
- // +optional
- RepositoryInfo `json:",inline"`
- // TeamAccess embeds InternalHolder for accessing the underlying object
- // +optional
- InternalHolder `json:",inline"`
-
- // Name describes the name of the team. The team name may contain slashes
- // +required
- Name string `json:"name"`
-
- // Permission describes the permission level for which the team is allowed to operate
- // Default: read
- // Available options: See the TeamRepositoryPermission enum
- // +optional
- Permission *TeamRepositoryPermission
-}
-```
-
-#### Repository Credentials
-
-`RepositoryCredentialsClient` allows adding & removing credentials (e.g. deploy keys) from accessing a specific repository.
-
-```go
-// RepositoryCredentialsClient operates on the access credential list for a specific repository
-type RepositoryCredentialsClient interface {
- // Create a credential with the given human-readable name, the given bytes and optional options
- // ErrAlreadyExists will be returned if the resource already exists
- Create(ctx context.Context, c RepositoryCredential, opts CredentialCreateOptions) error
-
- // Lists all credentials for the given credential type
- List(ctx context.Context, t RepositoryCredentialType) ([]RepositoryCredential, error)
-
- // Reconcile makes sure c is the actual state in the backing Git provider. If c doesn't exist
- // under the hood, it is created. If c is already the actual state, this is a no-op. If c isn't
- // the actual state, the resource will either be updated or deleted/recreated.
- Reconcile(ctx context.Context, c RepositoryCredential) error
-
- // Deletes a credential from the repo. name corresponds to GetName() of the credential
- // ErrNotFound is returned if the resource does not exist
- Delete(ctx context.Context, t RepositoryCredentialType, name string) error
-}
-```
-
-In order to support multiple different types of credentials, `RepositoryCredential` is an interface:
-
-```go
-// RepositoryCredential is a credential that allows access (either read-only or read-write) to the repo
-type RepositoryCredential interface {
- // GetType returns the type of the credential
- GetType() RepositoryCredentialType
-
- // GetName returns a name (or title/description) of the credential
- GetName() string
-
- // GetData returns the key that will be authorized to access the repo, this can e.g. be a SSH public key
- GetData() []byte
-
- // IsReadOnly returns whether this credential is authorized to write to the repository or not
- IsReadOnly() bool
-}
-```
-
-The default implementation of `RepositoryCredential` is `DeployKey`:
-
-```go
-// DeployKey represents a short-lived credential (e.g. an SSH public key) used for accessing a repository
-type DeployKey struct {
- // DeployKey embeds InternalHolder for accessing the underlying object
- // +optional
- InternalHolder `json:",inline"`
-
- // Title is the human-friendly interpretation of what the key is for (and does)
- // +required
- Title string `json:"title"`
-
- // Key specifies the public part of the deploy (e.g. SSH) key
- // +required
- Key []byte `json:"key"`
-
- // ReadOnly specifies whether this DeployKey can write to the repository or not
- // Default value at POST-time: true
- // +optional
- ReadOnly *bool `json:"readOnly"`
-}
-```
diff --git a/docs/roadmap/index.md b/docs/roadmap/index.md
deleted file mode 100644
index b4088451..00000000
--- a/docs/roadmap/index.md
+++ /dev/null
@@ -1,148 +0,0 @@
-# Roadmap
-
-!!! hint "Production readiness"
- 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:
-
-- [source-controller](../components/source)
-- [kustomize-controller](../components/kustomize)
-- [notification-controller](../components/notification)
-- [helm-controller](../components/helm)
-
-The following GitOps Toolkit APIs are considered production ready:
-
-- `source.toolkit.fluxcd.io/v1beta1`
-- `kustomize.toolkit.fluxcd.io/v1beta1`
-- `notification.toolkit.fluxcd.io/v1beta1`
-- `helm.toolkit.fluxcd.io/v2beta1`
-
-## The road to Flux v2 GA
-
-In our planning discussions we have identified these possible areas of work,
-this list is subject to change while we gather feedback:
-
-- Stabilize the image automation APIs
- * Review the spec of `ImageRepository`, `ImagePolicy` and `ImageUpdateAutomation`
- * Promote the image automation APIs to `v1beta1`
- * Include the image automation controllers in the default components list
-
-- Improve the documentation
- * Gather feedback on the [migration guides](https://github.com/fluxcd/flux2/discussions/413) and address more use-cases
- * Incident management and troubleshooting guides
- * Cloud specific guides (AWS, Azure, Google Cloud, more?)
- * Consolidate the docs under [fluxcd.io](https://fluxcd.io) website
-
-## The road to Flux v1 feature parity
-
-In our planning discussions we identified three areas of work:
-
-- Feature parity with Flux v1 in read-only mode
-- Feature parity with the image-update functionality in Flux v1
-- Feature parity with Helm Operator v1
-
-### Flux read-only feature parity
-
-[= 100% "100%"]
-
-Flux v2 read-only is ready to try. See the [Getting
-Started](https://toolkit.fluxcd.io/get-started/) how-to, and the
-[Migration
-guide](https://toolkit.fluxcd.io/guides/flux-v1-migration/).
-
-This would be the first stepping stone: we want Flux v2 to be on-par with today's Flux in
-[read-only mode](https://github.com/fluxcd/flux/blob/master/docs/faq.md#can-i-run-flux-with-readonly-git-access)
-and [FluxCloud](https://github.com/justinbarrick/fluxcloud) notifications.
-
-Goals
-
-- :material-check-bold: [Offer a migration guide for those that are using Flux in read-only mode to synchronize plain manifests](https://toolkit.fluxcd.io/guides/flux-v1-migration/)
-- :material-check-bold: [Offer a migration guide for those that are using Flux in read-only mode to synchronize Kustomize overlays](https://toolkit.fluxcd.io/guides/flux-v1-migration/)
-- :material-check-bold: [Offer a dedicated component for forwarding events to external messaging platforms](https://toolkit.fluxcd.io/guides/notifications/)
-
-Non-Goals
-
-- Migrate users that are using Flux to run custom scripts with `flux.yaml`
-- Automate the migration of `flux.yaml` kustomize users
-
-Tasks
-
-- [x] Design the events API
-- [x] Implement events in source and kustomize controllers
-- [x] Make the kustomize-controller apply/gc events on-par with Flux v1 apply events
-- [x] Design the notifications and events filtering API
-- [x] Implement a notification controller for Slack, MS Teams, Discord, Rocket
-- [x] Implement Prometheus metrics in source and kustomize controllers
-- [x] Review the git source and kustomize APIs
-- [x] Support [bash-style variable substitution](https://toolkit.fluxcd.io/components/kustomize/kustomization/#variable-substitution) as an alternative to `flux.yaml` envsubst/sed usage
-- [x] Create a migration guide for `flux.yaml` kustomize users
-- [x] Include support for SOPS
-
-### Flux image update feature parity
-
-[= 100% "100%"]
-
-Image automation is available as a prerelease. See [this
-guide](https://toolkit.fluxcd.io/guides/image-update/) for how to
-install and use it.
-
-Goals
-
-- Offer components that can replace Flux v1 image update feature
-
-Non-Goals
-
-- Maintain backwards compatibility with Flux v1 annotations
-- [Order by timestamps found inside image layers](https://github.com/fluxcd/flux2/discussions/802)
-
-Tasks
-
-- [x] [Design the image scanning and automation API](https://github.com/fluxcd/flux2/discussions/107)
-- [x] Implement an image scanning controller
-- [x] Public image repo support
-- [x] Credentials from Secret [fluxcd/image-reflector-controller#35](https://github.com/fluxcd/image-reflector-controller/pull/35)
-- [x] Design the automation component
-- [x] Implement the image scan/patch/push workflow
-- [x] Integrate the new components in the Flux CLI [fluxcd/flux2#538](https://github.com/fluxcd/flux2/pull/538)
-- [x] Write a guide for how to use image automation ([guide here](https://toolkit.fluxcd.io/guides/image-update/))
-- [x] ACR/ECR/GCR integration ([guide here](https://toolkit.fluxcd.io/guides/image-update/#imagerepository-cloud-providers-authentication))
-- [x] Write a migration guide from Flux v1 annotations ([guide here](https://toolkit.fluxcd.io/guides/flux-v1-automation-migration/))
-
-### Helm v3 feature parity
-
-[= 100% "100%"]
-
-Helm support in Flux v2 is ready to try. See the [Helm controller
-guide](https://toolkit.fluxcd.io/guides/helmreleases/), and the [Helm
-controller migration
-guide](https://toolkit.fluxcd.io/guides/helm-operator-migration/).
-
-Goals
-
-- Offer a migration guide for those that are using Helm Operator with Helm v3 and charts from
- Helm and Git repositories
-
-Non-Goals
-
-- Migrate users that are using Helm v2
-
-Tasks
-
-- [x] Implement a Helm controller for Helm v3 covering all the current release options
-- [x] Discuss and design Helm releases based on source API:
- * [x] Providing values from sources
- * [x] Conditional remediation on failed Helm actions
- * [x] Support for Helm charts from Git
-- [x] Review the Helm release, chart and repository APIs
-- [x] Implement events in Helm controller
-- [x] Implement Prometheus metrics in Helm controller
-- [x] Implement support for values from `Secret` and `ConfigMap` resources
-- [x] Implement conditional remediation on (failed) Helm actions
-- [x] Implement support for Helm charts from Git
-- [x] Implement support for referring to an alternative chart values file
-- [x] Stabilize API
-- [x] [Create a migration guide for Helm Operator users](../guides/helm-operator-migration.md)
diff --git a/docs/use-cases/azure.md b/docs/use-cases/azure.md
deleted file mode 100644
index 64a68876..00000000
--- a/docs/use-cases/azure.md
+++ /dev/null
@@ -1,233 +0,0 @@
-# Using Flux on Azure
-
-## AKS Cluster Options
-
-It's important to follow some guidelines when installing Flux on AKS.
-
-### CNI and Network Policy
-
-Previously, there has been an issue with Flux and Network Policy on AKS.
-([Upstream Azure Issue](https://github.com/Azure/AKS/issues/2031)) ([Flux Issue](https://github.com/fluxcd/flux2/issues/703))
-If you ensure your AKS cluster is upgraded, and your Nodes have been restarted with the most recent Node images,
-this could resolve flux reconciliation failures where source-controller is unreachable.
-Using `--network-plugin=azure --network-policy=calico` has been tested to work properly.
-This issue only affects you if you are using `--network-policy` on AKS, which is not a default option.
-
-!!! warning
- AKS `--network-policy` is currently in Preview
-
-### AAD Pod-Identity
-
-Depending on the features you are interested in using with Flux, you may want to install AAD Pod Identity.
-With [AAD Pod-Identity](https://azure.github.io/aad-pod-identity/docs/), we can create Pods that have their own
-cloud credentials for accessing Azure services like Azure Container Registry(ACR) and Azure Key Vault(AKV).
-
-If you do not use AAD Pod-Identity, you'll need to manage and store Service Principal credentials
-in K8s Secrets, to integrate Flux with other Azure Services.
-
-As a pre-requisite, your cluster must have `--enable-managed-identity` configured.
-
-This software can be [installed via Helm](https://azure.github.io/aad-pod-identity/docs/getting-started/installation/)
-(unmanaged by Azure).
-Use Flux's `HelmRepository` and `HelmRelease` object to manage the aad-pod-identity installation
-from a bootstrap repository and keep it up to date.
-
-!!! note
- As an alternative to Helm, the `--enable-aad-pod-identity` flag for the `az aks create` is currently in Preview.
- Follow the Azure guide for [Creating an AKS cluster with AAD Pod Identity](https://docs.microsoft.com/en-us/azure/aks/use-azure-ad-pod-identity)
- if you would like to enable this feature with the Azure CLI.
-
-### Cluster Creation
-
-The following creates an AKS cluster with some minimal configuration that will work well with Flux:
-
-```sh
-az aks create \
- --network-plugin="azure" \
- --network-policy="calico" \
- --enable-managed-identity \
- --enable-pod-identity \
- --name="my-cluster"
-```
-
-!!! info
- When working with the Azure CLI, it can help to set a default `location`, `group`, and `acr`.
- See `az configure --help`, `az configure --list-defaults`, and `az configure --defaults key=value`.
-
-## Flux Installation for Azure DevOps
-
-Ensure you can login to [dev.azure.com](https://dev.azure.com) for your proper organization,
-and create a new repository to hold your Flux install and other Kubernetes resources.
-
-Clone the Git repository locally:
-
-```sh
-git clone ssh://git@ssh.dev.azure.com/v3///
-cd my-repository
-```
-
-Create a directory inside the repository:
-
-```sh
-mkdir -p ./clusters/my-cluster/flux-system
-```
-
-Download the [Flux CLI](../guides/installation.md#install-the-flux-cli) and generate the manifests with:
-
-```sh
-flux install \
- --export > ./clusters/my-cluster/flux-system/gotk-components.yaml
-```
-
-Commit and push the manifest to the master branch:
-
-```sh
-git add -A && git commit -m "add components" && git push
-```
-
-Apply the manifests on your cluster:
-
-```sh
-kubectl apply -f ./clusters/my-cluster/flux-system/gotk-components.yaml
-```
-
-Verify that the controllers have started:
-
-```sh
-flux check
-```
-
-Create a `GitRepository` object on your cluster by specifying the SSH address of your repo:
-
-```sh
-flux create source git flux-system \
- --git-implementation=libgit2 \
- --url=ssh://git@ssh.dev.azure.com/v3/// \
- --branch= \
- --ssh-key-algorithm=rsa \
- --ssh-rsa-bits=4096 \
- --interval=1m
-```
-
-The above command will prompt you to add a deploy key to your repository, but Azure DevOps
-[does not support repository or org-specific deploy keys](https://developercommunity.visualstudio.com/t/allow-the-creation-of-ssh-deploy-keys-for-vsts-hos/365747).
-You may add the deploy key to a user's personal SSH keys, but take note that
-revoking the user's access to the repository will also revoke Flux's access.
-The better alternative is to create a machine-user whose sole purpose is
-to store credentials for automation.
-Using a machine-user also has the benefit of being able to be read-only or
-restricted to specific repositories if this is needed.
-
-!!! note
- Unlike `git`, Flux does not support the
- ["shorter" scp-like syntax for the SSH protocol](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols#_the_ssh_protocol)
- (e.g. `ssh.dev.azure.com:v3`).
- Use the [RFC 3986 compatible syntax](https://tools.ietf.org/html/rfc3986#section-3) instead: `ssh.dev.azure.com/v3`.
-
-If you wish to use Git over HTTPS, then generate a personal access token and supply it as the password:
-
-```sh
-flux create source git flux-system \
- --git-implementation=libgit2 \
- --url=https://dev.azure.com///_git/ \
- --branch=main \
- --username=git \
- --password=${AZ_PAT_TOKEN} \
- --interval=1m
-```
-
-Please consult the [Azure DevOps documentation](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page)
-on how to generate personal access tokens for Git repositories.
-Azure DevOps PAT's always have an expiration date, so be sure to have some process for renewing or updating these tokens.
-Similar to the lack of repo-specific deploy keys, a user needs to generate a user-specific PAT.
-If you are using a machine-user, you can generate a PAT or simply use the machine-user's password which does not expire.
-
-Create a `Kustomization` object on your cluster:
-
-```sh
-flux create kustomization flux-system \
- --source=flux-system \
- --path="./clusters/my-cluster" \
- --prune=true \
- --interval=10m
-```
-
-Export both objects, generate a `kustomization.yaml`, commit and push the manifests to Git:
-
-```sh
-flux export source git flux-system \
- > ./clusters/my-cluster/flux-system/gotk-sync.yaml
-
-flux export kustomization flux-system \
- >> ./clusters/my-cluster/flux-system/gotk-sync.yaml
-
-cd ./clusters/my-cluster/flux-system && kustomize create --autodetect
-
-git add -A && git commit -m "add sync manifests" && git push
-```
-
-Wait for Flux to reconcile your previous commit with:
-
-```sh
-watch flux get kustomization flux-system
-```
-
-### Flux Upgrade
-
-To upgrade the Flux components to a newer version, download the latest `flux` binary,
-run the install command in your repository root, commit and push the changes:
-
-```sh
-flux install \
- --export > ./clusters/my-cluster/flux-system/gotk-components.yaml
-
-git add -A && git commit -m "Upgrade to $(flux -v)" && git push
-```
-
-The [source-controller](../components/source/controller.md) will pull the changes on the cluster,
-then [kustomize-controller](../components/source/controller.md)
-will perform a rolling update of all Flux components including itself.
-
-## Helm Repositories on Azure Container Registry
-
-The Flux `HelmRepository` object currently supports
-[Chart Repositories](https://helm.sh/docs/topics/chart_repository/)
-as well as fetching `HelmCharts` from paths in `GitRepository` sources.
-
-Azure Container Registry has a sub-command ([`az acr helm`](https://docs.microsoft.com/en-us/cli/azure/acr/helm))
-for working with ACR-Hosted Chart Repositories, but it is deprecated.
-If you are using these deprecated Azure Chart Repositories,
-you can use Flux `HelmRepository` objects with them.
-
-[Newer ACR Helm documentation](https://docs.microsoft.com/en-us/azure/container-registry/container-registry-helm-repos)
-suggests using ACR as an experimental [Helm OCI Registry](https://helm.sh/docs/topics/registries/).
-This will not work with Flux, because using Charts from OCI Registries is not yet supported.
-
-## Secrets Management with SOPS and Azure Key Vault
-
-You will need to create an Azure Key Vault and bind a credential such as a Service Principal or Managed Identity to it.
-If you want to use Managed Identities, install or enable [AAD Pod Identity](#aad-pod-identity).
-
-Patch kustomize-controller with the proper Azure credentials, so that it may access your Azure Key Vault, and then begin
-committing SOPS encrypted files to the Git repository with the proper Azure Key Vault configuration.
-
-See the [Mozilla SOPS Azure Guide](../guides/mozilla-sops.md#azure) for further detail.
-
-## Image Updates with Azure Container Registry
-
-You will need to create an ACR registry and bind a credential such as a Service Principal or Managed Identity to it.
-If you want to use Managed Identities, install or enable [AAD Pod Identity](#aad-pod-identity).
-
-You may need to update your Flux install to include additional components:
-```sh
-flux install \
- --components-extra="image-reflector-controller,image-automation-controller" \
- --export > ./clusters/my-cluster/flux-system/gotk-components.yaml
-```
-
-Follow the [Image Update Automation Guide](../guides/image-update.md) and see the
-[ACR specific section](../guides/image-update.md#azure-container-registry) for more details.
-
-Your AKS cluster's configuration can also be updated to
-[allow the kubelets to pull images from ACR](https://docs.microsoft.com/en-us/azure/aks/cluster-container-registry-integration)
-without ImagePullSecrets as an optional, complimentary step.
diff --git a/docs/use-cases/gh-actions-manifest-generation.md b/docs/use-cases/gh-actions-manifest-generation.md
deleted file mode 100644
index f240ccd3..00000000
--- a/docs/use-cases/gh-actions-manifest-generation.md
+++ /dev/null
@@ -1,1279 +0,0 @@
-# GitHub Actions Manifest Generation
-
-This example implements "build-time" manifest generation on GitHub Actions.
-
-Third-party tools are used to generate YAML manifests in a CI job. The updated YAML are committed and pushed to Git, where `kustomize-controller` finally applies them.
-
-### Background
-
-There are many use cases for manifest generation tools, but Flux v2 no longer permits embedding arbitrary binaries with the Flux machinery to run at apply time.
-
-Flux (kustomize-controller) will apply whatever revision of the manifests are at the latest commit, on any branch it is pointed at. By design, Flux doesn't care for any details of how a commit is generated.
-
-Since ["select latest by build time" image automation][flux2/discussions/802] is deprecated, and since [`.flux.yaml` is also deprecated][flux2/issues/543], some staple workflows are no longer possible without new accommodations from infrastructure.
-
-#### What Should We Do?
-
-We first recommend users [adjust their tagging strategies][Sortable image tags], which is made clear elsewhere in the docs. This is usually a straightforward adjustment, and enables the use of [Image Update Policies][image update guide]; however this may not be feasible or desired in some cases.
-
-## Use Manifest Generation
-
-Introducing, Manifest Generation with Jsonnet, for [any old app] on GitHub!
-
-If you have followed the [Flux bootstrap guide] and only have one `fleet-infra` repository, it is recommended to create a separate repository that represents your application for this use case guide, or clone the repository linked above in order to review these code examples which have already been implemented there.
-
-### Primary Uses of Flux
-
-Flux's primary use case for `kustomize-controller` is to apply YAML manifests from the latest `Revision` of an `Artifact`.
-
-### Security Consideration
-
-Flux v2 can not be configured to call out to arbitrary binaries that a user might supply with an `InitContainer`, as it was possible to do in Flux v1.
-
-#### Motivation for this Guide
-
-In Flux v2 it is assumed if users want to run more than `Kustomize` with `envsubst`, that it will be done outside of Flux; the goal of this guide is to show several common use cases of this pattern in secure ways.
-
-#### Demonstrated Concepts
-
-It is intended, finally, to show through this use case, three fundamental ideas for use in CI to accompany Flux automation:
-
-1. Writing workflow that can commit changes back to the same branch of a working repository.
-1. A workflow to commit generated content from one directory into a different branch in the repository.
-1. Workflow to commit from any source directory into a target branch on a different repository.
-
-Readers can interpret this document with adaptations for use with other CI providers, or Git source hosts, or manifest generators.
-
-Jsonnet is demonstrated with examples presented in sufficient depth that, hopefully, Flux users who are not already familiar with manifest generation or Jsonnet can pick up `kubecfg` and start using it to solve novel and interesting configuration problems.
-
-### The Choice of GitHub Actions
-
-There are authentication concerns to address with every CI provider and they also differ by Git provider.
-
-Given that GitHub Actions are hosted on GitHub, this guide can be streamlined in some ways. We can almost completely skip configuring authentication. The cross-cutting concern is handled by the CI platform, except in our fourth and final example, the *Commit Across Repositories Workflow*.
-
-From a GitHub Action, as we must have been authenticated to write to a branch, Workflows also can transitively gain write access to the repo safely.
-
-Mixing and matching from other providers like Bitbucket Cloud, Jenkins, or GitLab will need more attention to these details for auth configurations. GitHub Actions is a platform that is designed to be secure by default.
-
-## Manifest Generation Examples
-
-There are several use cases presented.
-
-* [String Substitution with sed -i]
-* [Docker Build and Tag with Version]
-* [Jsonnet for YAML Document Rehydration]
-* [Commit Across Repositories Workflow]
-
-In case these examples are too heavy, this short link guide can help you navigate the four main examples. Finally, the code examples we've all been waiting for, the answer to complex `.flux.yaml` configs in Flux v2! 🎉🎁
-
-### String Substitution with `sed -i`
-
-The entry point for these examples begins at `.github/workflows/` in any GitHub source repository where your YAML manifests are stored.
-
-!!! warning "`GitRepository` source only targets one branch"
- While this first example operates on any branch (`branches: ['*']`), each `Kustomization` in Flux only deploys manifests from **one branch or tag** at a time. Understanding this is key for managing large Flux deployments and clusters with multiple `Kustomizations` and/or crossing several environments.
-
-First add this directory if needed in your repositories. Find the example below in context, and read on to understand how it works: [01-manifest-generate.yaml].
-
-```yaml
-# ./.github/workflows/01-manifest-generate.yaml
-name: Manifest Generation
-on:
- push:
- branches:
- - '*'
-
-jobs:
- run:
- name: Push Git Update
- runs-on: ubuntu-latest
- steps:
- - name: Prepare
- id: prep
- run: |
- VERSION=${GITHUB_SHA::8}
- echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- echo ::set-output name=VERSION::${VERSION}
-
- - name: Checkout repo
- uses: actions/checkout@v2
-
- - name: Update manifests
- run: ./update-k8s.sh $GITHUB_SHA
-
- - name: Commit changes
- uses: EndBug/add-and-commit@v7
- with:
- add: '.'
- message: "[ci skip] deploy from ${{ steps.prep.outputs.VERSION }}"
- signoff: true
-```
-
-In the `Prepare` step, even before the clone, GitHub Actions provides metadata about the commit. Then, `Checkout repo` performs a shallow clone for the build.
-
-```bash
-# excerpt from above - set two outputs named "VERSION" and "BUILD_DATE"
-VERSION=${GITHUB_SHA::8}
-echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
-echo ::set-output name=VERSION::${VERSION}
-```
-
-!!! note "When migrating to Flux v2"
- Users will find that [some guidance has changed since Flux v1]. Tagging images with a `GIT_SHA` was a common practice that is no longer supported by Flux's Image Automation. A newer alternative is adding timestamp or build number in [Sortable image tags], preferred by the `image-automation-controller`.
-
-Next we call out to a shell script `update-k8s.sh` taking one argument, the Git SHA value from GitHub:
-
-```yaml
-# excerpted from above - run a shell script
-- name: Update manifests
- run: ./update-k8s.sh $GITHUB_SHA
-```
-
-That script is below. It performs two in-place string substitutions using `sed`.
-
-```bash
-#!/bin/bash
-
-# update-k8s.sh
-set -feu # Usage: $0 # Fails when GIT_SHA is not provided
-
-GIT_SHA=${1:0:8}
-sed -i "s|image: kingdonb/any-old-app:.*|image: kingdonb/any-old-app:$GIT_SHA|" k8s.yml
-sed -i "s|GIT_SHA: .*|GIT_SHA: $GIT_SHA|" flux-config/configmap.yaml
-```
-
-`update-k8s.sh` receives `GITHUB_SHA` that the script trims down to 8 characters.
-
-Then, `sed -i` runs twice, updating `k8s.yml` and `flux-config/configmap.yaml` which are also provided as examples here. The new SHA value is added twice, once in each file.
-
-```yaml
-# k8s.yml
-apiVersion: apps/v1
-kind: Deployment
-metadata:
- name: any-old-app
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: any-old-app
- template:
- metadata:
- labels:
- app: any-old-app
- spec:
- containers:
- - image: kingdonb/any-old-app:4f314627
- name: any-old-app
----
-apiVersion: v1
-kind: Service
-metadata:
- name: any-old-app
-spec:
- type: ClusterIP
- ports:
- - name: "any-old-app"
- port: 3000
- selector:
- app: any-old-app
-```
-
-The convention of including a `k8s.yml` file in one's application repository is borrowed from [Okteto's Getting Started Guides], as a simplified example.
-
-The `k8s.yml` file in the application root is not meant to be applied by Flux, but might be a handy template to keep fresh as a developer reference nonetheless.
-
-The file below, `configmap.yaml`, is placed in a directory `flux-config/` which will be synchronized to the cluster by a `Kustomization` that we will add in the following step.
-
-```yaml
-# flux-config/configmap.yaml
-apiVersion: v1
-data:
- GIT_SHA: 4f314627
-kind: ConfigMap
-metadata:
- creationTimestamp: null
- name: any-old-app-version
- namespace: devl
-```
-
-These are the two files that are re-written in the `sed -i` example above.
-
-A configmap is an ideal place to write a variable that is needed by any downstream `Kustomization`, for example to use with `envsubst`.
-
-```yaml
----
-apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
-kind: Kustomization
-metadata:
- name: any-old-app-devl
-spec:
- interval: 15m0s
- path: ./
- prune: true
- sourceRef:
- kind: GitRepository
- name: any-old-app-prod
- targetNamespace: prod
- validation: client
- postBuild:
- substituteFrom:
- - kind: ConfigMap
- name: any-old-app-version
----
-apiVersion: source.toolkit.fluxcd.io/v1beta1
-kind: GitRepository
-metadata:
- name: any-old-app-prod
- namespace: prod
-spec:
- interval: 20m0s
- ref:
- branch: deploy
- secretRef:
- name: flux-secret
- url: ssh://git@github.com/kingdonb/csh-flux
-```
-
-Now, any downstream `Deployment` in the `Kustomization` can write a `PodSpec` like this one, to reference the image from the latest commit referenced by the `ConfigMap`:
-
-```yaml
-# flux/ some-example-deployment.yaml
-spec:
- replicas: 1
- selector:
- matchLabels:
- app: any-old-app
- template:
- metadata:
- labels:
- app: any-old-app
- spec:
- containers:
- - image: kingdonb/any-old-app:${GIT_SHA}
- name: any-old-app
-```
-
-Deployment specifications will vary, so adapting this example is left as exercise for the reader. Write it together with a kustomization.yaml, or just add this to a subdirectory anywhere within your Flux Kustomization path.
-
-### Docker Build and Tag with Version
-
-Now for another staple workflow: building and pushing an OCI image tag from a Dockerfile in any branch or tag.
-
-From the Actions marketplace, [Build and push Docker images] provides the heavy lifting in this example. Flux has nothing to do with building images, but we include this still — as some images will need to be built for our use in these examples.
-
-!!! hint "`ImageRepository` can reflect both branches and tags"
- This example builds an image for any branch or tag ref and pushes it to Docker Hub. (Note the omission of `branches: ['*']` that was in the prior example.) GitHub Secrets `DOCKERHUB_USERNAME` and `DOCKERHUB_TOKEN` are used here to authenticate with Docker Hub from within GitHub Actions.
-
-We again borrow a [Prepare step] from Kustomize Controller's own release workflow. Find the example below in context, [02-docker-build.yaml], or copy it from below.
-
-```yaml
-# ./.github/workflows/02-docker-build.yaml
-name: Docker Build, Push
-
-on:
- push:
- branches:
- - '*'
- tags-ignore:
- - 'release/*'
-
-jobs:
- docker:
- runs-on: ubuntu-latest
- steps:
- - name: Prepare
- id: prep
- run: |
- VERSION=${GITHUB_SHA::8}
- if [[ $GITHUB_REF == refs/tags/* ]]; then
- VERSION=${GITHUB_REF/refs\/tags\//}
- fi
- echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- echo ::set-output name=VERSION::${VERSION}
-
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v1
-
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
-
- - name: Login to DockerHub
- uses: docker/login-action@v1
- with:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
-
- - name: Build and push
- id: docker_build
- uses: docker/build-push-action@v2
- with:
- push: true
- tags: kingdonb/any-old-app:${{ steps.prep.outputs.VERSION }}
-
- - name: Image digest
- run: echo ${{ steps.docker_build.outputs.digest }}
-```
-
-The [Docker Login Action] is used here to enable an authenticated image push.
-
-Any secrets from GitHub Secrets can be used as shown, and support for image registries is explained in the linked README. Add a setting for `registry` if your app uses any private registry, rather than the implicit Docker Hub registry above.
-
-```
-# for example
-with:
- registry: registry.cloud.okteto.net
-```
-
-The image tag `VERSION` comes from the branch or Git tag that triggered the build. Whether that version is a `GIT_SHA` or a Semantic Version, (or anything in between!) the same workflow can be used to build an OCI image as shown here.
-
-### Jsonnet for YAML Document Rehydration
-
-As mentioned before, Flux only monitors one branch or tag per Kustomization.
-
-In the earlier examples, no fixed branch target was specified. Whatever branch triggered the workflow, received the generated YAMLs in the next commit.
-
-If you created your deployment manifests in any branch, the `deploy` branch or otherwise, it is necessary to add another `Kustomization` and `GitRepository` source to apply manifests from that branch and path in the cluster.
-
-In application repositories, it is common to maintain an environment branch, a release branch, or both. Some additional Flux objects may be needed for each new environment target with its own branch. Jsonnet can be used for more easily managing heavyweight repetitive boilerplate configuration such as this.
-
-It is recommended to follow these examples as they are written for better understanding, then later change and adapt them for your own release practices and environments.
-
-!!! note "`GitRepository` source only targets one branch"
- Since Flux uses one branch per Kustomization, to trigger an update we must write to a `deploy` branch or tag. Even when new app images can come from any branch (eg. for Dev environments where any latest commit is to be deployed) the YAML manifests to deploy will be sourced from just one branch.
-
-It is advisable to protect repository main and release branches with eg. branch policies and review requirements, as through automation, these branches can directly represent the production environment.
-
-The CI user for this example should be allowed to push directly to the `deploy` branch that Kustomize deploys from; this branch also represents the environment so must be protected in a similar fashion to `release`.
-
-Only authorized people (and build robots) should be allowed to make writes to a `deploy` branch.
-
-#### Jsonnet Render Action
-
-In this example, the outputted YAML manifests, (on successful completion of the Jsonnet render step,) are staged on the `deploy` branch, then committed and pushed.
-
-The latest commit on the `deploy` branch is reconciled into the cluster by another `Kustomization` that is omitted here, as it is assumed that users who have read this far already added this in the previous examples.
-
-You may find the example below in context, [03-release-manifests.yaml], or simply copy it from below.
-
-```yaml
-# ./.github/workflows/03-release-manifests.yaml
-name: Build jsonnet
-on:
- push:
- tags: ['release/*']
- branches: ['release']
-
-jobs:
- run:
- name: jsonnet push
- runs-on: ubuntu-latest
- steps:
- - name: Prepare
- id: prep
- run: |
- VERSION=${GITHUB_SHA::8}
- if [[ $GITHUB_REF == refs/tags/release/* ]]; then
- VERSION=${GITHUB_REF/refs\/tags\/release\//}
- fi
- echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- echo ::set-output name=VERSION::${VERSION}
-
- - name: Checkout repo
- uses: actions/checkout@v2
-
- - name: Setup kubecfg CLI
- uses: kingdonb/kubecfg/action@main
-
- - name: kubecfg show
- run: kubecfg show manifests/example.jsonnet > output/production.yaml
-
- - name: Prepare target branch
- run: ./ci/rake.sh deploy
-
- - name: Commit changes
- uses: EndBug/add-and-commit@v7
- with:
- add: 'production.yaml'
- branch: deploy
- message: "[ci skip] from ${{ steps.prep.outputs.VERSION }}"
- signoff: true
-```
-
-We add three new steps in this example:
-
-```yaml
-# excerpted from above - workflow steps 3, 4, and 5
-- name: Setup kubecfg CLI
- uses: kingdonb/kubecfg/action@main
-
-- name: kubecfg show
- run: kubecfg show manifests/example.jsonnet > output/production.yaml
-
-- name: Prepare target branch
- run: ./ci/rake.sh deploy
-```
-
-While the remaining examples will be written to depend on `kubecfg`, some use cases may prefer to use pure Jsonnet only as it is sandboxed and therefore safer. We plan to use the `kubecfg` capability to take input from other sources, like variables and references, but also network-driven imports and functions.
-
-```yaml
-# from above - substitute these steps in 03-release-manifests.yaml,
-# between "Checkout repo" and "Commit changes" to use plain Jsonnet instead of kubecfg
-- id: jsonnet-render
- uses: alexdglover/jsonnet-render@v1
- with:
- file: manifests/example.jsonnet
- output_file: output/production.yaml
- params: dryrun=true;env=prod
-
-- name: Prepare target branch
- run: ./ci/rake.sh deploy
-```
-
-The `jsonnet-render` step is borrowed from another source, again find it on [GitHub Actions Marketplace][actions/jsonnet-render] for more information. For Tanka users, there is also [letsbuilders/tanka-action] which describes itself as heavily inspired by `jsonnet-render`.
-
-!!! note "The `EndBug/add-and-commit` action is used again"
- This time, with the help of `rake.sh`, our change is staged into a different target branch. This is the same `deploy` branch, regardless of which branch or tag the build comes from; any configured push event can trigger this workflow to trigger an update to the deploy branch.
-
-```bash
-#!/bin/bash
-
-# ./ci/rake.sh
-set -feux # Usage: $0 # Fails when BRANCH is not provided
-BRANCH=$1
-
-# The output/ directory is listed in .gitignore, where jsonnet rendered output.
-pushd output
-
-# Fetch git branch 'deploy' and run `git checkout deploy`
-/usr/bin/git -c protocol.version=2 fetch \
- --no-tags --prune --progress --no-recurse-submodules \
- --depth=1 origin $BRANCH
-git checkout $BRANCH --
-
-# Prepare the output to commit by itself in the deploy branch's root directory.
-mv -f ./production.yaml ../ # Overwrite any existing files (no garbage collection here)
-git diff
-
-# All done (the commit will take place in the next action!)
-popd
-```
-
-Give this file `chmod +x` before adding and committing; tailor this workflow to your needs. We render from a file `manifests/example.jsonnet`, it can be anything. The output is a single K8s YAML file, `production.yaml`.
-
-```yaml
-- name: Commit changes
- uses: EndBug/add-and-commit@v7
- with:
- add: 'production.yaml'
- branch: deploy
- message: "[ci skip] from ${{ steps.prep.outputs.VERSION }}"
- signoff: true
-```
-
-This is [Add & Commit] with a `branch` option, to set the target branch. We've added a `signoff` option as well here, to demonstrate another feature of this GitHub Action. There are many ways to use this workflow step. The link provides more information.
-
-The examples that follow can be copied and pasted into `manifests/example.jsonnet`, then committed to the `release` branch and pushed to GitHub in order to execute them.
-
-Pushing this to your repository will fail at first, unless and until a `deploy` branch is created.
-
-Run `git checkout --orphan deploy` to create a new empty HEAD in your repo.
-
-Run `git reset` and `git stash` to dismiss any files that were staged, then run `git commit --allow-empty` to create an initial empty commit on the branch.
-
-Now you can copy and run these commands to create an empty branch:
-
-```
-#- Add a basic kustomization.yaml file
-cat < kustomization.yaml
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-resources:
-- production.yaml
-EOF
-
-#- Add a gitignore so output directory is created
-cat < .gitignore
-/output/**
-!/output/.keep
-EOF
-
-#- Add the .keep file
-touch output/.keep
-
-#- Push these files into an empty branch, and go back to main branch
-git add output/.keep .gitignore kustomization.yaml
-git commit -m'seed deploy kustomization.yaml for prod'
-git push -u origin deploy
-git checkout main
-```
-
-On the main branch as well, create a `.gitignore` and `/output/.keep` for that branch too. We need to make sure that the `output/` directory is present for writing whenever the Jsonnet workflow begins. The `rake.sh` script sweeps files from the output into the root directory of the `deploy` branch.
-
-Now run `git checkout -b release; git push -u origin release` to trigger this action and see it working! 🤞🤞
-
-You may need to be sure that GitHub Actions are enabled on your repository before this will work.
-
-Read onward to see some basic as well as more advanced uses of `kubecfg`.
-
-##### Jsonnet `ConfigMap` with `envsubst`
-
-The next example "enforces," or copies, a value from a `configMap` from one namespace into many namespaces. This is done so that Kustomizations for each namespace can maintain similar config data in their reconciliations while staying DRY, with some configurations that reach across namespace boundaries.
-
-With Jsonnet, Kustomize, and Kustomization Controller's `postBuild` which uses `envsubst`, there are usually a handful of different ways to accomplish the same task.
-
-This example demonstrates a feature called `ext_vars` or [External Variables] in the Jsonnet `stdlib`.
-
-These examples assume (since no such protection has been presented) that nothing prevents `production.yaml` from writing resources throughout multiple namespaces. This may be difficult or impossible to achieve depending on your environment.
-
-In order to permit a Kustomization to write into different namespaces, some RBAC configuration may be required.
-
-When you write a `Kustomization` to apply this, be sure you are aware of whether or not you have set `targetNamespace` on the Flux `Kustomization` as it may override any namespace settings in the Jsonnet output. You may note similar configuration in the `kustomization.yaml` we wrote into the deploy branch as described above, in the step for **Jsonnet Render Action**.
-
-##### External Variable Substitution
-
-```javascript
-# Any Old App Jsonnet example 0.10.1 - manifests/example.jsonnet
-
-local kube = import 'https://github.com/bitnami-labs/kube-libsonnet/raw/73bf12745b86718083df402e89c6c903edd327d2/kube.libsonnet';
-
-local example = import 'example.libsonnet';
-
-{
- version_configmap: kube.ConfigMap('any-old-app-version') {
- metadata+: {
- namespace: 'prod',
- },
- data+: {
- VERSION: std.extVar('VERSION'),
- },
- },
- flux_kustomization: example.kustomization('any-old-app-prod') {
- metadata+: {
- namespace: 'flux-system',
- },
- spec+: {
- path: './flux-config/',
- postBuild+: {
- substituteFrom+: [
- {
- kind: 'ConfigMap',
- name: 'any-old-app-version',
- },
- ],
- },
- },
- },
- flux_gitrepository: example.gitrepository('any-old-app-prod') {
- metadata+: {
- namespace: 'flux-system',
- },
- spec+: {
- url: 'https://github.com/kingdonb/any_old_app',
- },
- },
-}
-```
-
-The above jsonnet declaration `example.jsonnet` will not complete without its neighbor `example.libsonnet` (which can be found [linked here][example 10.1 library].) This part of the example contains some boilerplate detail not meant to be copied, like the name `any-old-app-prod` and the string `'sops-gpg'` in `decryption.secretRef` which should be changed to match your environment).
-
-If you visited the linked `example.libsonnet` you may have noticed definitions for `kustomization` and `gitrepository` that are frankly pretty specific for a library function. They include details you wouldn't expect to find in a vendor library, like a default git repository URL, and a default hardcoded ref to the name of our Source gitrepository.
-
-This is **our library file**, so it can have our own implementation-specific details in it if we want to include them. Now, the power of Jsonnet is visible; we get to decide which configuration needs to be exposed in our main `example.jsonnet` file, and which parameters are defaults provided by the library, that can be treated like boilerplate and re-defined however we want.
-
-```json
-data+: {
- VERSION: std.extVar('VERSION'),
-},
-```
-
-This is `std.extVar` from `ext_vars` mentioned earlier. Arrange for the version to be passed in through the GitHub Actions workflow:
-
-```yaml
-# adapted from above - 03-release-manifests.yaml
-- name: kubecfg show
- run: kubecfg show -V VERSION=${{ steps.prep.outputs.VERSION }} manifests/example.jsonnet > output/production.yaml
-```
-
-The neighbor `example.libsonnet` file contains some boring (but necessary) boilerplate, so that `kubecfg` can fulfill this jsonnet, to generate and commit the full Kustomize-ready YAML into a `deploy` branch as specified in the workflow. (The `Kustomization` for this example is provided [from my fleet-infra repo here][any-old-app-deploy-kustomization.yaml]. Personalize and adapt this for use with your own application or manifest generations.)
-
-The values provided are for example only and should be personalized, or restructured/rewritten completely to suit your preferred template values and instances. For more idiomatic examples written recently by actual Jsonnet pros, the [Tanka - Using Jsonnet tutorial] is great, and so is [Tanka - Parameterizing] which I'll call out specifically for the `_config::` object example that is decidedly more elegant than my version of parameter passing.
-
-If you've not previously used Jsonnet before, then you might be wondering about that code example you just read and that's OK! If you **have** previously used Jsonnet and already know what idiomatic Jsonnet looks like, you might be wondering too... you can probably tell I (author, Kingdon) practically haven't ever written a lick of Jsonnet before today.
-
-These examples are going to get progressively more advanced as I learn Jsonnet while I go. At this point I already think it's pretty cool and I barely know how to use it, but I am starting to understand what type of problems people are using it to solve.
-
-ConfigMap values are not treated as secret data, so there is no encryption to contend with; this makes for what seems like a good first example. Jsonnet enthusiasts, please forgive my newness. I am sure that my interpretation of how to write Jsonnet is most likely not optimal or idiomatic.
-
-Above we showed how to pass in a string from our build pipeline, and use it to write back generated Jsonnet manifests into a commit.
-
-##### Make Two Environments
-
-Here's a second example, defining two environments in separate namespaces, instead of just one:
-
-```javascript
-# Any Old App Jsonnet example 0.10.2-alpha1 - manifests/example.jsonnet
-# Replicate a section of config and change nothing else about it
-
-// ...
-
-{
- version_configmap: kube.ConfigMap('any-old-app-version') {
- metadata+: {
- namespace: 'flux-system',
- },
- data+: {
- VERSION: std.extVar('VERSION'),
- },
- },
- test_flux_kustomization: example.kustomization('any-old-app-test') {
- metadata+: {
- namespace: 'flux-system',
- },
- spec+: {
- path: './flux-config/',
- postBuild+: {
- substituteFrom+: [
- {
- kind: 'ConfigMap',
- name: 'any-old-app-version',
- },
- ],
- },
- targetNamespace: 'test-tenant',
- },
- },
- prod_flux_kustomization: example.kustomization('any-old-app-prod') {
- metadata+: {
- namespace: 'flux-system',
- },
- spec+: {
- path: './flux-config/',
- postBuild+: {
- substituteFrom+: [
- {
- kind: 'ConfigMap',
- name: 'any-old-app-version',
- },
- ],
- },
- targetNamespace: 'prod-tenant',
- },
- },
- flux_gitrepository: example.gitrepository('any-old-app-prod') {
- metadata+: {
- namespace: 'flux-system',
- },
- spec+: {
- url: 'https://github.com/kingdonb/any_old_app',
- },
- },
-}
-```
-
-In this example, some front-matter was omitted for brevity. Wait, what? (There's nothing brief about this example, it's extra-verbose!)
-
-"I thought Jsonnet was supposed to be DRY." Be gentle, refactoring is a methodical and deliberate process. We simply copied the original one environment into two environments, test and prod, which differ only in name.
-
-In the next example, we will subtly change one of them to be configured differently from the other.
-
-##### Change Something and Refactor
-
-Note the string 'flux-system' only occurs once now, having been factored into a variable `config_ns`. These are some basic abstractions in Jsonnet that we can use to start to DRY up our source manifests.
-
-Again, practically nothing changes functionally, this still does exactly the same thing. With another refactoring, we can express this manifest more concisely, thanks to a new library function we can invent, named `example.any_old_app`.
-
-```javascript
-# Any Old App Jsonnet example 0.10.2-alpha4 - manifests/example.jsonnet
-# Make something different between test and prod
-
-// ...
-
-{
- version_configmap: kube.ConfigMap('any-old-app-version') {
- metadata+: {
- namespace: config_ns,
- },
- data+: {
- VERSION: std.extVar('VERSION'),
- },
- },
- test_flux_kustomization: example.any_old_app('test') {
- spec+: {
- prune: true,
- },
- },
- prod_flux_kustomization: example.any_old_app('prod') {
- spec+: {
- prune: false,
- },
- },
- flux_gitrepository: example.gitrepository('any-old-app-prod') {
- metadata+: {
- namespace: config_ns,
- },
- spec+: {
- url: 'https://github.com/kingdonb/any_old_app',
- },
- },
-}
-```
-
-Two things have changed to make this refactoring of the config differ from the first version. Hopefully you'll notice it's a lot shorter.
-
-Redundant strings have been collapsed into a variable, and more boilerplate has been moved into the library.
-
-This refactored state is perhaps the most obvious to review, and most intentionally clear about its final intent to the reader. Hopefully you noticed the original environments were identical (or if your eyes glossed over because of the wall of values, you've at least taken my word for it.)
-
-But now, these two differ. We're creating two configurations for `any_old_app`, named `test` and `prod`. One of them has `prune` enabled, the test environment, and `prod` is set more conservatively to prevent accidental deletions, with a setting of `prune: false`.
-
-Since the two environments should each differ only by the boolean setting of `spec.prune`, we can now pack up and hide away the remainder of the config in with the rest of the boilerplate.
-
-Hiding the undifferentiated boilerplate in a library makes it easier to detect and observe this difference in a quick visual review.
-
-Here's the new library function's definition:
-
-```javascript
-any_old_app(environment):: self.kustomization('any-old-app-' + environment) {
- metadata+: {
- namespace: 'flux-system',
- },
- spec+: {
- path: './flux-config/',
- postBuild+: {
- substituteFrom+: [
- {
- kind: 'ConfigMap',
- name: 'any-old-app-version',
- },
- ],
- },
- targetNamespace: environment + '-tenant',
- },
-},
-```
-
-This excerpt is taken from [the 10.2 release version][example 10.2 library excerpt] of `example.libsonnet`, where you can also read the specific definition of `kustomization` that is invoked with the expression `self.kustomization('any-old-app-' + environment)`.
-
-The evolution of this jsonnet snippet has gone from *unnecessarily verbose* to **perfect redundant clarity**. I say redundant, but I'm actually fine with this exactly the way it is. I think, if nothing further changes, we already have met the best way to express this particular manifest with Jsonnet.
-
-But given that config will undoubtedly have to change as the differing requirements of our development teams and their environments grow, this perfect clarity unfortunately can't last forever in its current form. It will have to scale.
-
-Notice that strings and repeated invocations of `any_old_app` are written with parallel structure and form, but there's nothing explicit linking them.
-
-The object-oriented programmer in me can't help but ask now, "what happens when we need another copy of the environment, this time slightly more different than those two, and ... how about two more after that, (and actually, can we really get by with only ten environments?)" — I am inclined towards thinking of this repeated structure as a sign that an object cries out, waiting to be recognized and named, and defined, (and refactored and defined again.)
-
-##### List Comprehension
-
-So get ready for _obfuscated nightmare mode_, (which is the name we thoughtfully reserved for the [best and final version][example 10.2 jsonnet] of the example,) shown below.
-
-```javascript
-# Any Old App Jsonnet example 0.10.2 - manifests/example.jsonnet
-
-// This is a simple manifest generation example to demo some simple tasks that
-// can be automated through Flux, with Flux configs rehydrated through Jsonnet.
-
-// This example uses kube.libsonnet from Bitnami. There are other
-// Kubernetes libraries available, or write your own!
-local kube = import 'https://github.com/bitnami-labs/kube-libsonnet/raw/73bf12745b86718083df402e89c6c903edd327d2/kube.libsonnet';
-
-// The declaration below adds configuration to a more verbose base, defined in
-// more detail at the neighbor libsonnet file here:
-local example = import 'example.libsonnet';
-local kubecfg = import 'kubecfg.libsonnet';
-local kustomize = import 'kustomize.libsonnet';
-
-local config_ns = 'flux-system';
-
-local flux_config = [
- kube.ConfigMap('any-old-app-version') {
- data+: {
- VERSION: std.extVar('VERSION'),
- },
- },
- example.gitrepository('any-old-app-prod') {
- spec+: {
- url: 'https://github.com/kingdonb/any_old_app',
- },
- },
-] + kubecfg.parseYaml(importstr 'examples/configMap.yaml');
-
-local kustomization = kustomize.applyList([
- kustomize.namespace(config_ns),
-]);
-
-local kustomization_output = std.map(kustomization, flux_config);
-
-{ flux_config: kustomization_output } + {
-
- local items = ['test', 'prod'],
-
- joined: {
- [ns + '_flux_kustomization']: {
- data: example.any_old_app(ns) {
- spec+: {
- prune: if ns == 'prod' then false else true,
- },
- },
- }
- for ns in items
-
- // Credit:
- // https://groups.google.com/g/jsonnet/c/ky6sjYj4UZ0/m/d4lZxWbhAAAJ
- // thanks Dave for showing how to do something like this in Jsonnet
- },
-}
-```
-
-This is the sixth revision of this example, (some have been omitted from the story, but they are [in Git history][examples 0.10.2-all].) I think it's really perfect now. If you're a programmer, I think, this version is perhaps much clearer. That's why I called it _obfuscated nightmare mode_, right? (I'm a programmer, I swear.)
-
-The `examples/configMap.yaml` file can be found [in the 0.10.2 tag][example 10.2 configmap] of `kingdonb/any_old_app`, it is vestigial and does not serve any functional purpose in this example, except for showing how to compose Jsonnet objects with parsed YAML from a file.
-
-You should note that kubecfg's `kubecfg.parseYaml` method always returns an array, even when the `importstr` input file only contains a single YAML document. Jsonnet arrays, like strings, can be easily added together with a familiar `+` operator.
-
-Jsonnet objects can also be added to other objects, composing their fields from smaller objects into larger ones. In the example above, we have added the `flux_config` object to a collection of `AnyOldApp` objects, a list comprehension from our environments. This is necessary and important because a Jsonnet program or library must always return a single object.
-
-I'm trying to learn Jsonnet as fast as I can, I hope you're still with me and if not, don't worry. Where did all of this programming come from? (And what's a list comprehension?) It really doesn't matter.
-
-The heavy lifting libraries for this example are from [anguslees/kustomize-libsonnet], which implements some basic primitives of Kustomize in Jsonnet. YAML parser is provided by [bitnami/kubecfg][kubecfg yaml parser], and the Jsonnet implementations of Kubernetes primitives by [bitnami-labs/kube-libsonnet].
-
-It is a matter of taste whether you consider from above the first, second, or third example to be better stylistically. It is a matter of taste and circumstances, to put a finer point on it. They each have strengths and weaknesses, depending mostly on whatever changes we will have to make to them next.
-
-We can compare these three versions to elucidate the intent of the programmatically most expressive version which followed the other two. If you're new at this, you may try to explain how these three examples are similar, and also how they differ. Follow the explanation below for added clarity.
-
-If you haven't studied Jsonnet, this last version may daunt you with its complexity. The fact is YAML is a document store and Jsonnet is a programming language. This complexity is exactly what we came here for, we want our configuration language to be more powerful! Bring on more complex Jsonnet examples!
-
-#### Breaking It Down
-
-We define a configmap and a gitrepository (in Jsonnet), then put it together with another configmap (from plain YAML). That's called `flux_config`.
-
-```javascript
-local kustomization = kustomize.applyList([
- kustomize.namespace(config_ns),
-]);
-
-local kustomization_output = std.map(kustomization, flux_config);
-```
-
-This little diddy (above) has the same effect as a Kustomization based on the following instruction to `kustomize build`, (except it's all jsonnet):
-
-```yaml
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-namespace: ${config_ns}
-```
-
-... setting the namespace for all objects in `flux_config` to the value of `config_ns`.
-
-Next, we join it together with a list comprehension (at least I think that's what this is called):
-
-```javascript
-local items = ['test', 'prod'],
-
-joined: {
- [ns + '_flux_kustomization']: {
- data: example.any_old_app(ns) {
- spec+: {
- prune: if ns == 'prod' then false else true,
- },
- },
- }
- for ns in items
-},
-```
-
-Two `any_old_app` templates are invoked programmatically, with different properties and names, and in target namespaces that are based on the environment names. They go on the end of the document list, and Jsonnet renders them alongside of the others, in various namespaces.
-
-This is the same technique as in `01-manifest-generate.yaml`, only this time with Jsonnet and `kubecfg` instead of `sed`, (and what a difference it makes!)
-
-This is the foundation for some real release machinery for your applications, this is not just a bunch of shell scripts. Whenever any commit hits the `release` branch, or when any tag in the form `release/*` is pushed, the repo is configured to push generated manifest changes to a `deploy` branch.
-
-This behavior is self-contained within the example `any_old_app` repository in these examples.
-
-We can use GitHub Actions and Jsonnet to populate parameters through ConfigMap values or with `extVars`, and at the same time, apply `Kustomization` and `GitRepository` as new sync infrastructure for the `deploy` branch with dependencies on those ConfigMaps. The `Kustomization` refers to the configmap and makes the `VERSION` or `GIT_SHA` variable available as a `postBuild` substitution, with values pulled from that same configmap we just applied.
-
-Later, we can repeat this process with a SOPS encrypted secret.
-
-The process is not very different, though some of the boilerplate is longer, we've already learned to pack away boilerplate. Copying and renaming encrypted secrets within the same cluster is possible wherever cluster operators are permitted to both decrypt and encrypt them with the decryption provider.
-
-A credential at `spec.decryption.secretRef` holds the key for decryption. Without additional configuration secrets can usually be copied freely around the cluster, as it is possible to decrypt them freely anywhere the decryption keys are made available.
-
-##### Copy `ConfigMap`s
-
-Assume that each namespace will be separately configured as a tenant by itself somehow later, and that each tenant performs its own git reconciliation within the tenant namespace. That config is out of scope for this example. We are only interested in briefly demonstrating some Jsonnet use cases here.
-
-The app version to install is maintained in a `ConfigMap` in each namespace based on our own decision logic. This can be implemented as a human operator who goes in and updates this variable's value before release time.
-
-This Jsonnet creates from a list of namespaces, and injects a `ConfigMap` into each namespace, [another example.jsonnet][example 10.3 jsonnet].
-
-```javascript
-# Any Old App Jsonnet example 0.10.3 - manifests/example.jsonnet
-
-local release_config = kube.ConfigMap('any-old-app-version');
-local namespace_list = ['prod', 'stg', 'qa', 'uat', 'dev'];
-
-local release_version = '0.10.3';
-local latest_candidate = '0.10.3-alpha1';
-
-{
- [ns + '_tenant']: {
- [ns + '_namespace']: {
- namespace: kube.Namespace(ns),
- },
- [ns + '_configmap']: {
- version_data: release_config {
- metadata+: {
- namespace: ns,
- },
- data+: {
- VERSION: if ns == 'prod' || ns == 'stg' then release_version else latest_candidate,
- },
- },
- },
- }
- for ns in namespace_list
-}
-```
-
-In this example, we have set up an additional 3 namespaces and assumed that a Flux Kustomization is provided some other way. The deploy configuration of all 5 environments is maintained here, in a single deploy config.
-
-Imagine that two policies should exist for promoting releases into environments. The environments for `dev`elopment, `U`ser `A`cceptance `T`esting (`uat`), and `Q`uality `A`ssurance (`qa`) can all be primed with the latest release candidate build at any given time.
-
-This is perhaps an excessive amount of formality for an open source or cloud-native project, though readers working in regulated environments may recognize this familiar pattern.
-
-This example will possibly fail to apply with the recommended validations enabled, failing with errors that you can review by running `flux get kustomization` in your flux namespace, like these:
-
-```
-validation failed: namespace/dev created (server dry run)
-namespace/prod created (server dry run)
-...
-Error from server (NotFound): error when creating "14f54b89-2456-4c15-862e-34670dfcda79.yaml": namespaces "dev" not found
-Error from server (NotFound): error when creating "14f54b89-2456-4c15-862e-34670dfcda79.yaml": namespaces "prod" not found
-```
-
-As you can perhaps see, the problem is that objects created within the namespace are not valid before creating the namespace. You can disable the validation temporarily by adding a setting `validation: none` to your Flux Kustomization to get past this error.
-
-In the deployment configuration above, both `prod` and staging (`stg`) are kept in sync with the latest release (not pre-release).
-
-Left as an exercise to the reader, we can also ask next: is it possible to supplement this configuration with a Flagger canary so that updates to the production config are able to be manually verified in the staging environment before they are promoted into Production?
-
-(Hint: Look at the [Manual Gating] feature of Flagger.)
-
-##### Copy `Secret`s
-
-This example writes the same `secretRef` into many `HelmReleases`, to provide for the cluster to be able to use the same `imagePullSecret` across several `Deployments` in a namespace. It is a common problem that `jsonnet` can solve quite handily, without repeating the `Secret` name over and over as a string.
-
-Because we have decided to create tenants for each namespace, now is a good time to mention [flux create tenant].
-
-We can take the output of `flux create tenant prod --with-namespace prod --export` and use it to create `manifests/examples/tenant.yaml`. Perhaps in a full implementation, we would create a tenant library function and call it many times to create our tenants.
-
-For this example, you may discard the `Namespace` and/or `ClusterRoleBinding` as they are not needed. Here, we actually just need a ServiceAccount to patch.
-
-```yaml
----
-# manifests/examples/tenant.yaml
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- labels:
- toolkit.fluxcd.io/tenant: prod
- name: prod
- namespace: prod
-```
-
-A namespace will be created by our Jsonnet example code instead (or you may comment this line out in the jsonnet below, if you are already working within a tenant.) The ClusterRoleBinding, or a more restrictive RoleBinding, is important for a functioning Flux tenant installation, but it is not needed for this example.
-
-(For more information on multi-tenancy, read the [Flux 2 Multi-Tenancy Guide].)
-
-We make an image pull secret with some docker registry credentials, for the purpose of completing the example. This is just for an example, it can be any secret that you want to replicate through several namespaces in the cluster with Jsonnet.
-
-```
-kubectl create secret docker-registry prod-docker-pull-secret \
- --namespace=prod \
- --docker-username=youruser --docker-password=secretpassword \
- --docker-email=required@example.org --dry-run=client -oyaml \
- > manifests/examples/sops-image-pull-secret.yaml
-sops -e -i manifests/examples/sops-image-pull-secret.yaml
-```
-
-If you are not familiar with SOPS encryption, you should complete the [Mozilla SOPS] Flux guide before replicating this example, and internalize all of the concepts explained there.
-
-You will need to have configured your cluster's Kustomization with a decryption provider and decryption keys to enable the inclusion of encrypted secrets in your config repos. It is not safe to write unencrypted secrets into your git repository, and this should be avoided at all costs even if your repository is kept private.
-
-This final Jsonnet example is presented in context as a working reference in the `any_old_app` repository, once again as [example.jsonnet][example 10.4 jsonnet].
-
-```javascript
-# Any Old App Jsonnet example 0.10.4 - manifests/example.jsonnet
-
-local kubecfg = import 'kubecfg.libsonnet';
-local kustomize = import 'kustomize.libsonnet';
-
-local tenant =
- kubecfg.parseYaml(importstr 'examples/tenant.yaml');
-local pull_secrets =
- kubecfg.parseYaml(importstr 'examples/sops-image-pull-secret.yaml');
-
-local prod_ns = 'prod';
-local staging_ns = 'stg';
-local image_pull_secret = 'prod-docker-pull-secret';
-
-// Set the Image Pull Secret on each ServiceAccount
-local updateConfig(o) = (
- if o.kind == 'ServiceAccount' then o {
- imagePullSecrets: [{ name: image_pull_secret }],
- } else o
-);
-
-// Create a namespace, and add to it Namespace and Secret
-local prod_tenant = [
- kube.Namespace(prod_ns),
-] + pull_secrets + tenant;
-
-// Prod kustomization - apply the updateConfig
-local prod_kustomization = kustomize.applyList([
- updateConfig,
-]);
-
-// Stg kustomization - apply the updateConfig and "stg" ns
-local staging_kustomization = kustomize.applyList([
- updateConfig,
- kustomize.namespace(staging_ns),
-]);
-
-// Include both kustomizations in the Jsonnet object
-{
- prod: std.map(prod_kustomization, prod_tenant),
- stg: std.map(staging_kustomization, prod_tenant),
-}
-```
-
-The `kubecfg.parseYaml` instruction returns a list of Jsonnet objects. Our own Jsonnet closely mirrors the [example provided][anguslees example jsonnet] by anguslees, with a few differences.
-
-The power of kubecfg is well illustrated through this example inspired by [anguslees/kustomize-libsonnet]. We parse several YAML files and make several minor updates to them. It really doesn't matter if one document involved is a secret, or that its data is encrypted by SOPS.
-
-If you are coming to Mozilla SOPS support in Flux v2, having used the SealedSecrets controller before when it was recommended in Flux v1, then you are probably surprised that this works. SOPS does not encrypt secret metadata when used with Flux's Kustomize Controller integration, which makes examples like this one possible.
-
-The ServiceAccount is a part of Flux's `tenant` configuration, and a fundamental concept of Kubernetes RBAC. If this concept is still new to you, read more in the [Kubernetes docs on Using Service Accounts].
-
-The other fundamental concept to understand is a Namespace.
-
-Secrets are namespaced objects, and ordinary users with tenant privileges cannot reach outside of their namespace. If tenants should manage a Flux Kustomization within their own namespace boundaries, then a `sops-gpg` secret must be present in the Namespace with the Kustomization. Cross-namespace secret refs are not supported.
-
-However, any principal with access to read a `sops-gpg` secret can decrypt any data that are encrypted for it.
-
-Each ServiceAccount can list one or more `imagePullSecrets`, and any pod that binds the ServiceAccount will automatically include any pull secrets provided there. By adding the imagePullSecret to a ServiceAccount, we can streamline including it everywhere that it is needed.
-
-We can apply a list of transformations with `kustomize.applyList` that provides a list of pass-through mutating functions for Jsonnet to apply to each Jsonnet object; in our case we use the `updateConfig` function to patch each ServiceAccount with the ImagePullSecret that we want it to use.
-
-Finally, for staging, we additionally apply `kustomize.namespace` to update all resources to use the `stg` namespace instead of the `prod` namespace. The secret can be copied anywhere we want within the reach of our Flux Kustomization, and since our Flux Kustomization still has `cluster-admin` and local access to the decryption key, there is no obstacle to copying secrets.
-
-#### Handling `Secret`s
-
-Because a `secret` is not safe to store in Git unencrypted, Flux recommends using SOPS to encrypt it.
-
-SOPS will produce a [different data key][sops/issues/315] for each fresh invocation of `sops -e`, producing different cipher data even for the same input data. This is true even when the secret content has not changed. This means, unfortunately, it is not practical for a Manifest Generation routine to implement secret transparency without also granting the capability to read secrets to the CI infrastructure.
-
-SOPS stores the metadata required to decrypt each secret in the metadata of the secret, which must be stored unencrypted to allow encrypted secrets to be read by the private key owners.
-
-Secret transparency means that it should be possible for an observer to know when a stored secret has been updated or rotated. Transparency can be achieved in SOPS by running `sops` as an editor, using `sops [encrypted.yaml]`, which decrypts for editing and re-encrypts the secret upon closing the editor, thereby only changing the cipher text when secret data also changes.
-
-Depending on your access model, this suggestion could be either a complete non-starter, or a helpful add-on.
-
-As an example, Secrets could be read from GitHub Secrets during a CI job, then written encrypted into a secret that is pushed to the deploy branch. This implementation provides a basic solution for simple centralized secrets rotation. But as this would go way beyond simple manifest generation, we consider this beyond the scope of the tutorial, and it is mentioned only as an example of a more complex usage scenario for users to consider.
-
-#### Replicate `Secrets` Across Namespaces
-
-When the data of a `secret` is stored in the Git repository, it can be encrypted to store and transmit safely. SOPS in Kustomize supports encryption of only `(stringData|data)` fields, not secret `metadata` including `namespace`. This means that secrets within the same repo can be copied freely and decrypted somewhere else, just as long as the `Kustomization` still has access to the SOPS private key.
-
-Because of these properties though, copying a SOPS-encrypted secret from one namespace to another within one single Flux tenant is as easy as cloning the YAML manifest and updating the `namespace` field. Compared to SealedSecrets controller, which does not permit this type of copying; SOPS, on the other hand, does not currently prevent this without some attention being paid to RBAC.
-
-Remember to protect your secrets with RBAC! This is not optional, when handling secrets as in this example.
-
-#### Protecting `Secrets` from Unauthorized Access
-
-The logical boundary of a secret is any cluster or tenant where the private key is available for decrypting.
-
-This means that any SOPS secret, once encrypted, can be copied anywhere or used as a base for other Kustomizations in the cluster, so long as the Kustomization itself has access to the decryption keys.
-
-It is important to understand that the `sops-gpg` key that is generated in the Flux SOPS guide can be used by any `Kustomization` in the `flux-system` namespace.
-
-It cannot be over-emphasized; if users want secrets to remain secret, the `flux-system` namespace (and indeed the entire cluster itself) must be hardened and protected, managed by qualified cluster admins. It is recommended that changes which could access encrypted secrets are tightly controlled as much as deemed appropriate.
-
-#### More Advanced Secrets Usage
-
-The use of KMS as opposed to in-cluster GPG keys with SOPS is left as an exercise for the reader. The basics of KMS with various cloud providers is covered in more depth by the [Mozilla SOPS][using various cloud providers] guide.
-
-Another scenario we considered, but rejected for these examples, requires to decrypt and then re-encrypt SOPS secrets, for use with the `secretGenerator` feature of Kustomize. This workflow is not supported here for reasons already explained.
-
-Flux suggests maintaining the only active copy of the decryption key for a cluster inside of that cluster (though there may be a provision for backups, or some alternate keys permitted to decrypt.) This arrangement makes such use cases significantly more complicated to explain, beyond the scope of this guide.
-
-For those uses though, additional Workflow Actions are provided:
-
-The [Decrypt SOPS Secrets] action may be useful and it is mentioned here, (but no example uses are provided.)
-
-The [Sops Binary Installer] action enables more advanced use cases, like encrypting or re-encrypting secrets.
-
-#### Jsonnet Recap
-
-While much of this type of manipulation could be handled in `Kustomization`'s `postBuild`, via `envsubst`, some configurations are more complicated this way. They can be better handled in CI, where access to additional tools can be provided.
-
-By writing YAML manifests into a Git commit, the same manifests that `Kustomize` directly applies, they can be saved for posterity. Or projected out into a new pull request where they can be reviewed before application, or with the proper safe-guards in place they can be applied immediately through a more direct-driven automation.
-
-With generated YAML that Flux applies in the cluster directly from Git commits, **fui-yoh** - that's GitOps!
-
-### Commit Across Repositories Workflow
-
-Flux will not deploy from pushes on just any branch; GitRepository sources target just one specific branch. Merging to a `staging` branch, for example, can be used to trigger a deployment to a Staging environment.
-
-Manifest generation can be used to solve, broadly, very many problems, such that even with many examples, this guide would never be totally exhaustive.
-
-This is the final example in this guide.
-
-Here we show 🥁 ... how to replicate the original behavior of Flux v1's image automation! 🤯 🎉
-
-You can put this workflow in your application repo, and target it toward your `fleet-infra` repo.
-
-To replicate the nearest approximation of Flux's "deploy latest image" feature of yesteryore, we use push events to do the job, as we hinted was possible in an earlier example. This can be done without Flux v1's redundant and expensive image pull behavior, retrieving build metadata required to order image tags for deployment.
-
-Flux recommends using real version numbers in your image tags, with a canonical ordering.
-
-The alternative is racy and doesn't always guarantee the latest commit will be the one that is deployed, since this behavior depends on the time that each commit is pushed, and even precisely how long the build takes to complete; the difference is fine for Dev environments, but this is not a strategy for Production use cases.
-
-Your app's CI can commit and push YAML manifests (or one manifest for each app) into a separate deploy branch for `Kustomization` to apply. The deploy branch in a separate repository should be a branch to which the CI user is granted write access.
-
-While there are some issues, this is actually perfect for non-prod deployments, eg. in a test environment!
-
-In context, find [04-update-fleet-infra.yaml], or simply copy it from below.
-
-```yaml
-# ./.github/workflows/04-update-fleet-infra.yaml
-name: Update Fleet-Infra
-on:
- push:
- branches:
- - 'main'
-
-jobs:
- run:
- name: Push Update
- runs-on: ubuntu-latest
- steps:
- - name: Prepare
- id: prep
- run: |
- VERSION=${GITHUB_SHA::8}
- if [[ $GITHUB_REF == refs/tags/* ]]; then
- VERSION=${GITHUB_REF/refs\/tags\//}
- fi
- echo ::set-output name=BUILD_DATE::$(date -u +'%Y-%m-%dT%H:%M:%SZ')
- echo ::set-output name=VERSION::${VERSION}
-
- - name: Checkout repo
- uses: actions/checkout@v2
-
- - name: Update manifests
- run: ./update-k8s.sh $GITHUB_SHA
-
- - name: Push directory to another repository
- uses: cpina/github-action-push-to-another-repository@v1.2
-
- env:
- API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}
- with:
- source-directory: 'flux-config'
- destination-github-username: 'kingdonb'
- destination-repository-name: 'fleet-infra'
- target-branch: 'deploy'
- user-email: kingdon+bot@weave.works
- commit-message: "[ci skip] deploy from ${{ steps.prep.outputs.VERSION }}"
-```
-
-This is [Push directory to another repository]. This is especially useful because Flux v2 is made to work with more than one GitRepository.
-
-If you must use a mono-repo, consider adding a deploy branch to it! There is no need for branches in the same repo to always share a parent and intersect again at a merge point.
-
-A mono-repo can be counter-productive for performance and will create bottlenecks for Flux, as large commits will take longer to clone, and therefore to reconcile. Ignoring with `.sourceignore` or `spec.ignore` will unfortunately not help much with this. Some limitations can only be overcome by changing the data structure.
-
-The `flux-system` is in the `main` branch of `kingdonb/fleet-infra`, as is the default. We prepared in advance, an empty commit with no parent in the same repository, on the `deploy` branch, so that this checkout would begin with an empty workspace that `ci/rake.sh` could copy the `output/` of Jsonnet into.
-
-```bash
-git checkout --orphan deploy
-git reset --hard
-git commit --allow-empty -m'initial empty commit'
-git push origin deploy
-```
-
-This is not technically regressive when compared to the behavior of Flux v1's `fluxcd.io/automated`, actually avoiding image pull depending on push instead to write the latest Git tag, externally and functionally identical to how Flux v1 did automation. Little else is good that we can say about it.
-
-It is a compatibility shim, to bridge the gap for Flux v1 users. If possible, users are encouraged to migrate to using timestamps, build numbers, or semver tags, that are all supported by some [Flux v2 image automation] features that are still in alpha at the time of this writing.
-
-Flux's new [Image Automation Controllers] are the new solution for Production use!
-
-### Adapting for Flux v2
-
-In Flux v2, with `ImagePolicy`, these examples may be adjusted to order tags by their `BUILD_DATE`, by adding more string information to the tags. Besides a build timestamp, we can also add branch name.
-
-Why not have it all: `${branch}-${sha}-${ts}` – this is the suggestion given in:
-
-* [Example of a build process with timestamp tagging].
-
-Example formats and alternative strings to use for tagging are at:
-
-* [Sortable image tags to use with automation].
-
-We don't expect you to follow these examples to the letter. They present an evolution and are meant to show some of the breadth of options that are available, rather than as prescriptive guidance.
-
-If you are on GitHub, and are struggling to get started using GitHub Actions, or maybe still waiting to make a move on your planned migration from Flux v1; we hope that these GitHub Actions examples can help Flux users to better bridge the gap between both versions.
-
-[flux2/discussions/802]: https://github.com/fluxcd/flux2/discussions/802
-[flux2/issues/543]: https://github.com/fluxcd/flux2/issues/543
-[image update guide]: /guides/image-update/
-[any old app]: https://github.com/kingdonb/any_old_app
-[Flux bootstrap guide]: /get-started/
-[String Substitution with sed -i]: #string-substitution-with-sed-i
-[Docker Build and Tag with Version]: #docker-build-and-tag-with-version
-[Jsonnet for YAML Document Rehydration]: #jsonnet-for-yaml-document-rehydration
-[Commit Across Repositories Workflow]: #commit-across-repositories-workflow
-[01-manifest-generate.yaml]: https://github.com/kingdonb/any_old_app/blob/main/.github/workflows/01-manifest-generate.yaml
-[some guidance has changed since Flux v1]: https://github.com/fluxcd/flux2/discussions/802#discussioncomment-320189
-[Sortable image tags]: /guides/sortable-image-tags/
-[Okteto's Getting Started Guides]: https://github.com/okteto/go-getting-started/blob/master/k8s.yml
-[Build and push Docker images]: https://github.com/marketplace/actions/build-and-push-docker-images
-[Prepare step]: https://github.com/fluxcd/kustomize-controller/blob/5da1fc043db4a1dc9fd3cf824adc8841b56c2fcd/.github/workflows/release.yml#L17-L25
-[02-docker-build.yaml]: https://github.com/kingdonb/any_old_app/blob/main/.github/workflows/02-docker-build.yaml
-[Docker Login Action]: https://github.com/marketplace/actions/docker-login
-[03-release-manifests.yaml]: https://github.com/kingdonb/any_old_app/blob/main/.github/workflows/03-release-manifests.yaml
-[actions/jsonnet-render]: https://github.com/marketplace/actions/jsonnet-render
-[letsbuilders/tanka-action]: https://github.com/letsbuilders/tanka-action
-[Add & Commit]: https://github.com/marketplace/actions/add-commit
-[External Variables]: https://jsonnet.org/ref/stdlib.html#ext_vars
-[example 10.1 library]: https://github.com/kingdonb/any_old_app/blob/release/0.10.1/manifests/example.libsonnet
-[any-old-app-deploy-kustomization.yaml]: https://github.com/kingdonb/csh-flux/commit/7c3f1e62e2a87a2157bc9a22db4f913cc30dc12e#diff-f6ebc9688433418f0724f3545c96c301f029fd5a15847b824eab04545e057e84
-[Tanka - Using Jsonnet tutorial]: https://tanka.dev/tutorial/jsonnet
-[Tanka - Parameterizing]: https://tanka.dev/tutorial/parameters
-[example 10.2 library excerpt]: https://github.com/kingdonb/any_old_app/blob/release/0.10.2/manifests/example.libsonnet#L47-L63
-[example 10.2 jsonnet]: https://github.com/kingdonb/any_old_app/blob/release/0.10.2/manifests/example.jsonnet
-[examples 0.10.2-all]: https://github.com/kingdonb/any_old_app/releases?after=0.10.2-alpha5
-[example 10.2 configmap]: https://github.com/kingdonb/any_old_app/blob/release/0.10.2/manifests/examples/configMap.yaml
-[anguslees/kustomize-libsonnet]: (https://github.com/anguslees/kustomize-libsonnet)
-[kubecfg yaml parser]: https://github.com/bitnami/kubecfg/blob/master/lib/kubecfg.libsonnet#L25
-[bitnami-labs/kube-libsonnet]: https://github.com/bitnami-labs/kube-libsonnet
-[example 10.3 jsonnet]: https://github.com/kingdonb/any_old_app/blob/release/0.10.3/manifests/example.jsonnet
-[Manual Gating]: https://docs.flagger.app/usage/webhooks#manual-gating
-[flux create tenant]: /cmd/flux_create_tenant
-[Flux 2 Multi-Tenancy Guide]: https://github.com/fluxcd/flux2-multi-tenancy
-[Mozilla SOPS]: /guides/mozilla-sops/
-[example 10.4 jsonnet]: https://github.com/kingdonb/any_old_app/blob/release/0.10.4/manifests/example.jsonnet
-[anguslees example jsonnet]: https://github.com/anguslees/kustomize-libsonnet/blob/master/example.jsonnet
-[Kubernetes docs on Using Service Accounts]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-multiple-service-accounts
-[sops/issues/315]: https://github.com/mozilla/sops/issues/315
-[using various cloud providers]: /guides/mozilla-sops/#using-various-cloud-providers
-[Decrypt SOPS Secrets]: https://github.com/marketplace/actions/decrypt-sops-secrets
-[Sops Binary Installer]: https://github.com/marketplace/actions/sops-binary-installer
-[04-update-fleet-infra.yaml]: https://github.com/kingdonb/any_old_app/blob/main/.github/workflows/04-update-fleet-infra.yaml
-[Push directory to another repository]: https://github.com/marketplace/actions/push-directory-to-another-repository
-[Flux v2 image automation]: /guides/image-update/
-[Image Automation Controllers]: /components/image/controller/
-[Example of a build process with timestamp tagging]: /guides/sortable-image-tags/#example-of-a-build-process-with-timestamp-tagging
-[Sortable image tags to use with automation]: /guides/sortable-image-tags/#formats-and-alternatives
diff --git a/docs/use-cases/helm.md b/docs/use-cases/helm.md
deleted file mode 100644
index efc0e938..00000000
--- a/docs/use-cases/helm.md
+++ /dev/null
@@ -1,208 +0,0 @@
-# Flux for Helm Users
-
-Welcome Helm users!
-We think Flux's Helm Controller is the best way to do Helm according to GitOps principles, and we're dedicated to doing what we can to help you feel the same way.
-
-## What Does Flux add to Helm?
-
-Helm 3 was designed with both a client and an SDK, but no running software agents.
-This architecture intended anything outside of the client scope to be addressed by other tools in the ecosystem, which could then make use of Helm's SDK.
-
-Built on Kubernetes controller-runtime, Flux's Helm Controller is an example of a mature software agent that uses Helm's SDK to full effect.
-
-
-Flux's biggest addition to Helm is a structured declaration layer for your releases that automatically gets reconciled to your cluster based on your configured rules:
-
-- While the Helm client commands let you imperatively do things
-- Flux Helm Custom Resources let you declare what you want the Helm SDK to do automatically
-
-Additional benefits Flux adds to Helm include:
-
-- Managing / structuring multiple environments
-- A control loop, with configurable retry logic
-- Automated drift detection between the desired and actual state of your operations
-- Automated responses to that drift, including reconciliation, notifications, and unified logging
-
-## Getting Started
-
-The simplest way to explain is by example.
-Lets translate imperative Helm commands to Flux Helm Controller Custom Resources:
-
-Helm client:
-
-```console
-helm repo add traefik https://helm.traefik.io/traefik
-helm install my-traefik traefik/traefik \
- --version 9.18.2 \
- --namespace traefik
-```
-
-Flux client:
-
-```console
-flux create source helm traefik --url https://helm.traefik.io/traefik
-flux create helmrelease --chart my-traefik \
- --source HelmRepository/traefik \
- --chart-version 9.18.2 \
- --namespace traefik
-```
-
-The main difference is Flux client will not imperatively create resources in the cluster.
-Instead these commands create Custom Resource *files*, which are committed to version control as instructions only (note: you may use the `--export` flag to manage any file edits with finer grained control before pushing to version control).
-Separately, the Flux Helm Controller software agent automatically reconciles these instructions with the running state of your cluster based on your configured rules.
-
-Lets check out what the Custom Resoruce instruction files look like:
-
-```yaml
-# /flux/boot/traefik/helmrepo.yaml
-apiVersion: source.toolkit.fluxcd.io/v1beta1
-kind: HelmRepository
-metadata:
- name: traefik
- namespace: traefik
-spec:
- interval: 1m0s
- url: https://helm.traefik.io/traefik
-```
-
-```yaml
-# /flux/boot/traefik/helmrelease.yaml
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
- name: traefik
- namespace: traefik
-spec:
- chart:
- spec:
- chart: traefik
- sourceRef:
- kind: HelmRepository
- name: traefik
- version: 9.18.2
- interval: 1m0s
-```
-
-
-
-Once these are applied to your cluster, the Flux Helm Controller automatically uses the Helm SDK to do your bidding according to the rules you've set.
-
-Why is this important?
-If you or your team has ever collaborated with multiple engineers on one or more apps, and/or in more than one namespace or cluster, you probably have a good idea of how declarative, automatic reconciliation can help solve common problems.
-If not, or either way, you may want to check out this [short introduction to GitOps](https://youtu.be/r-upyR-cfDY).
-
-## Customizing Your Release
-
-While Helm charts are usually installable using default configurations, users will often customize charts with their preferred configuration by [overriding the default values](https://helm.sh/docs/intro/using_helm/#customizing-the-chart-before-installing).
-The Helm client allows this by imperatively specifying override values with `--set` on the command line, and in additional `--values` files. For example:
-
-```console
-helm install my-traefik traefik/traefik --set service.type=ClusterIP
-```
-
-and
-
-```console
-helm install my-traefik traefik/traefik --values ci/kind-values.yaml
-```
-
-where `ci/kind-values.yaml` contains:
-
-```yaml
-service:
- type: ClusterIP
-```
-
-Flux Helm Controller allows these same YAML values overrides on the `HelmRelease` CRD.
-These can be declared directly in `spec.values`:
-
-```yaml
-spec:
- values:
- service:
- type: ClusterIP
-```
-
-and defined in `spec.valuesFrom` as a list of `ConfigMap` and `Secret` resources from which to draw values, allowing reusability and/or greater security.
-See `HelmRelease` CRD [values overrides](https://toolkit.fluxcd.io/components/helm/helmreleases/#values-overrides) documentation for the latest spec.
-
-## Managing Secrets and ConfigMaps
-
-You may manage these `ConfigMap` and `Secret` resources any way you wish, but there are several benefits to managing these with the Flux Kustomize Controller.
-
-It is fairly straigtforward to use Kustomize `configMapGenerator` to [trigger a Helm release upgrade every time the encoded values change](https://toolkit.fluxcd.io/guides/helmreleases/#refer-to-values-in-configmaps-generated-with-kustomize).
-This common use case currently solveable in Helm by [adding specially crafted annotations](https://helm.sh/docs/howto/charts_tips_and_tricks/#automatically-roll-deployments) to a chart.
-The Flux Kustomize Controller method allows you to accomplish this on any chart without additional templated annotations.
-
-You may also use Kustomize Controller built-in [Mozilla SOPS integration](https://toolkit.fluxcd.io/components/kustomize/kustomization/#secrets-decryption) to securely manage your encrypted secrets stored in git.
-See the [Flux SOPS guide](https://toolkit.fluxcd.io/guides/mozilla-sops/) for step-by-step instructions through various use cases.
-
-## Automatic Release Upgrades
-
-If you want Helm Controller to automatically upgrade your releases when a new chart version is available in the release's referenced `HelmRepository`, you may specify a SemVer range (i.e. `>=4.0.0 <5.0.0`) instead of a fixed version.
-
-This is useful if your release should use a fixed MAJOR chart version, but want the latest MINOR or PATCH versions as they become available.
-
-For full SemVer range syntax, see `Masterminds/semver` [Checking Version Constraints](https://github.com/Masterminds/semver/blob/master/README.md#checking-version-constraints) documentation.
-
-## Automatic Uninstalls and Rollback
-
-The Helm Controller offers an extensive set of configuration options to remediate when a Helm release fails, using [spec.install.remediate](https://toolkit.fluxcd.io/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.InstallRemediation), [spec.upgrade.remediate](https://toolkit.fluxcd.io/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.UpgradeRemediation), [spec.rollback](https://toolkit.fluxcd.io/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.Rollback) and [spec.uninstall](https://toolkit.fluxcd.io/components/helm/api/#helm.toolkit.fluxcd.io/v2beta1.Uninstall).
-Features include the option to remediate with an uninstall after an upgrade failure, and the option to keep a failed release for debugging purposes when it has run out of retries.
-
-Here is an example for configuring automated uninstalls (for all available fields, consult the `InstallRemediation` and `Uninstall` API references linked above):
-
-```yaml
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
- name: my-release
- namespace: default
-spec:
- # ...omitted for brevity
- install:
- # Remediation configuration for when the Helm install
- # (or sequent Helm test) action fails
- remediation:
- # Number of retries that should be attempted on failures before
- # bailing, a negative integer equals to unlimited retries
- retries: -1
- # Configuration options for the Helm uninstall action
- uninstall:
- timeout: 5m
- disableHooks: false
- keepHistory: false
-```
-
-Here is an example of automated rollback configuration (for all available fields, consult the `UpgradeRemediation` and `Rollback` API references linked above):
-
-```yaml
-apiVersion: helm.toolkit.fluxcd.io/v2beta1
-kind: HelmRelease
-metadata:
- name: my-release
- namespace: default
-spec:
- # ...omitted for brevity
- upgrade:
- # Remediaton configuration for when an Helm upgrade action fails
- remediation:
- # Amount of retries to attempt after a failure,
- # setting this to 0 means no remedation will be
- # attempted
- retries: 5
- # Configuration options for the Helm rollback action
- rollback:
- timeout: 5m
- disableWait: false
- disableHooks: false
- recreate: false
- force: false
- cleanupOnFail: false
-```
-
-## Next Steps
-
-- [Guides > Manage Helm Releases](/guides/helmreleases/)
-- [Toolkit Components > Helm Controller](/components/helm/controller/)
-- [Migration > Migrate to the Helm Controller](/guides/helm-operator-migration/)
diff --git a/mkdocs.yml b/mkdocs.yml
deleted file mode 100644
index 0e4e5248..00000000
--- a/mkdocs.yml
+++ /dev/null
@@ -1,216 +0,0 @@
-site_name: Flux | GitOps Toolkit
-site_description: Open and extensible continuous delivery solution for Kubernetes
-site_author: The Flux project
-site_url: https://toolkit.fluxcd.io
-
-repo_name: fluxcd/flux2
-repo_url: https://github.com/fluxcd/flux2
-edit_uri: ""
-
-theme:
- name: material
- logo: _files/flux-icon@2x.png
- language: en
- palette:
- primary: blue
- accent: indigo
- custom_dir: mkdocs/
-
-docs_dir: docs
-
-extra_css:
- - _static/custom.css
-
-plugins:
- - search
-
-markdown_extensions:
- - admonition
- - codehilite:
- guess_lang: false
- - 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.tasklist
- - pymdownx.tilde
- - toc:
- permalink: true
-
-nav:
- - Introduction: index.md
- - Core Concepts: core-concepts/index.md
- - Get Started: get-started/index.md
- - Migration:
- - 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
- - Setup Notifications: guides/notifications.md
- - Setup Webhook Receivers: guides/webhook-receivers.md
- - Monitoring with Prometheus: guides/monitoring.md
- - Sealed Secrets: guides/sealed-secrets.md
- - Mozilla SOPS: guides/mozilla-sops.md
- - Automate image updates to Git: guides/image-update.md
- - Sortable image tags to use with automation: guides/sortable-image-tags.md
- - Use Cases:
- - Azure: use-cases/azure.md
- - GitHub Actions Manifest Generation: use-cases/gh-actions-manifest-generation.md
- - Helm: use-cases/helm.md
- - Toolkit Components:
- - Overview: components/index.md
- - Source Controller:
- - Overview: components/source/controller.md
- - GitRepository CRD: components/source/gitrepositories.md
- - HelmRepository CRD: components/source/helmrepositories.md
- - HelmChart CRD: components/source/helmcharts.md
- - Bucket CRD: components/source/buckets.md
- - Source API Reference: components/source/api.md
- - Kustomize Controller:
- - Overview: components/kustomize/controller.md
- - Kustomization CRD: components/kustomize/kustomization.md
- - Kustomize API Reference: components/kustomize/api.md
- - Helm Controller:
- - Overview: components/helm/controller.md
- - HelmRelease CRD: components/helm/helmreleases.md
- - Helm API Reference: components/helm/api.md
- - Notification Controller:
- - Overview: components/notification/controller.md
- - Event: components/notification/event.md
- - Provider CRD: components/notification/provider.md
- - Alert CRD: components/notification/alert.md
- - Receiver CRD: components/notification/receiver.md
- - Notification API Reference: components/notification/api.md
- - Image Automation Controllers:
- - Overview: components/image/controller.md
- - ImageRepository CRD: components/image/imagerepositories.md
- - ImagePolicy CRD: components/image/imagepolicies.md
- - ImageUpdateAutomation CRD: components/image/imageupdateautomations.md
- - Automation API Reference: components/image/automation-api.md
- - Flux CLI:
- - Overview: cmd/flux.md
- - Bootstrap: cmd/flux_bootstrap.md
- - Bootstrap github: cmd/flux_bootstrap_github.md
- - Bootstrap gitlab: cmd/flux_bootstrap_gitlab.md
- - Check: cmd/flux_check.md
- - Create: cmd/flux_create.md
- - Create kustomization: cmd/flux_create_kustomization.md
- - Create helmrelease: cmd/flux_create_helmrelease.md
- - Create source: cmd/flux_create_source.md
- - Create source git: cmd/flux_create_source_git.md
- - Create source helm: cmd/flux_create_source_helm.md
- - Create source bucket: cmd/flux_create_source_bucket.md
- - Create alert provider: cmd/flux_create_alert-provider.md
- - Create alert: cmd/flux_create_alert.md
- - Create receiver: cmd/flux_create_receiver.md
- - Create image: cmd/flux_create_image.md
- - Create image policy: cmd/flux_create_image_policy.md
- - Create image repository: cmd/flux_create_image_repository.md
- - Create image update: cmd/flux_create_image_update.md
- - Create tenant: cmd/flux_create_tenant.md
- - Create secret: cmd/flux_create_secret.md
- - Create secret git: cmd/flux_create_secret_git.md
- - Create secret helm: cmd/flux_create_secret_helm.md
- - Create secret tls: cmd/flux_create_secret_tls.md
- - Delete: cmd/flux_delete.md
- - Delete kustomization: cmd/flux_delete_kustomization.md
- - Delete helmrelease: cmd/flux_delete_helmrelease.md
- - Delete source: cmd/flux_delete_source.md
- - Delete source git: cmd/flux_delete_source_git.md
- - Delete source helm: cmd/flux_delete_source_helm.md
- - Delete source bucket: cmd/flux_delete_source_bucket.md
- - Delete image: cmd/flux_delete_image.md
- - Delete image policy: cmd/flux_delete_image_policy.md
- - Delete image repository: cmd/flux_delete_image_repository.md
- - Delete image update: cmd/flux_delete_image_update.md
- - Export: cmd/flux_export.md
- - Export kustomization: cmd/flux_export_kustomization.md
- - Export helmrelease: cmd/flux_export_helmrelease.md
- - Export source: cmd/flux_export_source.md
- - Export source git: cmd/flux_export_source_git.md
- - Export source helm: cmd/flux_export_source_helm.md
- - Export source bucket: cmd/flux_export_source_bucket.md
- - Export alert provider: cmd/flux_export_alert-provider.md
- - Export alert: cmd/flux_export_alert.md
- - Export receiver: cmd/flux_export_receiver.md
- - Export image: cmd/flux_export_image.md
- - Export image policy: cmd/flux_export_image_policy.md
- - Export image repository: cmd/flux_export_image_repository.md
- - Export image update: cmd/flux_export_image_update.md
- - Get: cmd/flux_get.md
- - Get all: cmd/flux_get_all.md
- - Get kustomizations: cmd/flux_get_kustomizations.md
- - Get helmreleases: cmd/flux_get_helmreleases.md
- - Get sources: cmd/flux_get_sources.md
- - Get sources all: cmd/flux_get_sources_all.md
- - Get sources git: cmd/flux_get_sources_git.md
- - Get sources helm: cmd/flux_get_sources_helm.md
- - Get sources chart: cmd/flux_get_sources_chart.md
- - Get sources bucket: cmd/flux_get_sources_bucket.md
- - Get alert provider: cmd/flux_get_alert-provider.md
- - Get alerts: cmd/flux_get_alerts.md
- - Get alert providers: cmd/flux_get_alert-providers.md
- - Get receivers: cmd/flux_get_receivers.md
- - Get images: cmd/flux_get_images.md
- - Get images all: cmd/flux_get_images_all.md
- - Get images policy: cmd/flux_get_images_policy.md
- - 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
- - Resume source: cmd/flux_resume_source.md
- - Resume source git: cmd/flux_resume_source_git.md
- - Resume source helm: cmd/flux_resume_source_helm.md
- - Resume source chart: cmd/flux_resume_source_chart.md
- - Resume source bucket: cmd/flux_resume_source_bucket.md
- - Resume alert provider: cmd/flux_resume_alert-provider.md
- - Resume alert: cmd/flux_resume_alert.md
- - Resume receiver: cmd/flux_resume_receiver.md
- - Resume image: cmd/flux_resume_image.md
- - Resume image repository: cmd/flux_resume_image_repository.md
- - Resume image update: cmd/flux_resume_image_update.md
- - Suspend: cmd/flux_suspend.md
- - Suspend kustomization: cmd/flux_suspend_kustomization.md
- - Suspend helmrelease: cmd/flux_suspend_helmrelease.md
- - Suspend source: cmd/flux_suspend_source.md
- - Suspend source git: cmd/flux_suspend_source_git.md
- - Suspend source helm: cmd/flux_suspend_source_helm.md
- - Suspend source chart: cmd/flux_suspend_source_chart.md
- - Suspend source bucket: cmd/flux_suspend_source_bucket.md
- - Suspend alert provider: cmd/flux_suspend_alert-provider.md
- - Suspend alert: cmd/flux_suspend_alert.md
- - Suspend receiver: cmd/flux_suspend_receiver.md
- - Suspend image: cmd/flux_suspend_image.md
- - Suspend image repository: cmd/flux_suspend_image_repository.md
- - Suspend image update: cmd/flux_suspend_image_update.md
- - Reconcile: cmd/flux_reconcile.md
- - Reconcile kustomization: cmd/flux_reconcile_kustomization.md
- - Reconcile helmrelease: cmd/flux_reconcile_helmrelease.md
- - Reconcile source: cmd/flux_reconcile_source.md
- - Reconcile source git: cmd/flux_reconcile_source_git.md
- - Reconcile source helm: cmd/flux_reconcile_source_helm.md
- - Reconcile source bucket: cmd/flux_reconcile_source_bucket.md
- - Reconcile image: cmd/flux_reconcile_image.md
- - Reconcile image repository: cmd/flux_reconcile_image_repository.md
- - Reconcile image update: cmd/flux_reconcile_image_update.md
- - Uninstall: cmd/flux_uninstall.md
- - Dev Guides:
- - Watching for source changes: dev-guides/source-watcher.md
- - Advanced debugging: dev-guides/debugging.md
- - Roadmap: roadmap/index.md
- - Contributing: contributing/index.md
- - FAQ: faq/index.md
diff --git a/mkdocs/main.html b/mkdocs/main.html
deleted file mode 100644
index eb0ab453..00000000
--- a/mkdocs/main.html
+++ /dev/null
@@ -1,32 +0,0 @@
-{% extends "base.html" %}
-
-{% block extrahead %}
-
-
-{% if page and page.meta and page.meta.title %}
-
-{% elif page and page.title and not page.is_homepage %}
-
-{% else %}
-
-{% endif %}
-
-
-
-
-
-
-
-
-{% if page and page.meta and page.meta.title %}
-
-{% elif page and page.title and not page.is_homepage %}
-
-{% else %}
-
-{% endif %}
-
-
-
-
-{% endblock %}