Skip to content

Commit

Permalink
Add filter for apps for which ownership can be overriden
Browse files Browse the repository at this point in the history
Signed-off-by: Soumik Majumder <[email protected]>
  • Loading branch information
100mik committed Aug 5, 2024
1 parent 7f5711f commit d51cc7c
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 2 deletions.
12 changes: 12 additions & 0 deletions pkg/kapp/cmd/app/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -382,15 +382,27 @@ func (o *DeployOptions) existingResources(newResources []ctlres.Resource,
return ""
}

labelValAppMapResolver := func() map[string]string {
items, _ := apps.List(nil)
appLabelMap := map[string]string{}
for _, item := range items {
meta, _ := item.Meta()
appLabelMap[meta.LabelValue] = item.Name()
}
return appLabelMap
}

matchingOpts := ctlres.AllAndMatchingOpts{
ExistingNonLabeledResourcesCheck: o.DeployFlags.ExistingNonLabeledResourcesCheck,
ExistingNonLabeledResourcesCheckConcurrency: o.DeployFlags.ExistingNonLabeledResourcesCheckConcurrency,
SkipResourceOwnershipCheck: o.DeployFlags.OverrideOwnershipOfExistingResources,
SkipOwnershipCheckAllowedApps: o.DeployFlags.OwnershipOverrideAllowedApps,
IsNewApp: isNewApp,

// Prevent accidently overriding kapp state records
DisallowedResourcesByLabelKeys: []string{ctlapp.KappIsAppLabelKey},
LabelErrorResolutionFunc: labelErrorResolutionFunc,
LabelValAppMapResolverFunc: labelValAppMapResolver,

//Scope resource searching to UsedGKs
IdentifiedResourcesListOpts: ctlres.IdentifiedResourcesListOpts{
Expand Down
3 changes: 3 additions & 0 deletions pkg/kapp/cmd/app/deploy_flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type DeployFlags struct {
ExistingNonLabeledResourcesCheck bool
ExistingNonLabeledResourcesCheckConcurrency int
OverrideOwnershipOfExistingResources bool
OwnershipOverrideAllowedApps []string

AppChangesMaxToKeep int

Expand Down Expand Up @@ -48,6 +49,8 @@ func (s *DeployFlags) Set(cmd *cobra.Command) {
100, "Concurrency to check for existing non-labeled resources")
cmd.Flags().BoolVar(&s.OverrideOwnershipOfExistingResources, "dangerous-override-ownership-of-existing-resources",
false, "Steal existing resources from another app")
cmd.Flags().StringSliceVar(&s.OwnershipOverrideAllowedApps, "ownership-override-allowed-apps", nil,
"Specify existing apps in the same namespace that existing resources can be stolen from if --dangerous-override-ownership-of-existing-resources is set")

cmd.Flags().BoolVar(&s.DefaultLabelScopingRules, "default-label-scoping-rules",
true, "Use default label scoping rules")
Expand Down
30 changes: 28 additions & 2 deletions pkg/kapp/resources/labeled_resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package resources

import (
"fmt"
"slices"
"strings"
"sync"

Expand Down Expand Up @@ -93,10 +94,12 @@ type AllAndMatchingOpts struct {
ExistingNonLabeledResourcesCheck bool
ExistingNonLabeledResourcesCheckConcurrency int
SkipResourceOwnershipCheck bool
SkipOwnershipCheckAllowedApps []string
IsNewApp bool

DisallowedResourcesByLabelKeys []string
LabelErrorResolutionFunc func(string, string) string
LabelValAppMapResolverFunc func() map[string]string

IdentifiedResourcesListOpts IdentifiedResourcesListOpts
}
Expand Down Expand Up @@ -131,7 +134,8 @@ func (a *LabeledResources) AllAndMatching(newResources []Resource, opts AllAndMa
}
}

if !opts.SkipResourceOwnershipCheck && len(nonLabeledResources) > 0 {
if len(nonLabeledResources) > 0 && (!opts.SkipResourceOwnershipCheck ||
(opts.SkipResourceOwnershipCheck && len(opts.SkipOwnershipCheckAllowedApps) > 0)) {
resourcesForCheck := a.resourcesForOwnershipCheck(newResources, nonLabeledResources)
if len(resourcesForCheck) > 0 {
err := a.checkResourceOwnership(resourcesForCheck, opts)
Expand Down Expand Up @@ -180,10 +184,19 @@ func (a *LabeledResources) checkResourceOwnership(resources []Resource, opts All
}

var errs []error
labelValAppMap := map[string]string{}
if len(opts.SkipOwnershipCheckAllowedApps) > 0 && opts.SkipResourceOwnershipCheck {
labelValAppMap = opts.LabelValAppMapResolverFunc()
}

for _, res := range resources {
if val, found := res.Labels()[expectedLabelKey]; found {
if val != expectedLabelVal {
ownershipOverrideAllowed := false
if opts.SkipResourceOwnershipCheck {
ownershipOverrideAllowed = a.ownershipOverrideAllowed(labelValAppMap, res,
expectedLabelKey, opts.SkipOwnershipCheckAllowedApps)
}
if val != expectedLabelVal && !ownershipOverrideAllowed {
ownerMsg := fmt.Sprintf("different label '%s=%s'", expectedLabelKey, val)
if opts.LabelErrorResolutionFunc != nil {
ownerMsgSuggested := opts.LabelErrorResolutionFunc(expectedLabelKey, val)
Expand All @@ -208,6 +221,19 @@ func (a *LabeledResources) checkResourceOwnership(resources []Resource, opts All
return nil
}

func (a *LabeledResources) ownershipOverrideAllowed(labelValAppMap map[string]string, res Resource,
expectedLabelKey string, overrideAllowedApps []string) bool {
labelVal, found := res.Labels()[expectedLabelKey]
if !found {
return true
}
appName, found := labelValAppMap[labelVal]
if !found {
return false
}
return slices.Contains(overrideAllowedApps, appName)
}

func (a *LabeledResources) checkDisallowedLabels(resources []Resource, disallowedLblKeys []string) error {
var errs []error

Expand Down

0 comments on commit d51cc7c

Please sign in to comment.