Skip to content

Commit

Permalink
Fix status when system is insync
Browse files Browse the repository at this point in the history
DM must not have status.delta when controllers are insync. This commit
ensures no delta for host, system and data network controllers.

Test plan:
PASS - perform day-2 operations, ensure no delta once controllers are
insync.

Signed-off-by: Wallysson Silva <wallysson.silva@windriver.com>
  • Loading branch information
wasnio committed Dec 9, 2024
1 parent bc5a0fe commit 2734bf9
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 95 deletions.
5 changes: 5 additions & 0 deletions api/v1/constructors.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package v1
import (
"fmt"
"regexp"
"slices"
"strconv"
"strings"

Expand Down Expand Up @@ -202,6 +203,10 @@ func parseProcessorInfo(profile *HostProfileSpec, host v1info.HostInfo) error {
node.Functions = append(node.Functions, data)
}

slices.SortFunc(node.Functions, func(a, b ProcessorFunctionInfo) int {
return strings.Compare(a.Function, b.Function)
})

result = append(result, node)
}

Expand Down
12 changes: 12 additions & 0 deletions api/v1/datanetwork_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ func (d *DataNetwork) SetAnnotations(annotations map[string]string) {
d.ObjectMeta.Annotations = annotations
}

func (d *DataNetwork) GetStatusDelta() string {
return d.Status.Delta
}

func (d *DataNetwork) SetStatusDelta(delta string) {
d.Status.Delta = delta
}

func (d *DataNetwork) GetInsync() bool {
return d.Status.InSync
}

// +kubebuilder:object:root=true
// DataNetworks defines the attributes that represent the data network level
// attributes of a StarlingX system. This is a composition of the following
Expand Down
12 changes: 12 additions & 0 deletions api/v1/host_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,18 @@ type HostStatus struct {
Delta string `json:"delta"`
}

func (h *Host) SetStatusDelta(delta string) {
h.Status.Delta = delta
}

func (h *Host) GetStatusDelta() string {
return h.Status.Delta
}

func (h *Host) GetInsync() bool {
return h.Status.InSync
}

func (h *Host) GetStrategyRequired() string {
return h.Status.StrategyRequired
}
Expand Down
12 changes: 12 additions & 0 deletions api/v1/system_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,18 @@ type System struct {
Status SystemStatus `json:"status,omitempty"`
}

func (s *System) SetStatusDelta(delta string) {
s.Status.Delta = delta
}

func (s *System) GetStatusDelta() string {
return s.Status.Delta
}

func (s *System) GetInsync() bool {
return s.Status.InSync
}

// +kubebuilder:object:root=true
// SystemList contains a list of System
// +deepequal-gen=false
Expand Down
40 changes: 8 additions & 32 deletions controllers/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"time"

