package util import ( acmapi "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/apis/anthoscertmanager/v1" acmmeta "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/apis/meta/v1" logf "gitbucket.jerxie.com/yangyangxie/AnthosCertManager/pkg/logs" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/clock" ) // Clock is defined as a package var so it can be stubbed out during tests. var Clock clock.Clock = clock.RealClock{} // CertificateHasCondition will return true if the given Certificate has a // condition matching the provided CertificateCondition. // Only the Type and Status field will be used in the comparison, meaning that // this function will return 'true' even if the Reason, Message and // LastTransitionTime fields do not match. func CertificateHasCondition(crt *acmapi.Certificate, c acmapi.CertificateCondition) bool { if crt == nil { return false } existingConditions := crt.Status.Conditions for _, cond := range existingConditions { if c.Type == cond.Type && c.Status == cond.Status { return true } } return false } // RemoveCertificateCondition will remove any condition with this condition type func RemoveCertificateCondition(crt *acmapi.Certificate, conditionType acmapi.CertificateConditionType) { var updatedConditions []acmapi.CertificateCondition for _, cond := range crt.Status.Conditions { if cond.Type != conditionType { // Only add the unrelated conditions updatedConditions = append(updatedConditions, cond) } } // Add the other conditions back. crt.Status.Conditions = updatedConditions } // IssuerHasCondition will return true if the given GenericIssuer has a // condition matching the provided IssuerCondition. // Only the Type and Status field will be used in the comparison, meaning that // this function will return 'true' even if the Reason, Message and // LastTransitionTime fields do not match. func IssuerHasCondition(i acmapi.GenericIssuer, c acmapi.IssuerCondition) bool { if i == nil { return false } existingConditions := i.GetStatus().Conditions for _, cond := range existingConditions { if c.Type == cond.Type && c.Status == cond.Status { return true } } return false } // SetIssuerCondition will set a 'condition' on the given GenericIssuer. // - If no condition of the same type already exists, the condition will be // inserted with the LastTransitionTime set to the current time. // - If a condition of the same type and state already exists, the condition // will be updated but the LastTransitionTime will not be modified. // - If a condition of the same type and different state already exists, the // condition will be updated and the LastTransitionTime set to the current // time. // // This function works with both Issuer and ClusterIssuer resources. func SetIssuerCondition(i acmapi.GenericIssuer, observedGeneration int64, conditionType acmapi.IssuerConditionType, status acmmeta.ConditionStatus, reason, message string) { newCondition := acmapi.IssuerCondition{ Type: conditionType, Status: status, Reason: reason, Message: message, } nowTime := metav1.NewTime(Clock.Now()) newCondition.LastTransitionTime = &nowTime // Set the condition generation newCondition.ObservedGeneration = observedGeneration // Search through existing conditions for idx, cond := range i.GetStatus().Conditions { // Skip unrelated conditions if cond.Type != conditionType { continue } // If this update doesn't contain a state transition, we don't update // the conditions LastTransitionTime to Now() if cond.Status == status { newCondition.LastTransitionTime = cond.LastTransitionTime } else { logf.V(logf.InfoLevel).Infof("Found status change for Issuer %q condition %q: %q -> %q; setting lastTransitionTime to %v", i.GetObjectMeta().Name, conditionType, cond.Status, status, nowTime.Time) } // Overwrite the existing condition i.GetStatus().Conditions[idx] = newCondition return } // If we've not found an existing condition of this type, we simply insert // the new condition into the slice. i.GetStatus().Conditions = append(i.GetStatus().Conditions, newCondition) logf.V(logf.InfoLevel).Infof("Setting lastTransitionTime for Issuer %q condition %q to %v", i.GetObjectMeta().Name, conditionType, nowTime.Time) } // SetCertificateCondition will set a 'condition' on the given Certificate. func SetCertificateCondition(crt *acmapi.Certificate, observedGeneration int64, conditionType acmapi.CertificateConditionType, status acmmeta.ConditionStatus, reason, message string) { newCondition := acmapi.CertificateCondition{ Type: conditionType, Status: status, Reason: reason, Message: message, } nowtime := metav1.NewTime(Clock.Now()) newCondition.LastTransitionTime = &nowtime newCondition.ObservedGeneration = observedGeneration for idx, cond := range crt.Status.Conditions { if cond.Type != conditionType { continue } // If the status is not changed, keep the original time. if cond.Status == status { newCondition.LastTransitionTime = cond.LastTransitionTime } else { logf.V(logf.InfoLevel).Infof("Found status change for Certificate %q condition %q: %q -> %q; setting lastTransitionTime to %v", crt.Name, conditionType, cond.Status, status, nowtime.Time) } //override the existing condition crt.Status.Conditions[idx] = newCondition return } // If we could not find the condition, we just insert it to the slice. crt.Status.Conditions = append(crt.Status.Conditions, newCondition) logf.V(logf.InfoLevel).Infof("Setting lastTransitionTime for Certificate %q condition %q to %v", crt.Name, conditionType, nowtime.Time) } func GetCertificateCondition(crt *acmapi.Certificate, conditionType acmapi.CertificateConditionType) *acmapi.CertificateCondition { for _, cond := range crt.Status.Conditions { if cond.Type == conditionType { return &cond } } return nil } func GetCertificateRequestCondition(req *acmapi.CertificateRequest, conditionType acmapi.CertificateRequestConditionType) *acmapi.CertificateRequestCondition { for _, cond := range req.Status.Conditions { if cond.Type == conditionType { return &cond } } return nil }