Skip to content

Commit

Permalink
[v2] Adding ScaledObject.Status Conditions (kedacore#750)
Browse files Browse the repository at this point in the history
  • Loading branch information
zroubalik authored and Zbynek Roubalik committed Jul 7, 2020
1 parent 646753b commit 7c91553
Show file tree
Hide file tree
Showing 11 changed files with 383 additions and 42 deletions.
21 changes: 21 additions & 0 deletions deploy/crds/keda.sh_scaledjobs_crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6375,6 +6375,27 @@ spec:
status:
description: ScaledJobStatus defines the observed state of ScaledJob
properties:
conditions:
items:
properties:
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition
type: string
required:
- status
- type
type: object
type: array
lastActiveTime:
format: date-time
type: string
Expand Down
29 changes: 27 additions & 2 deletions deploy/crds/keda.sh_scaledobjects_crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ spec:
- jsonPath: .spec.triggers[*].type
name: Triggers
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Active")].status
name: Active
type: string
- jsonPath: .metadata.creationTimestamp
name: Age
type: date
Expand Down Expand Up @@ -104,6 +110,27 @@ spec:
status:
description: ScaledObjectStatus is the status for a ScaledObject resource
properties:
conditions:
items:
properties:
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition
type: string
required:
- status
- type
type: object
type: array
externalMetricNames:
items:
type: string
Expand Down Expand Up @@ -131,8 +158,6 @@ spec:
type: object
scaleTargetKind:
type: string
required:
- scaleTargetGVKR
type: object
required:
- spec
Expand Down
133 changes: 133 additions & 0 deletions pkg/apis/keda/v1alpha1/condition_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package v1alpha1

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

type ConditionType string

const (
// ConditionReady specifies that the resource is ready.
// For long-running resources.
ConditionReady ConditionType = "Ready"
// ConditionActive specifies that the resource has finished.
// For resource which run to completion.
ConditionActive ConditionType = "Active"
)

type Condition struct {
// Type of condition
// +required
Type ConditionType `json:"type" description:"type of status condition"`

// Status of the condition, one of True, False, Unknown.
// +required
Status metav1.ConditionStatus `json:"status" description:"status of the condition, one of True, False, Unknown"`

// The reason for the condition's last transition.
// +optional
Reason string `json:"reason,omitempty" description:"one-word CamelCase reason for the condition's last transition"`

// A human readable message indicating details about the transition.
// +optional
Message string `json:"message,omitempty" description:"human-readable message indicating details about last transition"`
}

type Conditions []Condition

// AreInitialized performs check all Conditions are initialized
// return true if Conditions are initialized
// return false if Conditions are not initialized
func (c *Conditions) AreInitialized() bool {
foundReady := false
foundActive := false
if *c != nil {
for _, condition := range *c {
if condition.Type == ConditionReady {
foundReady = true
break
}
}
for _, condition := range *c {
if condition.Type == ConditionActive {
foundActive = true
break
}
}
}

return foundReady && foundActive
}

// GetInitializedConditions returns Conditions initialized to the default -> Status: Unknown
func GetInitializedConditions() *Conditions {
return &Conditions{{Type: ConditionReady, Status: metav1.ConditionUnknown}, {Type: ConditionActive, Status: metav1.ConditionUnknown}}
}

// IsTrue is true if the condition is True
func (c *Condition) IsTrue() bool {
if c == nil {
return false
}
return c.Status == metav1.ConditionTrue
}

// IsFalse is true if the condition is False
func (c *Condition) IsFalse() bool {
if c == nil {
return false
}
return c.Status == metav1.ConditionFalse
}

// IsUnknown is true if the condition is Unknown
func (c *Condition) IsUnknown() bool {
if c == nil {
return true
}
return c.Status == metav1.ConditionUnknown
}

// SetReadyCondition modifies Ready Condition according to input parameters
func (c *Conditions) SetReadyCondition(status metav1.ConditionStatus, reason string, message string) {
if *c == nil {
c = GetInitializedConditions()
}
c.setCondition(ConditionReady, status, reason, message)
}

// SetActiveCondition modifies Active Condition according to input parameters
func (c *Conditions) SetActiveCondition(status metav1.ConditionStatus, reason string, message string) {
if *c == nil {
c = GetInitializedConditions()
}
c.setCondition(ConditionActive, status, reason, message)
}

// GetActiveCondition returns Condition of type Active
func (c *Conditions) GetActiveCondition() Condition {
if *c == nil {
c = GetInitializedConditions()
}
return c.getCondition(ConditionActive)
}

func (c Conditions) getCondition(conditionType ConditionType) Condition {
for i := range c {
if c[i].Type == conditionType {
return c[i]
}
}
return Condition{}
}

func (c Conditions) setCondition(conditionType ConditionType, status metav1.ConditionStatus, reason string, message string) {
for i := range c {
if c[i].Type == conditionType {
c[i].Status = status
c[i].Reason = reason
c[i].Message = message
break
}
}
}
8 changes: 8 additions & 0 deletions pkg/apis/keda/v1alpha1/scaledjob_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import (

// ScaledJobSpec defines the desired state of ScaledJob
// +k8s:openapi-gen=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:path=scaledobjects,scope=Namespaced
// +kubebuilder:printcolumn:name="Triggers",type="string",JSONPath=".spec.triggers[*].type"
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status"
// +kubebuilder:printcolumn:name="Active",type="string",JSONPath=".status.conditions[?(@.type==\"Active\")].status"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
type ScaledJobSpec struct {

// TODO define the spec
Expand All @@ -30,6 +36,8 @@ type ScaledJobSpec struct {
type ScaledJobStatus struct {
// +optional
LastActiveTime *metav1.Time `json:"lastActiveTime,omitempty"`
// +optional
Conditions Conditions `json:"conditions,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
9 changes: 6 additions & 3 deletions pkg/apis/keda/v1alpha1/scaledobject_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
// +kubebuilder:printcolumn:name="ScaleTargetKind",type="string",JSONPath=".status.scaleTargetKind"
// +kubebuilder:printcolumn:name="ScaleTargetName",type="string",JSONPath=".spec.scaleTargetRef.name"
// +kubebuilder:printcolumn:name="Triggers",type="string",JSONPath=".spec.triggers[*].type"
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status"
// +kubebuilder:printcolumn:name="Active",type="string",JSONPath=".status.conditions[?(@.type==\"Active\")].status"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
type ScaledObject struct {
metav1.TypeMeta `json:",inline"`
Expand Down Expand Up @@ -70,13 +72,14 @@ type ScaleTriggers struct {
type ScaledObjectStatus struct {
// +optional
ScaleTargetKind string `json:"scaleTargetKind,omitempty"`

ScaleTargetGVKR *kedautil.GroupVersionKindResource `json:"scaleTargetGVKR"`

// +optional
ScaleTargetGVKR *kedautil.GroupVersionKindResource `json:"scaleTargetGVKR,omitempty"`
// +optional
LastActiveTime *metav1.Time `json:"lastActiveTime,omitempty"`
// +optional
ExternalMetricNames []string `json:"externalMetricNames,omitempty"`
// +optional
Conditions Conditions `json:"conditions,omitempty"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
Expand Down
46 changes: 46 additions & 0 deletions pkg/apis/keda/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions pkg/controller/scaledobject/hpa.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"

kedav1alpha1 "github.com/kedacore/keda/pkg/apis/keda/v1alpha1"
kedacontrollerutil "github.com/kedacore/keda/pkg/controller/util"
kedautil "github.com/kedacore/keda/pkg/util"

"github.com/go-logr/logr"
Expand Down Expand Up @@ -130,8 +131,9 @@ func (r *ReconcileScaledObject) getScaledObjectMetricSpecs(logger logr.Logger, s
}

// store External.MetricNames used by scalers defined in the ScaledObject
scaledObject.Status.ExternalMetricNames = externalMetricNames
err = r.client.Status().Update(context.TODO(), scaledObject)
status := scaledObject.Status.DeepCopy()
status.ExternalMetricNames = externalMetricNames
err = kedacontrollerutil.UpdateScaledObjectStatus(r.client, logger, scaledObject, status)
if err != nil {
logger.Error(err, "Error updating scaledObject status with used externalMetricNames")
return nil, err
Expand Down
Loading

0 comments on commit 7c91553

Please sign in to comment.