"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
"github.com/gophercloud/gophercloud"
perrors "github.com/pkg/errors"
starlingxv1 "github.com/wind-river/cloud-platform-deployment-manager/api/v1"
Expand Down Expand Up @@ -92,6 +91,14 @@ var (
// mechanism and no retry is necessary.
RetryNever = reconcile.Result{Requeue: false}

// Properties contained on DataNetwork resouce
DataNetworkPropers = map[string]interface{}{
"type": nil,
"description": nil,
"mtu": nil,
"vxlan": []string{"multicastgroup", "udpPortNumber", "ttl", "endpointMode"},
}

// Properties contained on System resource
SystemProperties = map[string]interface{}{
"certificates": nil,
Expand Down Expand Up @@ -397,37 +404,6 @@ func (in *EventLogger) WarningEvent(object runtime.Object, reason string, messag
in.event(object, v1.EventTypeWarning, 1, reason, messageFmt, args...)
}

func GetDeltaString(spec interface{}, current interface{}, parameters map[string]interface{}) (string, error) {

specBytes, err := json.Marshal(spec)
if err != nil {
return "", err
}

currentBytes, err := json.Marshal(current)
if err != nil {
return "", err
}

var specData map[string]interface{}
var currentData map[string]interface{}

err = json.Unmarshal([]byte(specBytes), &specData)
if err != nil {
return "", err
}

err = json.Unmarshal([]byte(currentBytes), &currentData)
if err != nil {
return "", err
}

diff := cmp.Diff(currentData, specData)
deltaString := collectDiffValues(diff, parameters)
deltaString = strings.TrimSuffix(deltaString, "\n")
return deltaString, nil
}

/*
CollectDiffValues collects and returns the diff values from the given diff string.
The function returns lines starting with '+' or '-' that represent the differences,
Expand Down
76 changes: 76 additions & 0 deletions controllers/common/delta.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package common

import (
"context"
"encoding/json"
"fmt"
"strings"

"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
"sigs.k8s.io/controller-runtime/pkg/client"
)

type instance interface {
client.Object

SetStatusDelta(string)
GetStatusDelta() string
GetInsync() bool
}

func GetDeltaString(spec interface{}, current interface{}, parameters map[string]interface{}) (string, error) {

specBytes, err := json.Marshal(spec)
if err != nil {
return "", err
}

currentBytes, err := json.Marshal(current)
if err != nil {
return "", err
}

var specData map[string]interface{}
var currentData map[string]interface{}

err = json.Unmarshal([]byte(specBytes), &specData)
if err != nil {
return "", err
}

err = json.Unmarshal([]byte(currentBytes), &currentData)
if err != nil {
return "", err
}

diff := cmp.Diff(currentData, specData)
deltaString := collectDiffValues(diff, parameters)
deltaString = strings.TrimSuffix(deltaString, "\n")
return deltaString, nil
}

func SetInstanceDelta(
inst instance, spec, current interface{},
parameters map[string]interface{},
status client.StatusWriter, log logr.Logger,
) {
kind := inst.GetObjectKind().GroupVersionKind().Kind
log.Info(fmt.Sprintf("Updating delta for kind %s", kind))

oldDelta := inst.GetStatusDelta()
if inst.GetInsync() {
inst.SetStatusDelta("")
} else if delta, err := GetDeltaString(spec, current, parameters); err == nil {
inst.SetStatusDelta(delta)
} else {
log.Info(fmt.Sprintf("Failed to get Delta string for kind %s: %s\n", kind, err))
}

if oldDelta != inst.GetStatusDelta() {
err := status.Update(context.TODO(), inst)
if err != nil {
log.Info(fmt.Sprintf("Failed to update the status for kind %s: %s", kind, err))
}
}
}
26 changes: 8 additions & 18 deletions controllers/datanetwork_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"context"
"encoding/json"
"fmt"
"strings"

"github.com/go-logr/logr"
"github.com/gophercloud/gophercloud"
Expand Down Expand Up @@ -49,29 +48,24 @@ type DataNetworkReconciler struct {
// update is needed to a data network system resource in order to reconcile
// with the latest stored configuration.
func dataNetworkUpdateRequired(instance *starlingxv1.DataNetwork, n *datanetworks.DataNetwork, r *DataNetworkReconciler) (opts datanetworks.DataNetworkOpts, result bool) {
var delta strings.Builder
if instance.Name != n.Name {
opts.Name = &instance.Name
delta.WriteString(fmt.Sprintf("\t+Name: %s\n", *opts.Name))
result = true
}

spec := instance.Spec
if spec.Type != n.Type {
opts.Type = &spec.Type
delta.WriteString(fmt.Sprintf("\t+Type: %s\n", *opts.Type))
result = true
}

if spec.MTU != nil && *spec.MTU != n.MTU {
opts.MTU = spec.MTU
delta.WriteString(fmt.Sprintf("\t+MTU: %d\n", *opts.MTU))
result = true
}

if spec.Description != nil && *spec.Description != n.Description {
opts.Description = spec.Description
delta.WriteString(fmt.Sprintf("\t+Description: %s\n", *opts.Description))
result = true
}

Expand All @@ -80,46 +74,42 @@ func dataNetworkUpdateRequired(instance *starlingxv1.DataNetwork, n *datanetwork
if vxlan.EndpointMode != nil && n.Mode != nil {
if *vxlan.EndpointMode != *n.Mode {
opts.Mode = vxlan.EndpointMode
delta.WriteString(fmt.Sprintf("\t+Mode: %s\n", *opts.Mode))
result = true
}
}

if vxlan.UDPPortNumber != nil && n.UDPPortNumber != nil {
if *vxlan.UDPPortNumber != *n.UDPPortNumber {
opts.PortNumber = vxlan.UDPPortNumber
delta.WriteString(fmt.Sprintf("\t+PortNumber: %d\n", *opts.PortNumber))
result = true
}
}

if vxlan.TTL != nil && n.TTL != nil {
if *vxlan.TTL != *n.TTL {
opts.TTL = vxlan.TTL
delta.WriteString(fmt.Sprintf("\t+TTL: %d\n", *opts.TTL))
result = true
}
}

if vxlan.MulticastGroup != nil && n.MulticastGroup != nil {
if *vxlan.MulticastGroup != *n.MulticastGroup {
opts.MulticastGroup = vxlan.MulticastGroup
delta.WriteString(fmt.Sprintf("\t+MulticastGroup: %s\n", *opts.MulticastGroup))
result = true
}
}
}
deltaString := delta.String()
if deltaString != "" {
deltaString = "\n" + strings.TrimSuffix(deltaString, "\n")
logDataNetwork.Info(fmt.Sprintf("delta configuration:%s\n", deltaString))
}
instance.Status.Delta = deltaString
err := r.Client.Status().Update(context.TODO(), instance)

currentSpec, err := starlingxv1.NewDataNetworkSpec(*n)
if err != nil {
logDataNetwork.Info(fmt.Sprintf("failed to update status: %s\n", err))
return opts, false
}

common.SetInstanceDelta(
instance, currentSpec, spec, common.DataNetworkPropers,
r.Client.Status(), logDataNetwork,
)

return opts, result
}

Expand Down
24 changes: 3 additions & 21 deletions controllers/host/host_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1774,37 +1774,19 @@ func (r *HostReconciler) ReconcileExistingHost(client *gophercloud.ServiceClient
}

logHost.Info("comparing profile attributes", "host", host.ID)
inSync := r.CompareAttributes(profile, current, instance, host.Personality, system_info)
instance.Status.InSync = r.CompareAttributes(profile, current, instance, host.Personality, system_info)
common.SetInstanceDelta(instance, profile, current, common.HostProperties, r.Client.Status(), logHost)

// Continue the following steps even inSync:
// strategy not finished
if inSync && (instance.Status.StrategyRequired == cloudManager.StrategyNotRequired) {
if instance.Status.InSync && (instance.Status.StrategyRequired == cloudManager.StrategyNotRequired) {
logHost.V(2).Info("no changes between composite profile and current config", "host", host.ID)
instance.Status.Delta = ""
return nil
}

logHost.Info("defaults are:", "values", defaults)

logHost.Info("final profile is:", "values", profile)

logHost.Info("current config is:", "values", current)

deltaString, err := common.GetDeltaString(profile, current, common.HostProperties)
if err != nil {
logHost.Info(fmt.Sprintf("failed to get Delta status: %s\n", err))
}

if deltaString != "" {
logHost.V(2).Info(fmt.Sprintf("delta configuration:%s\n", deltaString))
instance.Status.Delta = deltaString

err = r.Client.Status().Update(context.TODO(), instance)
if err != nil {
logHost.Info(fmt.Sprintf("failed to update status: %s", err))
}
}

if instance.Status.Reconciled &&
r.StopAfterInSync() &&
instance.Status.StrategyRequired != cloudManager.StrategyLockRequired {
Expand Down
27 changes: 3 additions & 24 deletions controllers/system/system_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1125,29 +1125,8 @@ func (r *SystemReconciler) ReconcileRequired(instance *starlingxv1.System, spec
current.Certificates = &res
}

if spec.DeepEqual(current) {
logSystem.V(2).Info("no changes between spec and current configuration")
instance.Status.Delta = ""
return nil, false
}

logSystem.Info("spec is:", "values", spec)

logSystem.Info("current is:", "values", current)

deltaString, err := common.GetDeltaString(current, spec, common.SystemProperties)
if err != nil {
logSystem.Info(fmt.Sprintf("failed to get Delta status: %s\n", err))
}

if deltaString != "" {
logSystem.Info(fmt.Sprintf("delta configuration:%s\n", deltaString))
instance.Status.Delta = deltaString
err = r.Client.Status().Update(context.TODO(), instance)
if err != nil {
logSystem.Info(fmt.Sprintf("failed to update status: %s\n", err))
}
}
instance.Status.InSync = spec.DeepEqual(current)
common.SetInstanceDelta(instance, current, spec, common.SystemProperties, r.Client.Status(), logSystem)

if instance.Status.Reconciled && r.StopAfterInSync() {
// Do not process any further changes once we have reached a
Expand Down Expand Up @@ -1497,7 +1476,7 @@ func (r *SystemReconciler) ReconcileResource(client *gophercloud.ServiceClient,
}

if r.statusUpdateRequired(instance, systemInfo, inSync) {
logSystem.Info("updating status for system", "status", instance.Status)
logSystem.V(2).Info("updating status for system", "status", instance.Status)

err3 := r.Client.Status().Update(context.TODO(), instance)
if err3 != nil {
Expand Down

0 comments on commit 2734bf9

Please sign in to comment.