c01ae85c33a19e33cd06e77e8e6959b7dd44277e
[oom/platform/cert-service.git] / certServiceK8sExternalProvider / src / certservice-controller / certservice_issuer_status_reconciler.go
1 /*
2  * ============LICENSE_START=======================================================
3  * oom-certservice-k8s-external-provider
4  * ================================================================================
5  * Copyright (c) 2019 Smallstep Labs, Inc.
6  * Modifications copyright (C) 2020 Nokia. All rights reserved.
7  * ================================================================================
8  * This source code was copied from the following git repository:
9  * https://github.com/smallstep/step-issuer
10  * The source code was modified for usage in the ONAP project.
11  * ================================================================================
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  *      http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  * ============LICENSE_END=========================================================
24  */
25
26
27 package certservice_controller
28
29 import (
30         "context"
31         "fmt"
32         "github.com/go-logr/logr"
33         core "k8s.io/api/core/v1"
34         meta "k8s.io/apimachinery/pkg/apis/meta/v1"
35         "onap.org/oom-certservice/k8s-external-provider/src/api"
36 )
37
38 type certServiceIssuerStatusReconciler struct {
39         *CertServiceIssuerReconciler
40         issuer *api.CertServiceIssuer
41         logger logr.Logger
42 }
43
44 func newStatusReconciler(r *CertServiceIssuerReconciler, iss *api.CertServiceIssuer, log logr.Logger) *certServiceIssuerStatusReconciler {
45         return &certServiceIssuerStatusReconciler{
46                 CertServiceIssuerReconciler: r,
47                 issuer:                      iss,
48                 logger:                      log,
49         }
50 }
51
52 func (r *certServiceIssuerStatusReconciler) Update(ctx context.Context, status api.ConditionStatus, reason, message string, args ...interface{}) error {
53         completeMessage := fmt.Sprintf(message, args...)
54         r.setCondition(status, reason, completeMessage)
55
56         // Fire an Event to additionally inform users of the change
57         eventType := core.EventTypeNormal
58         if status == api.ConditionFalse {
59                 eventType = core.EventTypeWarning
60         }
61         r.Recorder.Event(r.issuer, eventType, reason, completeMessage)
62
63         return r.Client.Status().Update(ctx, r.issuer)
64 }
65
66 func (r *certServiceIssuerStatusReconciler) UpdateNoError(ctx context.Context, status api.ConditionStatus, reason, message string, args ...interface{}) {
67         if err := r.Update(ctx, status, reason, message, args...); err != nil {
68                 r.logger.Error(err, "failed to update", "status", status, "reason", reason)
69         }
70 }
71
72 // setCondition will set a 'condition' on the given api.CertServiceIssuer resource.
73 //
74 // - If no condition of the same type already exists, the condition will be
75 //   inserted with the LastTransitionTime set to the current time.
76 // - If a condition of the same type and state already exists, the condition
77 //   will be updated but the LastTransitionTime will not be modified.
78 // - If a condition of the same type and different state already exists, the
79 //   condition will be updated and the LastTransitionTime set to the current
80 //   time.
81 func (r *certServiceIssuerStatusReconciler) setCondition(status api.ConditionStatus, reason, message string) {
82         now := meta.NewTime(r.Clock.Now())
83         c := api.CertServiceIssuerCondition{
84                 Type:               api.ConditionReady,
85                 Status:             status,
86                 Reason:             reason,
87                 Message:            message,
88                 LastTransitionTime: &now,
89         }
90
91         // Search through existing conditions
92         for idx, cond := range r.issuer.Status.Conditions {
93                 // Skip unrelated conditions
94                 if cond.Type != api.ConditionReady {
95                         continue
96                 }
97
98                 // If this update doesn't contain a state transition, we don't update
99                 // the conditions LastTransitionTime to Now()
100                 if cond.Status == status {
101                         c.LastTransitionTime = cond.LastTransitionTime
102                 } else {
103                         r.logger.Info("found status change for CertServiceIssuer condition; setting lastTransitionTime", "condition", cond.Type, "old_status", cond.Status, "new_status", status, "time", now.Time)
104                 }
105
106                 // Overwrite the existing condition
107                 r.issuer.Status.Conditions[idx] = c
108                 return
109         }
110
111         // If we've not found an existing condition of this type, we simply insert
112         // the new condition into the slice.
113         r.issuer.Status.Conditions = append(r.issuer.Status.Conditions, c)
114         r.logger.Info("setting lastTransitionTime for CertServiceIssuer condition", "condition", api.ConditionReady, "time", now.Time)
115 }