Add changes to Armada Charts CRD
Allow tracking of helm status, resource wait and tests. Change-Id: I9e4de81272c7471f326679d5c4b4427cbf836797 Signed-off-by: Ruslan Aliev <raliev@mirantis.com>
This commit is contained in:
parent
d557f99c8f
commit
0f3ef2a6c9
@ -172,10 +172,19 @@ type ArmadaChartStatus struct {
|
||||
// +optional
|
||||
UpgradeFailures int64 `json:"upgradeFailures,omitempty"`
|
||||
|
||||
// HelmStatus describes the status of helm release
|
||||
// +optional
|
||||
HelmStatus string `json:"helmStatus,omitempty"`
|
||||
|
||||
// Tested is the bool value whether the Helm Release was successfully
|
||||
// tested or not.
|
||||
// +optional
|
||||
Tested bool `json:"tested,omitempty"`
|
||||
|
||||
// WaitCompleted is the bool value whether the Helm Release resources were
|
||||
// waited for or not.
|
||||
// +optional
|
||||
WaitCompleted bool `json:"waitCompleted,omitempty"`
|
||||
}
|
||||
|
||||
// ArmadaChartProgressing resets any failures and registers progress toward
|
||||
@ -191,7 +200,9 @@ func ArmadaChartProgressing(ac ArmadaChart) ArmadaChart {
|
||||
}
|
||||
apimeta.SetStatusCondition(ac.GetStatusConditions(), newCondition)
|
||||
resetFailureCounts(&ac)
|
||||
resetWaitCompleted(&ac)
|
||||
resetTested(&ac)
|
||||
ac.Status.HelmStatus = "Unknown"
|
||||
return ac
|
||||
}
|
||||
|
||||
@ -238,6 +249,14 @@ func setTested(hr *ArmadaChart) {
|
||||
hr.Status.Tested = true
|
||||
}
|
||||
|
||||
func resetWaitCompleted(hr *ArmadaChart) {
|
||||
hr.Status.WaitCompleted = false
|
||||
}
|
||||
|
||||
func setWaitCompleted(hr *ArmadaChart) {
|
||||
hr.Status.WaitCompleted = true
|
||||
}
|
||||
|
||||
func NewForConfigOrDie(c *rest.Config) *rest.RESTClient {
|
||||
cs, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
@ -280,6 +299,13 @@ func setConfigDefaults(config *rest.Config) error {
|
||||
|
||||
//+kubebuilder:object:root=true
|
||||
//+kubebuilder:subresource:status
|
||||
// +kubebuilder:printcolumn:name="Namespace",type=string,JSONPath=`.metadata.namespace`
|
||||
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
|
||||
// +kubebuilder:printcolumn:name="Ready",type=boolean,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
|
||||
// +kubebuilder:printcolumn:name="Message",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].message`,priority=10
|
||||
// +kubebuilder:printcolumn:name="Helm Status",type=string,JSONPath=`.status.helmStatus`
|
||||
// +kubebuilder:printcolumn:name="Wait Completed",type=boolean,JSONPath=`.status.waitCompleted`
|
||||
// +kubebuilder:printcolumn:name="Tested",type=boolean,JSONPath=`.status.tested`
|
||||
|
||||
// ArmadaChart is the Schema for the armadacharts API
|
||||
type ArmadaChart struct {
|
||||
|
@ -14,7 +14,30 @@ spec:
|
||||
singular: armadachart
|
||||
scope: Namespaced
|
||||
versions:
|
||||
- name: v1
|
||||
- additionalPrinterColumns:
|
||||
- jsonPath: .metadata.namespace
|
||||
name: Namespace
|
||||
type: string
|
||||
- jsonPath: .metadata.creationTimestamp
|
||||
name: Age
|
||||
type: date
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].status
|
||||
name: Ready
|
||||
type: boolean
|
||||
- jsonPath: .status.conditions[?(@.type=="Ready")].message
|
||||
name: Message
|
||||
priority: 10
|
||||
type: string
|
||||
- jsonPath: .status.helmStatus
|
||||
name: Helm Status
|
||||
type: string
|
||||
- jsonPath: .status.waitCompleted
|
||||
name: Wait Completed
|
||||
type: boolean
|
||||
- jsonPath: .status.tested
|
||||
name: Tested
|
||||
type: boolean
|
||||
name: v1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ArmadaChart is the Schema for the armadacharts API
|
||||
@ -200,6 +223,9 @@ spec:
|
||||
description: HelmChart is the namespaced name of the HelmChart resource
|
||||
created by the controller for the ArmadaChart.
|
||||
type: string
|
||||
helmStatus:
|
||||
description: HelmStatus describes the status of helm release
|
||||
type: string
|
||||
installFailures:
|
||||
description: InstallFailures is the install failure count against
|
||||
the latest desired state. It is reset after a successful reconciliation.
|
||||
@ -234,6 +260,10 @@ spec:
|
||||
the latest desired state. It is reset after a successful reconciliation.
|
||||
format: int64
|
||||
type: integer
|
||||
waitCompleted:
|
||||
description: WaitCompleted is the bool value whether the Helm Release
|
||||
resources were waited for or not.
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
served: true
|
||||
|
@ -129,10 +129,10 @@ func (r *ArmadaChartReconciler) reconcile(ctx context.Context, ac armadav1.Armad
|
||||
// Prepare values
|
||||
var vals map[string]interface{}
|
||||
if ac.Spec.Values != nil {
|
||||
var vals_err error
|
||||
vals, vals_err = chartutil.ReadValues(ac.Spec.Values.Raw)
|
||||
if vals_err != nil {
|
||||
return armadav1.ArmadaChartNotReady(ac, "InitFailed", vals_err.Error()), ctrl.Result{}, vals_err
|
||||
var valsErr error
|
||||
vals, valsErr = chartutil.ReadValues(ac.Spec.Values.Raw)
|
||||
if valsErr != nil {
|
||||
return armadav1.ArmadaChartNotReady(ac, "InitFailed", valsErr.Error()), ctrl.Result{}, valsErr
|
||||
}
|
||||
}
|
||||
// Load chart from artifact
|
||||
@ -154,6 +154,10 @@ func (r *ArmadaChartReconciler) reconcileChart(ctx context.Context,
|
||||
if err != nil {
|
||||
return armadav1.ArmadaChartNotReady(ac, "InitFailed", err.Error()), err
|
||||
}
|
||||
restCfg, err := gettr.ToRESTConfig()
|
||||
if err != nil {
|
||||
return armadav1.ArmadaChartNotReady(ac, "InitFailed", err.Error()), err
|
||||
}
|
||||
|
||||
run, err := runner.NewRunner(gettr, ac.Namespace, log)
|
||||
if err != nil {
|
||||
@ -167,24 +171,19 @@ func (r *ArmadaChartReconciler) reconcileChart(ctx context.Context,
|
||||
return armadav1.ArmadaChartNotReady(ac, "GetLastReleaseFailed", "failed to get last release revision"), err
|
||||
}
|
||||
|
||||
testRel := func() (armadav1.ArmadaChart, error) {
|
||||
if ac.Spec.Test.Enabled && !ac.Status.Tested {
|
||||
log.Info("performing tests")
|
||||
rel, err = run.Test(ac)
|
||||
if err != nil {
|
||||
return armadav1.ArmadaChartNotReady(ac, "TestFailed", err.Error()), err
|
||||
}
|
||||
}
|
||||
return armadav1.ArmadaChartReady(ac), err
|
||||
}
|
||||
|
||||
if rel == nil {
|
||||
log.Info("helm install has started")
|
||||
rel, err = run.Install(ctx, ac, chrt, vals)
|
||||
} else {
|
||||
ac.Status.HelmStatus = string(rel.Info.Status)
|
||||
if updateStatusErr := r.patchStatus(ctx, &ac); updateStatusErr != nil {
|
||||
log.Error(updateStatusErr, "unable to update status after helm status update")
|
||||
return armadav1.ArmadaChartNotReady(ac, "UpdateStatusFailed", updateStatusErr.Error()), updateStatusErr
|
||||
}
|
||||
|
||||
if rel.Info.Status == release.StatusDeployed && !isUpdateRequired(ctx, rel, chrt, vals) {
|
||||
log.Info("no updates found, skipping upgrade")
|
||||
return testRel()
|
||||
return r.finalizeRelease(ctx, run, restCfg, ac)
|
||||
}
|
||||
|
||||
if rel.Info.Status.IsPending() {
|
||||
@ -221,25 +220,36 @@ func (r *ArmadaChartReconciler) reconcileChart(ctx context.Context,
|
||||
err = fmt.Errorf("failed to install/upgrade helm release: %s", err.Error())
|
||||
return armadav1.ArmadaChartNotReady(ac, "InstallUpgradeFailed", err.Error()), err
|
||||
}
|
||||
|
||||
if ac.Spec.Wait.Timeout > 0 && len(ac.Spec.Wait.Labels) > 0 {
|
||||
log.Info("preparing to wait resources")
|
||||
resCfg, err := gettr.ToRESTConfig()
|
||||
if err != nil {
|
||||
return armadav1.ArmadaChartNotReady(ac, "WaitFailed", err.Error()), err
|
||||
}
|
||||
err = r.waitRelease(ctx, resCfg, ac)
|
||||
if err != nil {
|
||||
return armadav1.ArmadaChartNotReady(ac, "WaitFailed", err.Error()), err
|
||||
}
|
||||
ac.Status.HelmStatus = string(rel.Info.Status)
|
||||
if err := r.patchStatus(ctx, &ac); err != nil {
|
||||
log.Error(err, "unable to update armadachart status")
|
||||
}
|
||||
|
||||
return testRel()
|
||||
return r.finalizeRelease(ctx, run, restCfg, ac)
|
||||
}
|
||||
|
||||
func (r *ArmadaChartReconciler) waitRelease(ctx context.Context, restCfg *rest.Config, hr armadav1.ArmadaChart) error {
|
||||
func (r *ArmadaChartReconciler) finalizeRelease(ctx context.Context, run *runner.Runner, restCfg *rest.Config, hr armadav1.ArmadaChart) (armadav1.ArmadaChart, error) {
|
||||
hr, err := r.waitRelease(ctx, restCfg, hr)
|
||||
if err != nil {
|
||||
return hr, err
|
||||
}
|
||||
|
||||
return r.testRelease(ctx, run, hr)
|
||||
}
|
||||
|
||||
func (r *ArmadaChartReconciler) waitRelease(ctx context.Context, restCfg *rest.Config, hr armadav1.ArmadaChart) (armadav1.ArmadaChart, error) {
|
||||
log := ctrl.LoggerFrom(ctx)
|
||||
|
||||
if hr.Status.WaitCompleted {
|
||||
log.Info("wait has been already completed")
|
||||
return hr, nil
|
||||
}
|
||||
|
||||
if hr.Spec.Wait.Timeout == 0 {
|
||||
log.Info("No Chart timeout specified, using default 900s")
|
||||
hr.Spec.Wait.Timeout = 900
|
||||
}
|
||||
|
||||
if hr.Spec.Wait.ArmadaChartWaitResources == nil {
|
||||
log.Info(fmt.Sprintf("there are no explicitly defined resources to wait: %s, using default ones", hr.Name))
|
||||
hr.Spec.Wait.ArmadaChartWaitResources = []armadav1.ArmadaChartWaitResource{{Type: "job"}, {Type: "pod"}}
|
||||
@ -288,12 +298,28 @@ func (r *ArmadaChartReconciler) waitRelease(ctx context.Context, restCfg *rest.C
|
||||
}
|
||||
err := opts.Wait(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
return hr, err
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("all resources are ready")
|
||||
return nil
|
||||
hr.Status.WaitCompleted = true
|
||||
if err := r.patchStatus(ctx, &hr); err != nil {
|
||||
return hr, err
|
||||
}
|
||||
|
||||
return hr, nil
|
||||
}
|
||||
|
||||
func (r *ArmadaChartReconciler) testRelease(ctx context.Context, run *runner.Runner, ac armadav1.ArmadaChart) (armadav1.ArmadaChart, error) {
|
||||
log := ctrl.LoggerFrom(ctx)
|
||||
if ac.Spec.Test.Enabled && !ac.Status.Tested {
|
||||
log.Info("performing tests")
|
||||
if _, err := run.Test(ac); err != nil {
|
||||
return armadav1.ArmadaChartNotReady(ac, "TestFailed", err.Error()), err
|
||||
}
|
||||
}
|
||||
return armadav1.ArmadaChartReady(ac), nil
|
||||
}
|
||||
|
||||
// loadHelmChart attempts to download the artifact from the provided source,
|
||||
@ -372,6 +398,7 @@ func (r *ArmadaChartReconciler) reconcileDelete(ctx context.Context, ac *armadav
|
||||
|
||||
// Remove our finalizer from the list and update it.
|
||||
controllerutil.RemoveFinalizer(ac, armadav1.ArmadaChartFinalizer)
|
||||
ac.Status.HelmStatus = string(release.StatusUninstalled)
|
||||
if err := r.Update(ctx, ac); err != nil {
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user