Skip to content

Commit

Permalink
parse component status
Browse files Browse the repository at this point in the history
  • Loading branch information
Richard87 committed Aug 27, 2024
1 parent 9144898 commit 3de4fc8
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 74 deletions.
119 changes: 46 additions & 73 deletions api/models/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ import (
cmv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmetav1 "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
deploymentModels "github.com/equinor/radix-api/api/deployments/models"
"github.com/equinor/radix-api/api/utils"
"github.com/equinor/radix-api/api/utils/event"
"github.com/equinor/radix-api/api/utils/predicate"
"github.com/equinor/radix-api/api/utils/tlsvalidation"
commonutils "github.com/equinor/radix-common/utils"
"github.com/equinor/radix-common/utils/pointers"
"github.com/equinor/radix-common/utils/slice"
operatordefaults "github.com/equinor/radix-operator/pkg/apis/defaults"
operatordeployment "github.com/equinor/radix-operator/pkg/apis/deployment"
radixv1 "github.com/equinor/radix-operator/pkg/apis/radix/v1"
operatorutils "github.com/equinor/radix-operator/pkg/apis/utils"
radixlabels "github.com/equinor/radix-operator/pkg/apis/utils/labels"
Expand Down Expand Up @@ -65,11 +64,16 @@ func buildComponent(
WithExternalDNS(getComponentExternalDNS(ra.Name, radixComponent, secretList, certs, certRequests, tlsValidator))

componentPods := slice.FindAll(podList, predicate.IsPodForComponent(ra.Name, radixComponent.GetName()))
var kd *appsv1.Deployment
if depl, ok := slice.FindFirst(deploymentList, predicate.IsDeploymentForComponent(ra.Name, radixComponent.GetName())); ok {
kd = &depl
}

if rd.Status.ActiveTo.IsZero() {
builder.WithPodNames(slice.Map(componentPods, func(pod corev1.Pod) string { return pod.Name }))
builder.WithRadixEnvironmentVariables(getRadixEnvironmentVariables(componentPods))
builder.WithReplicaSummaryList(BuildReplicaSummaryList(componentPods, lastEventWarnings))
builder.WithStatus(getComponentStatus(radixComponent, ra, rd, componentPods))
builder.WithStatus(getComponentStatus(radixComponent, kd, rd, podList))
builder.WithAuxiliaryResource(getAuxiliaryResources(ra.Name, radixComponent, deploymentList, podList, lastEventWarnings))
}

Expand Down Expand Up @@ -235,93 +239,62 @@ func certificateRequestConditionReady(condition cmv1.CertificateRequestCondition
return condition.Type == cmv1.CertificateRequestConditionReady
}

func getComponentStatus(component radixv1.RadixCommonDeployComponent, ra *radixv1.RadixApplication, rd *radixv1.RadixDeployment, pods []corev1.Pod) deploymentModels.ComponentStatus {
environmentConfig := utils.GetComponentEnvironmentConfig(ra, rd.Spec.Environment, component.GetName())
if component.GetType() == radixv1.RadixComponentTypeComponent {
// Manually stopped or KEDA scaled down to 0
if runningReplicaDiffersFromConfig(component, environmentConfig, pods) &&
!runningReplicaDiffersFromSpec(component, pods) &&
len(pods) == 0 {
return deploymentModels.StoppedComponent
}
func getComponentStatus(component radixv1.RadixCommonDeployComponent, kd *appsv1.Deployment, rd *radixv1.RadixDeployment, pods []corev1.Pod) deploymentModels.ComponentStatus {
var replicasUnavailable, replicasReady, replicas int32
if kd != nil {
replicasUnavailable = kd.Status.UnavailableReplicas
replicasReady = kd.Status.ReadyReplicas
replicas = pointers.Val(kd.Spec.Replicas)
}

if runningReplicaDiffersFromSpec(component, pods) {
return deploymentModels.ComponentReconciling
}
} else if component.GetType() == radixv1.RadixComponentTypeJob {
if len(pods) == 0 {
return deploymentModels.StoppedComponent
}
if replicas == 0 && component.GetType() == radixv1.RadixComponentTypeJob {
return deploymentModels.StoppedComponent
}
if runningReplicaIsOutdated(component, pods) {
return deploymentModels.ComponentOutdated

if isComponentManuallyStopped(component) && replicas == 0 {
return deploymentModels.StoppedComponent
}
restarted := component.GetEnvironmentVariables()[operatordefaults.RadixRestartEnvironmentVariable]
if strings.EqualFold(restarted, "") {
return deploymentModels.ConsistentComponent

if isCopmonentRestarting(component, rd) {
return deploymentModels.ComponentRestarting
}
restartedTime, err := commonutils.ParseTimestamp(restarted)
if err != nil {
// TODO: How should we handle invalid value for restarted time?

log.Logger.Warn().Err(err).Msgf("unable to parse restarted time %v", restarted)
return deploymentModels.ConsistentComponent
// Check if component is scaling up or down
if replicasUnavailable > 0 || replicas < replicasReady {
return deploymentModels.ComponentReconciling
}
reconciledTime := rd.Status.Reconciled
if reconciledTime.IsZero() || restartedTime.After(reconciledTime.Time) {
return deploymentModels.ComponentRestarting

if runningReplicaIsOutdated(component, pods) {
return deploymentModels.ComponentOutdated
}

return deploymentModels.ConsistentComponent
}

func runningReplicaDiffersFromConfig(component radixv1.RadixCommonDeployComponent, environmentConfig radixv1.RadixCommonEnvironmentConfig, actualPods []corev1.Pod) bool {
actualPodsLength := len(actualPods)

if component.GetReplicasOverride() != nil {
return actualPodsLength != *component.GetReplicasOverride()
func isComponentManuallyStopped(component radixv1.RadixCommonDeployComponent) bool {
override := component.GetReplicasOverride()
if override == nil {
return false
}

if commonutils.IsNil(environmentConfig) {
return actualPodsLength != operatordeployment.DefaultReplicas
}
// No HPA config
if environmentConfig.GetHorizontalScaling() == nil {
if environmentConfig.GetReplicas() != nil {
return actualPodsLength != *environmentConfig.GetReplicas()
}
return actualPodsLength != operatordeployment.DefaultReplicas
}
// With HPA config
if environmentConfig.GetReplicas() != nil && *environmentConfig.GetReplicas() == 0 {
return actualPodsLength != *environmentConfig.GetReplicas()
}
if environmentConfig.GetHorizontalScaling().MinReplicas != nil {
return actualPodsLength < int(*environmentConfig.GetHorizontalScaling().MinReplicas) ||
actualPodsLength > int(environmentConfig.GetHorizontalScaling().MaxReplicas)
}
return actualPodsLength < operatordeployment.DefaultReplicas ||
actualPodsLength > int(environmentConfig.GetHorizontalScaling().MaxReplicas)
return *override == 0
}

func runningReplicaDiffersFromSpec(component radixv1.RadixCommonDeployComponent, actualPods []corev1.Pod) bool {
actualPodsLength := len(actualPods)
// No HPA config
if component.GetHorizontalScaling() == nil {
if component.GetReplicas() != nil {
return actualPodsLength != *component.GetReplicas()
}
return actualPodsLength != operatordeployment.DefaultReplicas
func isCopmonentRestarting(component radixv1.RadixCommonDeployComponent, rd *radixv1.RadixDeployment) bool {
restarted := component.GetEnvironmentVariables()[operatordefaults.RadixRestartEnvironmentVariable]
if strings.EqualFold(restarted, "") {
return false
}
// With HPA config
if component.GetReplicas() != nil && *component.GetReplicas() == 0 {
return actualPodsLength != *component.GetReplicas()
restartedTime, err := commonutils.ParseTimestamp(restarted)
if err != nil {
log.Logger.Warn().Err(err).Msgf("unable to parse restarted time %v", restarted)
return false
}
if component.GetHorizontalScaling().MinReplicas != nil {
return actualPodsLength < int(*component.GetHorizontalScaling().MinReplicas) ||
actualPodsLength > int(component.GetHorizontalScaling().MaxReplicas)
reconciledTime := rd.Status.Reconciled
if reconciledTime.IsZero() || restartedTime.After(reconciledTime.Time) {
return true
}
return actualPodsLength < operatordeployment.DefaultReplicas ||
actualPodsLength > int(component.GetHorizontalScaling().MaxReplicas)
return false
}

func runningReplicaIsOutdated(component radixv1.RadixCommonDeployComponent, actualPods []corev1.Pod) bool {
Expand Down
7 changes: 7 additions & 0 deletions api/utils/predicate/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ func IsPodForComponent(appName, componentName string) func(corev1.Pod) bool {
}
}

func IsDeploymentForComponent(appName, componentName string) func(appsv1.Deployment) bool {
selector := labelselector.ForComponent(appName, componentName).AsSelector()
return func(deployment appsv1.Deployment) bool {
return selector.Matches(labels.Set(deployment.Labels))
}
}

func IsPodForAuxComponent(appName, componentName, auxType string) func(corev1.Pod) bool {
selector := labelselector.ForAuxiliaryResource(appName, componentName, auxType).AsSelector()
return func(pod corev1.Pod) bool {
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ toolchain go1.22.5

require (
github.com/cert-manager/cert-manager v1.15.0
github.com/equinor/radix-common v1.9.3
github.com/equinor/radix-common v1.9.4
github.com/equinor/radix-job-scheduler v1.10.2
github.com/equinor/radix-operator v1.57.19-0.20240826111516-e94c0a610d2f
github.com/evanphx/json-patch/v5 v5.9.0
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/equinor/radix-common v1.9.3 h1:dLKFzYy8/XyEG9Zygi0rMWIYGCddai/ILwUqjBiGYxQ=
github.com/equinor/radix-common v1.9.3/go.mod h1:+g0Wj0D40zz29DjNkYKVmCVeYy4OsFWKI7Qi9rA6kpY=
github.com/equinor/radix-common v1.9.4 h1:ErSnB2tqlRwaQuQdaA0qzsReDtHDgubcvqRO098ncEw=
github.com/equinor/radix-common v1.9.4/go.mod h1:+g0Wj0D40zz29DjNkYKVmCVeYy4OsFWKI7Qi9rA6kpY=
github.com/equinor/radix-job-scheduler v1.10.2 h1:Ea/gmSQjVdomC3XzkqJdR1TGQ9Bvq8ZJOKUfwYY3Ask=
github.com/equinor/radix-job-scheduler v1.10.2/go.mod h1:cnVXZ09D0rAPTZrcgWynL/txMQnpYmPSPyzfKfTYlec=
github.com/equinor/radix-operator v1.57.19-0.20240826111516-e94c0a610d2f h1:Fe1dguEAN9wUWN8Hqhw3Ej4MGsG39hc45zDA7lHFCZ8=
Expand Down

0 comments on commit 3de4fc8

Please sign in to comment.