Skip to content

Commit

Permalink
Preserve system annotations and labels during object update (#568)
Browse files Browse the repository at this point in the history
* preserve system annotations

* rename key

* update preservations at client side

* update etag

* update etag logic

* update using getState and update validation

* remove validateCreateOrUpdate from manager

* update etag

provider change detection change; Helm provider tag change (#575)

* provider change detection change; Helm provider tag change

* fix change state bug

* add version for helm

* remove no use code

---------

Co-authored-by: Haishi Bai <hbai@microsoft.com>
Co-authored-by: Jiawei Du <59427055+msftcoderdjw@users.noreply.github.com>

catalog sample fix with portal adjustment to new schema (#581)

fix retail scenario docs (#582)

fix #550 by allow the job to be requeued (#578)

Co-authored-by: Jiawei Du <59427055+msftcoderdjw@users.noreply.github.com>

update etag and test

fix ut

fix ut

* update k8s test
  • Loading branch information
linyguo authored Dec 13, 2024
1 parent 69805f1 commit fc3328f
Show file tree
Hide file tree
Showing 24 changed files with 331 additions and 103 deletions.
49 changes: 49 additions & 0 deletions api/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,54 @@ var (
EulaMessage string
)

const (
FullGroupName = "symphony"

// system annotations, reserved and should not be modified by client.
AzureCorrelationIdKey = "management.azure.com/correlationId"
AzureEdgeLocationKey = "management.azure.com/customLocation"
AzureOperationIdKey = "management.azure.com/operationId"
AzureNameIdKey = "management.azure.com/azureName"
AzureResourceIdKey = "management.azure.com/resourceId"
AzureSystemDataKey = "management.azure.com/systemData"
AzureTenantIdKey = "management.azure.com/tenantId" // Not used
RunningAzureCorrelationIdKey = "management.azure.com/runningCorrelationId"
SummaryJobIdKey = "SummaryJobIdKey"
OperationStartTimeKeyPostfix = FullGroupName + "/started-at" // instance/target

ProviderName = "management.azure.com/provider-name"
)

func SystemReservedAnnotations() []string {
return []string{
AzureCorrelationIdKey,
AzureEdgeLocationKey,
AzureOperationIdKey,
AzureNameIdKey,
AzureResourceIdKey,
AzureSystemDataKey,
AzureTenantIdKey,
RunningAzureCorrelationIdKey,
SummaryJobIdKey,
OperationStartTimeKeyPostfix,
}
}

func SystemReservedLabels() []string {
return []string{
Campaign,
DisplayName,
ProviderName,
ManagerMetaKey,
ParentName,
RootResource,
Solution,
StagedTarget,
StatusMessage,
Target,
}
}

const (
DefaultScope = "default"
SATokenPath = "/var/run/secrets/tokens/symphony-api-token"
Expand All @@ -33,6 +81,7 @@ const (
Solution = "solution"
Target = "target"
Campaign = "campaign"
StagedTarget = "staged_target"
)

// Environment variables keys
Expand Down
23 changes: 13 additions & 10 deletions api/pkg/apis/v1alpha1/managers/activations/activations-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,16 @@ func (m *ActivationsManager) GetState(ctx context.Context, name string, namespac
return model.ActivationState{}, err
}
var ret model.ActivationState
ret, err = getActivationState(entry.Body, entry.ETag)
ret, err = getActivationState(entry.Body)
if err != nil {
log.ErrorfCtx(ctx, "Failed to convert to activation state for %s in namespace %s: %v", name, namespace, err)
return model.ActivationState{}, err
}
ret.ObjectMeta.UpdateEtag(entry.ETag)
return ret, nil
}

func getActivationState(body interface{}, etag string) (model.ActivationState, error) {
func getActivationState(body interface{}) (model.ActivationState, error) {
var activationState model.ActivationState
bytes, _ := json.Marshal(body)
err := json.Unmarshal(bytes, &activationState)
Expand All @@ -111,7 +112,6 @@ func getActivationState(body interface{}, etag string) (model.ActivationState, e
if activationState.Spec == nil {
activationState.Spec = &model.ActivationSpec{}
}
activationState.ObjectMeta.ETag = etag
if activationState.Status == nil {
activationState.Status = &model.ActivationStatus{}
}
Expand All @@ -134,14 +134,19 @@ func (m *ActivationsManager) UpsertState(ctx context.Context, name string, state
}
state.ObjectMeta.FixNames(name)

oldState, getStateErr := m.GetState(ctx, state.ObjectMeta.Name, state.ObjectMeta.Namespace)
if getStateErr == nil {
state.ObjectMeta.PreserveSystemMetadata(oldState.ObjectMeta)
}

if m.needValidate {
if state.ObjectMeta.Labels == nil {
state.ObjectMeta.Labels = make(map[string]string)
}
if state.Spec != nil {
state.ObjectMeta.Labels[constants.Campaign] = state.Spec.Campaign
}
if err = m.ValidateCreateOrUpdate(ctx, state); err != nil {
if err = validation.ValidateCreateOrUpdateWrapper(ctx, &m.Validator, state, oldState, getStateErr); err != nil {
return err
}
}
Expand Down Expand Up @@ -221,10 +226,11 @@ func (t *ActivationsManager) ListState(ctx context.Context, namespace string) ([
ret := make([]model.ActivationState, 0)
for _, t := range activations {
var rt model.ActivationState
rt, err = getActivationState(t.Body, t.ETag)
rt, err = getActivationState(t.Body)
if err != nil {
return nil, err
}
rt.ObjectMeta.UpdateEtag(t.ETag)
ret = append(ret, rt)
}
log.InfofCtx(ctx, "List activation state for namespace %s get total count %d", namespace, len(ret))
Expand Down Expand Up @@ -259,6 +265,7 @@ func (t *ActivationsManager) ReportStatus(ctx context.Context, name string, name
var entry states.StateEntry
entry.ID = activationState.ObjectMeta.Name
entry.Body = activationState
entry.ETag = activationState.ObjectMeta.ETag // We need to set the ETag here because we need to update the labels and status

upsertRequest := states.UpsertRequest{
Value: entry,
Expand Down Expand Up @@ -312,6 +319,7 @@ func (t *ActivationsManager) ReportStageStatus(ctx context.Context, name string,
var entry states.StateEntry
entry.ID = activationState.ObjectMeta.Name
entry.Body = activationState
entry.ETag = activationState.ObjectMeta.ETag // We need to set the ETag here because we need to update the labels and status

upsertRequest := states.UpsertRequest{
Value: entry,
Expand Down Expand Up @@ -417,11 +425,6 @@ func mergeStageStatus(ctx context.Context, activationState *model.ActivationStat
return nil
}

func (t *ActivationsManager) ValidateCreateOrUpdate(ctx context.Context, state model.ActivationState) error {
old, err := t.GetState(ctx, state.ObjectMeta.Name, state.ObjectMeta.Namespace)
return validation.ValidateCreateOrUpdateWrapper(ctx, &t.Validator, state, old, err)
}

func (t *ActivationsManager) CampaignLookup(ctx context.Context, name string, namespace string) (interface{}, error) {
return states.GetObjectState(ctx, t.StateProvider, validation.Campaign, name, namespace)
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ func (t *CampaignContainersManager) UpsertState(ctx context.Context, name string
}
state.ObjectMeta.FixNames(name)

oldState, getStateErr := t.GetState(ctx, state.ObjectMeta.Name, state.ObjectMeta.Namespace)
if getStateErr == nil {
state.ObjectMeta.PreserveSystemMetadata(oldState.ObjectMeta)
}

body := map[string]interface{}{
"apiVersion": model.WorkflowGroup + "/v1",
"kind": "CampaignContainer",
Expand All @@ -89,7 +94,7 @@ func (t *CampaignContainersManager) UpsertState(ctx context.Context, name string
Value: states.StateEntry{
ID: name,
Body: body,
ETag: "",
ETag: state.ObjectMeta.ETag,
},
Metadata: map[string]interface{}{
"namespace": state.ObjectMeta.Namespace,
Expand Down Expand Up @@ -131,16 +136,17 @@ func (t *CampaignContainersManager) ListState(ctx context.Context, namespace str
ret := make([]model.CampaignContainerState, 0)
for _, t := range campaigncontainers {
var rt model.CampaignContainerState
rt, err = getCampaignContainerState(t.Body, t.ETag)
rt, err = getCampaignContainerState(t.Body)
if err != nil {
return nil, err
}
rt.ObjectMeta.UpdateEtag(t.ETag)
ret = append(ret, rt)
}
return ret, nil
}

func getCampaignContainerState(body interface{}, etag string) (model.CampaignContainerState, error) {
func getCampaignContainerState(body interface{}) (model.CampaignContainerState, error) {
var CampaignContainerState model.CampaignContainerState
bytes, _ := json.Marshal(body)
err := json.Unmarshal(bytes, &CampaignContainerState)
Expand Down Expand Up @@ -177,9 +183,10 @@ func (t *CampaignContainersManager) GetState(ctx context.Context, id string, nam
return model.CampaignContainerState{}, err
}
var ret model.CampaignContainerState
ret, err = getCampaignContainerState(Campaign.Body, Campaign.ETag)
ret, err = getCampaignContainerState(Campaign.Body)
if err != nil {
return model.CampaignContainerState{}, err
}
ret.ObjectMeta.UpdateEtag(Campaign.ETag)
return ret, nil
}
15 changes: 9 additions & 6 deletions api/pkg/apis/v1alpha1/managers/campaigns/campaigns-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func (m *CampaignsManager) GetState(ctx context.Context, name string, namespace
log.ErrorfCtx(ctx, "Failed to convert to campaign state for %s in namespace %s: %v", name, namespace, err)
return model.CampaignState{}, err
}
ret.ObjectMeta.UpdateEtag(entry.ETag)
return ret, nil
}

Expand Down Expand Up @@ -115,14 +116,19 @@ func (m *CampaignsManager) UpsertState(ctx context.Context, name string, state m
}
state.ObjectMeta.FixNames(name)

oldState, getStateErr := m.GetState(ctx, state.ObjectMeta.Name, state.ObjectMeta.Namespace)
if getStateErr == nil {
state.ObjectMeta.PreserveSystemMetadata(oldState.ObjectMeta)
}

if m.needValidate {
if state.ObjectMeta.Labels == nil {
state.ObjectMeta.Labels = make(map[string]string)
}
if state.Spec != nil {
state.ObjectMeta.Labels[constants.RootResource] = state.Spec.RootResource
}
if err = m.ValidateCreateOrUpdate(ctx, state); err != nil {
if err = validation.ValidateCreateOrUpdateWrapper(ctx, &m.CampaignValidator, state, oldState, getStateErr); err != nil {
return err
}
}
Expand All @@ -136,6 +142,7 @@ func (m *CampaignsManager) UpsertState(ctx context.Context, name string, state m
"metadata": state.ObjectMeta,
"spec": state.Spec,
},
ETag: state.ObjectMeta.ETag,
},
Metadata: map[string]interface{}{
"namespace": state.ObjectMeta.Namespace,
Expand Down Expand Up @@ -207,17 +214,13 @@ func (t *CampaignsManager) ListState(ctx context.Context, namespace string) ([]m
if err != nil {
return nil, err
}
rt.ObjectMeta.UpdateEtag(t.ETag)
ret = append(ret, rt)
}
log.InfofCtx(ctx, "List campaign state for namespace %s get total count %d", namespace, len(ret))
return ret, nil
}

func (t *CampaignsManager) ValidateCreateOrUpdate(ctx context.Context, state model.CampaignState) error {
old, err := t.GetState(ctx, state.ObjectMeta.Name, state.ObjectMeta.Namespace)
return validation.ValidateCreateOrUpdateWrapper(ctx, &t.CampaignValidator, state, old, err)
}

func (t *CampaignsManager) ValidateDelete(ctx context.Context, name string, namespace string) error {
state, err := t.GetState(ctx, name, namespace)
return validation.ValidateDeleteWrapper(ctx, &t.CampaignValidator, state, err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ func (t *CatalogContainersManager) UpsertState(ctx context.Context, name string,
}
state.ObjectMeta.FixNames(name)

oldState, getStateErr := t.GetState(ctx, state.ObjectMeta.Name, state.ObjectMeta.Namespace)
if getStateErr == nil {
state.ObjectMeta.PreserveSystemMetadata(oldState.ObjectMeta)
}

body := map[string]interface{}{
"apiVersion": model.FederationGroup + "/v1",
"kind": "CatalogContainer",
Expand All @@ -89,7 +94,7 @@ func (t *CatalogContainersManager) UpsertState(ctx context.Context, name string,
Value: states.StateEntry{
ID: name,
Body: body,
ETag: "",
ETag: state.ObjectMeta.ETag,
},
Metadata: map[string]interface{}{
"namespace": state.ObjectMeta.Namespace,
Expand Down Expand Up @@ -131,16 +136,17 @@ func (t *CatalogContainersManager) ListState(ctx context.Context, namespace stri
ret := make([]model.CatalogContainerState, 0)
for _, t := range catalogcontainers {
var rt model.CatalogContainerState
rt, err = getCatalogContainerState(t.Body, t.ETag)
rt, err = getCatalogContainerState(t.Body)
if err != nil {
return nil, err
}
rt.ObjectMeta.UpdateEtag(t.ETag)
ret = append(ret, rt)
}
return ret, nil
}

func getCatalogContainerState(body interface{}, etag string) (model.CatalogContainerState, error) {
func getCatalogContainerState(body interface{}) (model.CatalogContainerState, error) {
var CatalogContainerState model.CatalogContainerState
bytes, _ := json.Marshal(body)
err := json.Unmarshal(bytes, &CatalogContainerState)
Expand Down Expand Up @@ -171,15 +177,16 @@ func (t *CatalogContainersManager) GetState(ctx context.Context, id string, name
"kind": "CatalogContainer",
},
}
var Campaign states.StateEntry
Campaign, err = t.StateProvider.Get(ctx, getRequest)
var entry states.StateEntry
entry, err = t.StateProvider.Get(ctx, getRequest)
if err != nil {
return model.CatalogContainerState{}, err
}
var ret model.CatalogContainerState
ret, err = getCatalogContainerState(Campaign.Body, Campaign.ETag)
ret, err = getCatalogContainerState(entry.Body)
if err != nil {
return model.CatalogContainerState{}, err
}
ret.ObjectMeta.UpdateEtag(entry.ETag)
return ret, nil
}
21 changes: 11 additions & 10 deletions api/pkg/apis/v1alpha1/managers/catalogs/catalogs-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,15 @@ func (s *CatalogsManager) GetState(ctx context.Context, name string, namespace s
return model.CatalogState{}, err
}
var ret model.CatalogState
ret, err = getCatalogState(entry.Body, entry.ETag)
ret, err = getCatalogState(entry.Body)
if err != nil {
return model.CatalogState{}, err
}
ret.ObjectMeta.UpdateEtag(entry.ETag)
return ret, nil
}

func getCatalogState(body interface{}, etag string) (model.CatalogState, error) {
func getCatalogState(body interface{}) (model.CatalogState, error) {
var catalogState model.CatalogState
bytes, _ := json.Marshal(body)
err := json.Unmarshal(bytes, &catalogState)
Expand All @@ -102,7 +103,6 @@ func getCatalogState(body interface{}, etag string) (model.CatalogState, error)
if catalogState.Spec == nil {
catalogState.Spec = &model.CatalogSpec{}
}
catalogState.ObjectMeta.ETag = etag
if catalogState.Status == nil {
catalogState.Status = &model.CatalogStatus{}
}
Expand All @@ -122,6 +122,11 @@ func (m *CatalogsManager) UpsertState(ctx context.Context, name string, state mo
}
state.ObjectMeta.FixNames(name)

oldState, getStateErr := m.GetState(ctx, state.ObjectMeta.Name, state.ObjectMeta.Namespace)
if getStateErr == nil {
state.ObjectMeta.PreserveSystemMetadata(oldState.ObjectMeta)
}

if m.needValidate {
if state.ObjectMeta.Labels == nil {
state.ObjectMeta.Labels = make(map[string]string)
Expand All @@ -132,7 +137,7 @@ func (m *CatalogsManager) UpsertState(ctx context.Context, name string, state mo
state.ObjectMeta.Labels[constants.ParentName] = validation.ConvertReferenceToObjectName(state.Spec.ParentName)
}
}
if err = m.ValidateCreateOrUpdate(ctx, state); err != nil {
if err = validation.ValidateCreateOrUpdateWrapper(ctx, &m.CatalogValidator, state, oldState, getStateErr); err != nil {
return err
}
}
Expand Down Expand Up @@ -229,10 +234,11 @@ func (t *CatalogsManager) ListState(ctx context.Context, namespace string, filte
ret := make([]model.CatalogState, 0)
for _, t := range catalogs {
var rt model.CatalogState
rt, err = getCatalogState(t.Body, t.ETag)
rt, err = getCatalogState(t.Body)
if err != nil {
return nil, err
}
rt.ObjectMeta.UpdateEtag(t.ETag)
ret = append(ret, rt)
}
return ret, nil
Expand Down Expand Up @@ -303,11 +309,6 @@ func (g *CatalogsManager) GetTrees(ctx context.Context, filter string, namespace
return res, nil
}

func (t *CatalogsManager) ValidateCreateOrUpdate(ctx context.Context, state model.CatalogState) error {
old, err := t.GetState(ctx, state.ObjectMeta.Name, state.ObjectMeta.Namespace)
return validation.ValidateCreateOrUpdateWrapper(ctx, &t.CatalogValidator, state, old, err)
}

func (t *CatalogsManager) ValidateDelete(ctx context.Context, name string, namespace string) error {
state, err := t.GetState(ctx, name, namespace)
return validation.ValidateDeleteWrapper(ctx, &t.CatalogValidator, state, err)
Expand Down
Loading

0 comments on commit fc3328f

Please sign in to comment.