Skip to content

Commit

Permalink
Runnable status should report the state of the latest stamped object (#…
Browse files Browse the repository at this point in the history
…900)

* Introduce a status that tracks the runnable's stamped object

Currently we assume it's a tekton TaskRun so we only
concern ourselves with the "Succeeded" condition

[finishes #486]

Co-authored-by: Sam Coward <[email protected]>

* Pull "ExtractConditions" out as a utility

Co-authored-by: Sam Coward <[email protected]>
  • Loading branch information
2 people authored and Ciro S. Costa committed Jun 24, 2022
1 parent fa7065e commit 8d6b439
Show file tree
Hide file tree
Showing 8 changed files with 349 additions and 197 deletions.
7 changes: 5 additions & 2 deletions pkg/apis/v1alpha1/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,8 +149,9 @@ const (
// -- RUNNABLE ConditionTypes

const (
RunnableReady = "Ready"
RunTemplateReady = "RunTemplateReady"
RunnableReady = "Ready"
RunTemplateReady = "RunTemplateReady"
StampedObjectCondition = "StampedObjectCondition"
)

// -- RUNNABLE ConditionType - RunTemplateReady ConditionReasons
Expand All @@ -164,4 +165,6 @@ const (
FailedToListCreatedObjectsReason = "FailedToListCreatedObjects"
UnknownErrorReason = "UnknownError"
ClientBuilderErrorResourcesSubmittedReason = "ClientBuilderError"
SucceededStampedObjectConditionReason = "SucceededCondition"
UnknownStampedObjectConditionReason = "Unknown"
)
18 changes: 18 additions & 0 deletions pkg/conditions/runnable_conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,21 @@ func ClientBuilderErrorCondition(err error) metav1.Condition {
Message: err.Error(),
}
}

// -- Runnable.Status.Conditions - StampedObjectCondition

func StampedObjectConditionUnknown() metav1.Condition {
return metav1.Condition{
Type: v1alpha1.StampedObjectCondition,
Status: metav1.ConditionUnknown,
Reason: v1alpha1.UnknownStampedObjectConditionReason,
}
}

func StampedObjectConditionKnown(condition *metav1.Condition) metav1.Condition {
return metav1.Condition{
Type: v1alpha1.StampedObjectCondition,
Status: condition.Status,
Reason: v1alpha1.SucceededStampedObjectConditionReason,
}
}
10 changes: 10 additions & 0 deletions pkg/controllers/runnable_reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,15 @@ func (r *RunnableReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
r.conditionManager.AddPositive(conditions.RunTemplateReadyCondition())
}

var stampedObjectStatusPresent = false
var trackingError error

if stampedObject != nil {
stampedCondition := utils.ExtractConditions(stampedObject).ConditionWithType("Succeeded")
if stampedCondition != nil {
r.conditionManager.AddPositive(conditions.StampedObjectConditionKnown(stampedCondition))
stampedObjectStatusPresent = true
}
trackingError = r.StampedTracker.Watch(log, stampedObject, &handler.EnqueueRequestForOwner{OwnerType: &v1alpha1.Runnable{}})
if trackingError != nil {
log.Error(err, "failed to add informer for object", "object", stampedObject)
Expand All @@ -143,6 +150,9 @@ func (r *RunnableReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
log.V(logger.DEBUG).Info("added informer for object", "object", stampedObject)
}
}
if !stampedObjectStatusPresent {
r.conditionManager.AddPositive(conditions.StampedObjectConditionUnknown())
}

return r.completeReconciliation(ctx, runnable, outputs, err)
}
Expand Down
28 changes: 6 additions & 22 deletions pkg/realizer/healthcheck/healthcheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package healthcheck

import (
"encoding/json"
"fmt"

corev1 "k8s.io/api/core/v1"
Expand All @@ -26,6 +25,7 @@ import (
"github.com/vmware-tanzu/cartographer/pkg/conditions"
"github.com/vmware-tanzu/cartographer/pkg/eval"
"github.com/vmware-tanzu/cartographer/pkg/selector"
"github.com/vmware-tanzu/cartographer/pkg/utils"
)

func IsClusterTemplate(reference *corev1.ObjectReference) bool {
Expand All @@ -40,14 +40,14 @@ func IsClusterTemplate(reference *corev1.ObjectReference) bool {

func OwnerHealthCondition(resourceStatuses []v1alpha1.ResourceStatus, previousConditions []metav1.Condition) metav1.Condition {
var previousHealthCondition []metav1.Condition
condition := conditions.ConditionList(previousConditions).ConditionWithType(v1alpha1.ResourceHealthy)
condition := utils.ConditionList(previousConditions).ConditionWithType(v1alpha1.ResourceHealthy)
if condition != nil {
previousHealthCondition = append(previousHealthCondition, *condition)
}
healthyConditionManager := conditions.NewConditionManager(v1alpha1.ResourcesHealthy, previousHealthCondition)

for _, resourceStatus := range resourceStatuses {
resourceHealthyCondition := conditions.ConditionList(resourceStatus.Conditions).ConditionWithType(v1alpha1.ResourceHealthy)
resourceHealthyCondition := utils.ConditionList(resourceStatus.Conditions).ConditionWithType(v1alpha1.ResourceHealthy)
if resourceHealthyCondition != nil {
healthyConditionManager.AddPositive(*resourceHealthyCondition)
}
Expand Down Expand Up @@ -90,7 +90,7 @@ func DetermineHealthCondition(rule *v1alpha1.HealthRule, realizedResource *v1alp
}

func singleConditionTypeCondition(singleConditionType string, stampedObject *unstructured.Unstructured) metav1.Condition {
singleCondition := extractConditions(stampedObject).ConditionWithType(singleConditionType)
singleCondition := utils.ExtractConditions(stampedObject).ConditionWithType(singleConditionType)
if singleCondition != nil {
if singleCondition.Status == metav1.ConditionFalse || singleCondition.Status == metav1.ConditionTrue {
return conditions.SingleConditionMatchCondition(singleCondition.Status, singleConditionType, singleCondition.Message)
Expand All @@ -113,22 +113,6 @@ func multiMatchCondition(multiMatchRule *v1alpha1.MultiMatchHealthRule, stampedO
return conditions.MultiMatchNoMatchesCondition()
}

func extractConditions(stampedObject *unstructured.Unstructured) conditions.ConditionList {
var conditionList conditions.ConditionList
maybeStatus := stampedObject.UnstructuredContent()["status"]
if unstructuredStatus, statusOk := maybeStatus.(map[string]interface{}); statusOk {
maybeConditions := unstructuredStatus["conditions"]
maybeConditionsJSON, err := json.Marshal(maybeConditions)
if err == nil {
err = json.Unmarshal(maybeConditionsJSON, &conditionList)
if err != nil {
return conditions.ConditionList{}
}
}
}
return conditionList
}

func messageForMatchingFieldRequirement(requirement v1alpha1.HealthMatchFieldSelectorRequirement, stampedObject *unstructured.Unstructured) string {
evaluator := eval.EvaluatorBuilder()
fieldValue, fieldErr := evaluator.EvaluateJsonPath(requirement.Key, stampedObject.UnstructuredContent())
Expand All @@ -145,7 +129,7 @@ func messageForMatchingFieldRequirement(requirement v1alpha1.HealthMatchFieldSel

func anyUnhealthyMatchCondition(rule v1alpha1.HealthMatchRule, stampedObject *unstructured.Unstructured) *metav1.Condition {
for _, conditionRule := range rule.MatchConditions {
singleCondition := extractConditions(stampedObject).ConditionWithType(conditionRule.Type)
singleCondition := utils.ExtractConditions(stampedObject).ConditionWithType(conditionRule.Type)
if singleCondition != nil && singleCondition.Status == conditionRule.Status {
condition := conditions.MultiMatchResourcesHealthyCondition(metav1.ConditionFalse,
v1alpha1.MultiMatchConditionHealthyReason,
Expand All @@ -169,7 +153,7 @@ func allHealthyMatchCondition(rule v1alpha1.HealthMatchRule, stampedObject *unst
var firstReason string
var message string
for _, conditionRule := range rule.MatchConditions {
resourceCondition := extractConditions(stampedObject).ConditionWithType(conditionRule.Type)
resourceCondition := utils.ExtractConditions(stampedObject).ConditionWithType(conditionRule.Type)
if resourceCondition == nil || resourceCondition.Status != conditionRule.Status {
return nil
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/realizer/realizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"

"github.com/vmware-tanzu/cartographer/pkg/apis/v1alpha1"
"github.com/vmware-tanzu/cartographer/pkg/conditions"
"github.com/vmware-tanzu/cartographer/pkg/logger"
"github.com/vmware-tanzu/cartographer/pkg/realizer/healthcheck"
"github.com/vmware-tanzu/cartographer/pkg/realizer/statuses"
"github.com/vmware-tanzu/cartographer/pkg/templates"
"github.com/vmware-tanzu/cartographer/pkg/utils"
)

func MakeSupplychainOwnerResources(supplyChain *v1alpha1.ClusterSupplyChain) []OwnerResource {
Expand Down Expand Up @@ -125,7 +125,7 @@ func (r *realizer) Realize(ctx context.Context, resourceRealizer ResourceRealize
var additionalConditions []metav1.Condition
if (stampedObject == nil || template == nil) && previousResourceStatus != nil {
realizedResource = &previousResourceStatus.RealizedResource
if previousResourceStatusHealthyCondition := conditions.ConditionList(previousResourceStatus.Conditions).ConditionWithType(v1alpha1.ResourceHealthy); previousResourceStatusHealthyCondition != nil {
if previousResourceStatusHealthyCondition := utils.ConditionList(previousResourceStatus.Conditions).ConditionWithType(v1alpha1.ResourceHealthy); previousResourceStatusHealthyCondition != nil {
additionalConditions = []metav1.Condition{*previousResourceStatusHealthyCondition}
}
} else {
Expand Down
3 changes: 1 addition & 2 deletions pkg/realizer/runnable/realizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,7 @@ func (r *runnableRealizer) Realize(ctx context.Context, runnable *v1alpha1.Runna
}
}

// FIXME: why are we taking a DeepCopy?
err = runnableRepo.EnsureImmutableObjectExistsOnCluster(ctx, stampedObject.DeepCopy(), map[string]string{"carto.run/runnable-name": runnable.Name})
err = runnableRepo.EnsureImmutableObjectExistsOnCluster(ctx, stampedObject, map[string]string{"carto.run/runnable-name": runnable.Name})
if err != nil {
log.Error(err, "failed to ensure object exists on cluster", "object", stampedObject)
return nil, nil, errors.RunnableApplyStampedObjectError{
Expand Down
25 changes: 23 additions & 2 deletions pkg/conditions/condition_utils.go → pkg/utils/unstructured.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package conditions
package utils

import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
import (
"encoding/json"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

type ConditionList []metav1.Condition

Expand All @@ -26,3 +31,19 @@ func (c ConditionList) ConditionWithType(conditionType string) *metav1.Condition
}
return nil
}

func ExtractConditions(stampedObject *unstructured.Unstructured) ConditionList {
var conditionList ConditionList
maybeStatus := stampedObject.UnstructuredContent()["status"]
if unstructuredStatus, statusOk := maybeStatus.(map[string]interface{}); statusOk {
maybeConditions := unstructuredStatus["conditions"]
maybeConditionsJSON, err := json.Marshal(maybeConditions)
if err == nil {
err = json.Unmarshal(maybeConditionsJSON, &conditionList)
if err != nil {
return ConditionList{}
}
}
}
return conditionList
}
Loading

0 comments on commit 8d6b439

Please sign in to comment.