Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v2] Adding ScaledObject.Status Conditions #750

Merged
merged 1 commit into from
Apr 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 98 additions & 13 deletions deploy/crds/keda.sh_scaledjobs_crd.yaml

Large diffs are not rendered by default.

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 @@ -13,6 +13,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 @@ -103,6 +109,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 @@ -130,8 +157,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