Integrate feedback from hiddeco

Signed-off-by: Alexander Berger <alex-berger@gmx.ch>
This commit is contained in:
Alexander Berger 2021-04-19 16:53:29 +02:00
parent a6cc150aa6
commit defee3d26a
8 changed files with 200 additions and 68 deletions

View File

@ -6,7 +6,7 @@ on:
push:
branches:
- main
- "feature/**"
jobs:
kind:
runs-on: ubuntu-latest
@ -513,6 +513,7 @@ jobs:
fi
kubectl -n helm-system delete -f config/testdata/post-renderer-kustomize
- name: Boostrap CRDs Upgrade Tests
if: ${{ startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/') }}
run: |
REF=${{ github.ref }}
if echo "$REF" | grep 'refs/tags/'; then
@ -532,10 +533,12 @@ jobs:
kubectl -n default apply -f config/testdata/crds-upgrade/init
kubectl -n default wait helmreleases/crds-upgrade-test --for=condition=ready --timeout=2m
- name: CRDs Upgrade Test Create
if: ${{ startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/') }}
run: |
kubectl -n default apply -f config/testdata/crds-upgrade/create
kubectl -n default wait helmreleases/crds-upgrade-test --for=condition=ready --timeout=2m
- name: CRDs Upgrade Test CreateReplace
if: ${{ startsWith(github.ref, 'refs/tags/') || startsWith(github.ref, 'refs/heads/') }}
run: |
kubectl -n default apply -f config/testdata/crds-upgrade/create-replace
kubectl -n default wait helmreleases/crds-upgrade-test --for=condition=ready --timeout=2m

View File

@ -338,6 +338,27 @@ type Install struct {
// +optional
SkipCRDs bool `json:"skipCRDs,omitempty"`
// CRDs upgrade CRDs from the Helm Chart's crds directory according
// to the CRD upgrade policy provided here. Valid values are `Skip`,
// `Create` or `CreateReplace`. Default is `Create` and if omitted
// CRDs are installed but not updated.
//
// Skip: do neither install nor replace (update) any CRDs.
//
// Create: new CRDs are created, existing CRDs are neither updated nor deleted.
//
// CreateReplace: new CRDs are created, existing CRDs are updated (replaced)
// but not deleted.
//
// By default, CRDs are applied (installed) during Helm install action.
// With this option users can opt-in to CRD replace existing CRDs on Helm
// install actions, which is not (yet) natively supported by Helm.
// https://helm.sh/docs/chart_best_practices/custom_resource_definitions.
//
// +kubebuilder:validation:Enum=Skip;Create;CreateReplace
// +optional
CRDs CRDsPolicy `json:"crds,omitempty"`
// CreateNamespace tells the Helm install action to create the
// HelmReleaseSpec.TargetNamespace if it does not exist yet.
// On uninstall, the namespace will not be garbage collected.
@ -431,17 +452,19 @@ func (in InstallRemediation) RetriesExhausted(hr HelmRelease) bool {
return in.Retries >= 0 && in.GetFailureCount(hr) > int64(in.Retries)
}
// CRDsUpgradePolicy defines the upgrade approach to use for CRDs when upgrading
// a HelmRelease.
type CRDsChangePolicy string
// CRDsPolicy defines the install/upgrade approach to use for CRDs when
// installing or upgrading a HelmRelease.
type CRDsPolicy string
const (
// Create CRDs which do not already exist, do not replace already existing CRDs
// Skip CRDs do neither install nor replace (update) any CRDs.
Skip CRDsPolicy = "Skip"
// Create CRDs which do not already exist, do not replace (update) already existing
// CRDs and keep (do not delete) CRDs which no longer exist in the current release.
Create CRDsPolicy = "Create"
// Create CRDs which do not already exist, Replace (update) already existing CRDs
// and keep (do not delete) CRDs which no longer exist in the current release.
Create CRDsChangePolicy = "Create"
// Create CRDs which do not already exist, Replace already existing CRDs
// and keep (do not delete) CRDs which no longer exist in the current release.
CreateReplace CRDsChangePolicy = "CreateReplace"
CreateReplace CRDsPolicy = "CreateReplace"
)
// Upgrade holds the configuration for Helm upgrade actions for this
@ -487,10 +510,12 @@ type Upgrade struct {
// +optional
CleanupOnFail bool `json:"cleanupOnFail,omitempty"`
// UpgradeCRDs upgrade CRDs from the Helm Chart's crds directory according
// to the CRD upgrade policy provided here. Valid values are `Create` or
// `CreateReplace`. If omitted (the default) CRDs
// are not upgraded.
// CRDs upgrade CRDs from the Helm Chart's crds directory according
// to the CRD upgrade policy provided here. Valid values are `Skip`,
// `Create` or `CreateReplace`. Default is `Skip` and if omitted
// CRDs are neither installed nor upgraded.
//
// Skip: do neither install nor replace (update) any CRDs.
//
// Create: new CRDs are created, existing CRDs are neither updated nor deleted.
//
@ -501,9 +526,9 @@ type Upgrade struct {
// option users can opt-in to CRD upgrade, which is not (yet) natively supported by Helm.
// https://helm.sh/docs/chart_best_practices/custom_resource_definitions.
//
// +kubebuilder:validation:Enum=Create;CreateReplace
// +kubebuilder:validation:Enum=Skip;Create;CreateReplace
// +optional
UpgradeCRDs CRDsChangePolicy `json:"upgradeCRDs,omitempty"`
CRDs CRDsPolicy `json:"crds,omitempty"`
}
// GetTimeout returns the configured timeout for the Helm upgrade action, or the

View File

@ -142,6 +142,24 @@ spec:
description: Install holds the configuration for Helm install actions
for this HelmRelease.
properties:
crds:
description: "CRDs upgrade CRDs from the Helm Chart's crds directory
according to the CRD upgrade policy provided here. Valid values
are `Skip`, `Create` or `CreateReplace`. Default is `Create`
and if omitted CRDs are installed but not updated. \n Skip:
do neither install nor replace (update) any CRDs. \n Create:
new CRDs are created, existing CRDs are neither updated nor
deleted. \n CreateReplace: new CRDs are created, existing CRDs
are updated (replaced) but not deleted. \n By default, CRDs
are applied (installed) during Helm install action. With this
option users can opt-in to CRD replace existing CRDs on Helm
install actions, which is not (yet) natively supported by Helm.
https://helm.sh/docs/chart_best_practices/custom_resource_definitions."
enum:
- Skip
- Create
- CreateReplace
type: string
createNamespace:
description: CreateNamespace tells the Helm install action to
create the HelmReleaseSpec.TargetNamespace if it does not exist
@ -459,6 +477,23 @@ spec:
description: CleanupOnFail allows deletion of new resources created
during the Helm upgrade action when it fails.
type: boolean
crds:
description: "CRDs upgrade CRDs from the Helm Chart's crds directory
according to the CRD upgrade policy provided here. Valid values
are `Skip`, `Create` or `CreateReplace`. Default is `Skip` and
if omitted CRDs are neither installed nor upgraded. \n Skip:
do neither install nor replace (update) any CRDs. \n Create:
new CRDs are created, existing CRDs are neither updated nor
deleted. \n CreateReplace: new CRDs are created, existing CRDs
are updated (replaced) but not deleted. \n By default, CRDs
are not applied during Helm upgrade action. With this option
users can opt-in to CRD upgrade, which is not (yet) natively
supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions."
enum:
- Skip
- Create
- CreateReplace
type: string
disableHooks:
description: DisableHooks prevents hooks from running during the
Helm upgrade action.
@ -515,20 +550,6 @@ spec:
operation (like Jobs for hooks) during the performance of a
Helm upgrade action. Defaults to 'HelmReleaseSpec.Timeout'.
type: string
upgradeCRDs:
description: "UpgradeCRDs upgrade CRDs from the Helm Chart's crds
directory according to the CRD upgrade policy provided here.
Valid values are `Create` or `CreateReplace`. If omitted (the
default) CRDs are not upgraded. \n Create: new CRDs are created,
existing CRDs are neither updated nor deleted. \n CreateReplace:
new CRDs are created, existing CRDs are updated (replaced) but
not deleted. \n By default, CRDs are not applied during Helm
upgrade action. With this option users can opt-in to CRD upgrade,
which is not (yet) natively supported by Helm. https://helm.sh/docs/chart_best_practices/custom_resource_definitions."
enum:
- Create
- CreateReplace
type: string
type: object
values:
description: Values holds the values for this Helm release.

View File

@ -15,7 +15,7 @@ spec:
namespace: default
interval: 1m
upgrade:
upgradeCRDs: CreateReplace
crds: CreateReplace
values:
a: v2beta1
b: v2beta2

View File

@ -15,7 +15,7 @@ spec:
namespace: default
interval: 1m
upgrade:
upgradeCRDs: Create
crds: Create
values:
a: v2beta1
b: v2beta1

View File

@ -351,14 +351,15 @@ HelmReleaseStatus
</table>
</div>
</div>
<h3 id="helm.toolkit.fluxcd.io/v2beta1.CRDsChangePolicy">CRDsChangePolicy
<h3 id="helm.toolkit.fluxcd.io/v2beta1.CRDsPolicy">CRDsPolicy
(<code>string</code> alias)</h3>
<p>
(<em>Appears on:</em>
<a href="#helm.toolkit.fluxcd.io/v2beta1.Install">Install</a>,
<a href="#helm.toolkit.fluxcd.io/v2beta1.Upgrade">Upgrade</a>)
</p>
<p>CRDsUpgradePolicy defines the upgrade approach to use for CRDs when upgrading
a HelmRelease.</p>
<p>CRDsPolicy defines the install/upgrade approach to use for CRDs when
installing or upgrading a HelmRelease.</p>
<h3 id="helm.toolkit.fluxcd.io/v2beta1.CrossNamespaceObjectReference">CrossNamespaceObjectReference
</h3>
<p>
@ -1219,6 +1220,31 @@ CRDs are installed if not already present.</p>
</tr>
<tr>
<td>
<code>crds</code><br>
<em>
<a href="#helm.toolkit.fluxcd.io/v2beta1.CRDsPolicy">
CRDsPolicy
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>CRDs upgrade CRDs from the Helm Chart&rsquo;s crds directory according
to the CRD upgrade policy provided here. Valid values are <code>Skip</code>,
<code>Create</code> or <code>CreateReplace</code>. Default is <code>Create</code> and if omitted
CRDs are installed but not updated.</p>
<p>Skip: do neither install nor replace (update) any CRDs.</p>
<p>Create: new CRDs are created, existing CRDs are neither updated nor deleted.</p>
<p>CreateReplace: new CRDs are created, existing CRDs are updated (replaced)
but not deleted.</p>
<p>By default, CRDs are applied (installed) during Helm install action.
With this option users can opt-in to CRD replace existing CRDs on Helm
install actions, which is not (yet) natively supported by Helm.
<a href="https://helm.sh/docs/chart_best_practices/custom_resource_definitions">https://helm.sh/docs/chart_best_practices/custom_resource_definitions</a>.</p>
</td>
</tr>
<tr>
<td>
<code>createNamespace</code><br>
<em>
bool
@ -1804,19 +1830,20 @@ upgrade action when it fails.</p>
</tr>
<tr>
<td>
<code>upgradeCRDs</code><br>
<code>crds</code><br>
<em>
<a href="#helm.toolkit.fluxcd.io/v2beta1.CRDsChangePolicy">
CRDsChangePolicy
<a href="#helm.toolkit.fluxcd.io/v2beta1.CRDsPolicy">
CRDsPolicy
</a>
</em>
</td>
<td>
<em>(Optional)</em>
<p>UpgradeCRDs upgrade CRDs from the Helm Chart&rsquo;s crds directory according
to the CRD upgrade policy provided here. Valid values are <code>Create</code> or
<code>CreateReplace</code>. If omitted (the default) CRDs
are not upgraded.</p>
<p>CRDs upgrade CRDs from the Helm Chart&rsquo;s crds directory according
to the CRD upgrade policy provided here. Valid values are <code>Skip</code>,
<code>Create</code> or <code>CreateReplace</code>. Default is <code>Skip</code> and if omitted
CRDs are neither installed nor upgraded.</p>
<p>Skip: do neither install nor replace (update) any CRDs.</p>
<p>Create: new CRDs are created, existing CRDs are neither updated nor deleted.</p>
<p>CreateReplace: new CRDs are created, existing CRDs are updated (replaced)
but not deleted.</p>

View File

@ -199,6 +199,27 @@ type Install struct {
// +optional
SkipCRDs bool `json:"skipCRDs,omitempty"`
// CRDs upgrade CRDs from the Helm Chart's crds directory according
// to the CRD upgrade policy provided here. Valid values are `Skip`,
// `Create` or `CreateReplace`. Default is `Create` and if omitted
// CRDs are installed but not updated.
//
// Skip: do neither install nor replace (update) any CRDs.
//
// Create: new CRDs are created, existing CRDs are neither updated nor deleted.
//
// CreateReplace: new CRDs are created, existing CRDs are updated (replaced)
// but not deleted.
//
// By default, CRDs are applied (installed) during Helm install action.
// With this option users can opt-in to CRD replace existing CRDs on Helm
// install actions, which is not (yet) natively supported by Helm.
// https://helm.sh/docs/chart_best_practices/custom_resource_definitions.
//
// +kubebuilder:validation:Enum=Skip;Create;CreateReplace
// +optional
CRDs CRDsPolicy `json:"crds,omitempty"`
// CreateNamespace tells the Helm install action to create the
// HelmReleaseSpec.TargetNamespace if it does not exist yet.
// On uninstall, the namespace will not be garbage collected.
@ -269,10 +290,12 @@ type Upgrade struct {
// +optional
CleanupOnFail bool `json:"cleanupOnFail,omitempty"`
// UpgradeCRDs upgrade CRDs from the Helm Chart's crds directory according
// to the CRD upgrade policy provided here. Valid values are `Create` or
// `CreateReplace`. If omitted (the default) CRDs
// are not upgraded.
// CRDs upgrade CRDs from the Helm Chart's crds directory according
// to the CRD upgrade policy provided here. Valid values are `Skip`,
// `Create` or `CreateReplace`. Default is `Skip` and if omitted
// CRDs are neither installed nor upgraded.
//
// Skip: do neither install nor replace (update) any CRDs.
//
// Create: new CRDs are created, existing CRDs are neither updated nor deleted.
//
@ -283,9 +306,9 @@ type Upgrade struct {
// option users can opt-in to CRD upgrade, which is not (yet) natively supported by Helm.
// https://helm.sh/docs/chart_best_practices/custom_resource_definitions.
//
// +kubebuilder:validation:Enum=Create;CreateReplace
// +kubebuilder:validation:Enum=Skip;Create;CreateReplace
// +optional
UpgradeCRDs CRDsChangePolicy `json:"upgradeCRDs,omitempty"`
CRDs CRDsPolicy `json:"crds,omitempty"`
}
// UpgradeRemediation holds the configuration for Helm upgrade remediation.
@ -1144,9 +1167,11 @@ Chart as suggested by the
However, if you have to integrate and use many existing (upstream) Helm Charts, not being able to
upgrade the CRDs via FluxCD `HelmRelease` objects might become a cumbersome limitation within your GitOps
workflow. Therefore, FluxCD allows you to opt-in to upgrading CRDs by setting the `UpgradeCRDs` policy on
the `HelmRelease.spec.upgrade` object. The following UpgradeCRDs policies are supported:
workflow. Therefore, FluxCD allows you to opt-in to upgrading CRDs by setting the `crds` policy on
the `HelmRelease.spec.install` and `HelmRelease.spec.upgrade` objects.
The following UpgradeCRDs policies are supported:
- `Skip` Skip CRDs do neither install nor replace (update) any CRDs.
- `Create` Only create new CRDs which doe not yet exist, neither update nor delete any existing CRDs.
- `CreateReplace` Create new CRDs, update (replace) existing ones, but do **not** delete CRDs which
no longer exist in the current helm release.
@ -1170,8 +1195,10 @@ spec:
name: my-operator-repo
namespace: default
interval: 1m
install:
crds: CreateReplace
upgrade:
upgradeCRDs: CreateReplace
crds: CreateReplace
```
## Status

View File

@ -109,17 +109,40 @@ func (r *Runner) Install(hr v2.HelmRelease, chart *chart.Chart, values chartutil
install.DisableHooks = hr.Spec.GetInstall().DisableHooks
install.DisableOpenAPIValidation = hr.Spec.GetInstall().DisableOpenAPIValidation
install.Replace = hr.Spec.GetInstall().Replace
install.SkipCRDs = hr.Spec.GetInstall().SkipCRDs
var legacyCRDsPolicy v2.CRDsPolicy = v2.Create
if hr.Spec.GetInstall().SkipCRDs {
legacyCRDsPolicy = v2.Skip
}
cRDsPolicy, err := r.validateCRDsPolicy(hr.Spec.GetInstall().CRDs, legacyCRDsPolicy)
if err != nil {
return nil, wrapActionErr(r.logBuffer, err)
}
if (cRDsPolicy != v2.Skip && legacyCRDsPolicy == v2.Skip) || (cRDsPolicy == v2.Skip && legacyCRDsPolicy != v2.Skip) {
return nil, wrapActionErr(r.logBuffer,
fmt.Errorf("Contradicting CRDs installation settings, skipCRDs is set to %t and crds is set to %s", hr.Spec.GetInstall().SkipCRDs, cRDsPolicy))
}
if cRDsPolicy == v2.Skip || cRDsPolicy == v2.CreateReplace {
install.SkipCRDs = true
}
install.Devel = true
renderer, err := postRenderers(hr)
if err != nil {
return nil, err
return nil, wrapActionErr(r.logBuffer, err)
}
install.PostRenderer = renderer
if hr.Spec.TargetNamespace != "" {
install.CreateNamespace = hr.Spec.GetInstall().CreateNamespace
}
if cRDsPolicy == v2.CreateReplace {
crds := chart.CRDObjects()
if len(crds) > 0 {
if err := r.applyCRDs(cRDsPolicy, hr, chart); err != nil {
return nil, wrapActionErr(r.logBuffer, err)
}
}
}
rel, err := install.Run(chart, values.AsMap())
return rel, wrapActionErr(r.logBuffer, err)
}
@ -147,14 +170,14 @@ func (r *Runner) Upgrade(hr v2.HelmRelease, chart *chart.Chart, values chartutil
}
upgrade.PostRenderer = renderer
// If user opted-in to upgrade CRDs, upgrade them first.
cRDsChangePolicy, err := r.validateCRDsChangePolicy(hr.Spec.GetUpgrade().UpgradeCRDs)
cRDsPolicy, err := r.validateCRDsPolicy(hr.Spec.GetUpgrade().CRDs, v2.Skip)
if err != nil {
return nil, wrapActionErr(r.logBuffer, err)
}
if cRDsChangePolicy != "" {
if cRDsPolicy != v2.Skip {
crds := chart.CRDObjects()
if len(crds) > 0 {
if err := r.upgradeCRDs(cRDsChangePolicy, hr, chart); err != nil {
if err := r.applyCRDs(cRDsPolicy, hr, chart); err != nil {
return nil, wrapActionErr(r.logBuffer, err)
}
}
@ -163,19 +186,20 @@ func (r *Runner) Upgrade(hr v2.HelmRelease, chart *chart.Chart, values chartutil
return rel, wrapActionErr(r.logBuffer, err)
}
func (r *Runner) validateCRDsChangePolicy(policy v2.CRDsChangePolicy) (v2.CRDsChangePolicy, error) {
func (r *Runner) validateCRDsPolicy(policy v2.CRDsPolicy, defaultValue v2.CRDsPolicy) (v2.CRDsPolicy, error) {
switch policy {
case "":
return defaultValue, nil
case v2.Skip:
break
case v2.Create:
break
case v2.CreateReplace:
break
default:
return policy, errors.New(
fmt.Sprintf("Invalid CRD upgrade policy '%s' defined in field upgradeCRDs, valid values are '%s' or '%s'",
policy, v2.Create, v2.CreateReplace,
))
return policy, fmt.Errorf("invalid CRD upgrade policy '%s' defined in field upgradeCRDs, valid values are '%s', '%s' or '%s'",
policy, v2.Skip, v2.Create, v2.CreateReplace,
)
}
return policy, nil
}
@ -187,9 +211,9 @@ func (*rootScoped) Name() meta.RESTScopeName {
}
// This has been adapte from https://github.com/helm/helm/blob/v3.5.4/pkg/action/install.go#L127
func (r *Runner) upgradeCRDs(policy v2.CRDsChangePolicy, hr v2.HelmRelease, chart *chart.Chart) error {
func (r *Runner) applyCRDs(policy v2.CRDsPolicy, hr v2.HelmRelease, chart *chart.Chart) error {
cfg := r.config
cfg.Log("upgrade CRDs with policy %s", policy)
cfg.Log("apply CRDs with policy %s", policy)
// Collect all CRDs from all files in `crds` directory.
allCrds := make(kube.ResourceList, 0)
for _, obj := range chart.CRDObjects() {
@ -202,7 +226,10 @@ func (r *Runner) upgradeCRDs(policy v2.CRDsChangePolicy, hr v2.HelmRelease, char
allCrds = append(allCrds, res...)
}
totalItems := []*resource.Info{}
if policy == v2.Create {
switch policy {
case v2.Skip:
break
case v2.Create:
for i := range allCrds {
if rr, err := cfg.KubeClient.Create(allCrds[i : i+1]); err != nil {
crdName := allCrds[i].Name
@ -214,15 +241,16 @@ func (r *Runner) upgradeCRDs(policy v2.CRDsChangePolicy, hr v2.HelmRelease, char
}
continue
}
cfg.Log("failed to upgrade CRD %s: %s", crdName, err)
return errors.New(fmt.Sprintf("failed to upgrade CRD %s: %s", crdName, err))
cfg.Log("failed to create CRD %s: %s", crdName, err)
return errors.New(fmt.Sprintf("failed to create CRD %s: %s", crdName, err))
} else {
if rr != nil && rr.Created != nil {
totalItems = append(totalItems, rr.Created...)
}
}
}
} else if policy == v2.CreateReplace {
break
case v2.CreateReplace:
config, err := r.config.RESTClientGetter.ToRESTConfig()
if err != nil {
r.logBuffer.Log("Error while creating Kubernetes client config: %s", err)
@ -268,8 +296,8 @@ func (r *Runner) upgradeCRDs(policy v2.CRDsChangePolicy, hr v2.HelmRelease, char
}
// Send them to Kube
if rr, err := cfg.KubeClient.Update(original, allCrds, true); err != nil {
cfg.Log("failed to upgrade CRD %s", err)
return errors.New(fmt.Sprintf("failed to upgrade CRD %s", err))
cfg.Log("failed to apply CRD %s", err)
return errors.New(fmt.Sprintf("failed to apply CRD %s", err))
} else {
if rr != nil {
if rr.Created != nil {
@ -283,6 +311,7 @@ func (r *Runner) upgradeCRDs(policy v2.CRDsChangePolicy, hr v2.HelmRelease, char
}
}
}
break
}
if len(totalItems) > 0 {
// Invalidate the local cache, since it will not have the new CRDs