Skip to content

Commit 048e886

Browse files
committed
add apply/preview/destroy flag: inventory-policy
1 parent 1f65c10 commit 048e886

File tree

11 files changed

+89
-17
lines changed

11 files changed

+89
-17
lines changed

cmd/apply/cmdapply.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ import (
1414
"k8s.io/cli-runtime/pkg/genericclioptions"
1515
cmdutil "k8s.io/kubectl/pkg/cmd/util"
1616
"k8s.io/kubectl/pkg/util/i18n"
17+
"sigs.k8s.io/cli-utils/cmd/flagutils"
1718
"sigs.k8s.io/cli-utils/cmd/printers"
1819
"sigs.k8s.io/cli-utils/pkg/apply"
1920
"sigs.k8s.io/cli-utils/pkg/common"
20-
"sigs.k8s.io/cli-utils/pkg/inventory"
2121
"sigs.k8s.io/cli-utils/pkg/manifestreader"
2222
"sigs.k8s.io/cli-utils/pkg/provider"
2323
)
@@ -55,6 +55,9 @@ func GetApplyRunner(provider provider.Provider, loader manifestreader.ManifestLo
5555
"Background", "Propagation policy for pruning")
5656
cmd.Flags().DurationVar(&r.pruneTimeout, "prune-timeout", time.Duration(0),
5757
"Timeout threshold for waiting for all pruned resources to be deleted")
58+
cmd.Flags().StringVar(&r.inventoryPolicy, "inventory-policy", "strict",
59+
"It determines the behavior when the resources don't belong to current inventory. Available options "+
60+
"\"strict\" and \"adopt\".")
5861

5962
r.Command = cmd
6063
return r
@@ -80,13 +83,18 @@ type ApplyRunner struct {
8083
noPrune bool
8184
prunePropagationPolicy string
8285
pruneTimeout time.Duration
86+
inventoryPolicy string
8387
}
8488

8589
func (r *ApplyRunner) RunE(cmd *cobra.Command, args []string) error {
8690
prunePropPolicy, err := convertPropagationPolicy(r.prunePropagationPolicy)
8791
if err != nil {
8892
return err
8993
}
94+
inventoryPolicy, err := flagutils.ConvertInventoryPolicy(r.inventoryPolicy)
95+
if err != nil {
96+
return err
97+
}
9098

9199
// Only emit status events if we are waiting for status.
92100
//TODO: This is not the right way to do this. There are situations where
@@ -133,7 +141,7 @@ func (r *ApplyRunner) RunE(cmd *cobra.Command, args []string) error {
133141
DryRunStrategy: common.DryRunNone,
134142
PrunePropagationPolicy: prunePropPolicy,
135143
PruneTimeout: r.pruneTimeout,
136-
InventoryPolicy: inventory.AdoptIfNoInventory,
144+
InventoryPolicy: inventoryPolicy,
137145
})
138146

139147
// The printer will print updates from the channel. It will block

cmd/destroy/cmddestroy.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"k8s.io/cli-runtime/pkg/genericclioptions"
1212
cmdutil "k8s.io/kubectl/pkg/cmd/util"
1313
"k8s.io/kubectl/pkg/util/i18n"
14+
"sigs.k8s.io/cli-utils/cmd/flagutils"
1415
"sigs.k8s.io/cli-utils/cmd/printers"
1516
"sigs.k8s.io/cli-utils/pkg/apply"
1617
"sigs.k8s.io/cli-utils/pkg/manifestreader"
@@ -34,6 +35,9 @@ func GetDestroyRunner(provider provider.Provider, loader manifestreader.Manifest
3435

3536
cmd.Flags().StringVar(&r.output, "output", printers.DefaultPrinter(),
3637
fmt.Sprintf("Output format, must be one of %s", strings.Join(printers.SupportedPrinters(), ",")))
38+
cmd.Flags().StringVar(&r.inventoryPolicy, "inventory-policy", "strict",
39+
"It determines the behavior when the resources don't belong to current inventory. Available options "+
40+
"\"strict\" and \"adopt\".")
3741

3842
r.Command = cmd
3943
return r
@@ -54,10 +58,16 @@ type DestroyRunner struct {
5458
provider provider.Provider
5559
loader manifestreader.ManifestLoader
5660

57-
output string
61+
output string
62+
inventoryPolicy string
5863
}
5964

6065
func (r *DestroyRunner) RunE(cmd *cobra.Command, args []string) error {
66+
inventoryPolicy, err := flagutils.ConvertInventoryPolicy(r.inventoryPolicy)
67+
if err != nil {
68+
return err
69+
}
70+
6171
// Retrieve the inventory object.
6272
reader, err := r.loader.ManifestReader(cmd.InOrStdin(), args)
6373
if err != nil {
@@ -78,7 +88,10 @@ func (r *DestroyRunner) RunE(cmd *cobra.Command, args []string) error {
7888
if err != nil {
7989
return err
8090
}
81-
ch := r.Destroyer.Run(inv)
91+
option := &apply.DestroyerOption{
92+
InventoryPolicy: inventoryPolicy,
93+
}
94+
ch := r.Destroyer.Run(inv, option)
8295

8396
// The printer will print updates from the channel. It will block
8497
// until the channel is closed.

cmd/flagutils/utils.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2021 The Kubernetes Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package flagutils
5+
6+
import (
7+
"fmt"
8+
9+
"sigs.k8s.io/cli-utils/pkg/inventory"
10+
)
11+
12+
func ConvertInventoryPolicy(policy string) (inventory.InventoryPolicy, error) {
13+
switch policy {
14+
case "strict":
15+
return inventory.InventoryPolicyMustMatch, nil
16+
case "adopt":
17+
return inventory.AdoptIfNoInventory, nil
18+
default:
19+
return inventory.InventoryPolicyMustMatch, fmt.Errorf(
20+
"inventory policy must be one of strict, adopt")
21+
}
22+
}

cmd/preview/cmdpreview.go

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ import (
1212
"k8s.io/cli-runtime/pkg/genericclioptions"
1313
cmdutil "k8s.io/kubectl/pkg/cmd/util"
1414
"k8s.io/kubectl/pkg/util/i18n"
15+
"sigs.k8s.io/cli-utils/cmd/flagutils"
1516
"sigs.k8s.io/cli-utils/cmd/printers"
1617
"sigs.k8s.io/cli-utils/pkg/apply"
1718
"sigs.k8s.io/cli-utils/pkg/apply/event"
1819
"sigs.k8s.io/cli-utils/pkg/common"
19-
"sigs.k8s.io/cli-utils/pkg/inventory"
2020
"sigs.k8s.io/cli-utils/pkg/manifestreader"
2121
"sigs.k8s.io/cli-utils/pkg/provider"
2222
)
@@ -53,6 +53,9 @@ func GetPreviewRunner(provider provider.Provider, loader manifestreader.Manifest
5353
cmd.Flags().BoolVar(&previewDestroy, "destroy", previewDestroy, "If true, preview of destroy operations will be displayed.")
5454
cmd.Flags().StringVar(&r.output, "output", printers.DefaultPrinter(),
5555
fmt.Sprintf("Output format, must be one of %s", strings.Join(printers.SupportedPrinters(), ",")))
56+
cmd.Flags().StringVar(&r.inventoryPolicy, "inventory-policy", "strict",
57+
"It determines the behavior when the resources don't belong to current inventory. Available options "+
58+
"\"strict\" and \"adopt\".")
5659

5760
r.Command = cmd
5861
return r
@@ -76,6 +79,7 @@ type PreviewRunner struct {
7679

7780
serverSideOptions common.ServerSideOptions
7881
output string
82+
inventoryPolicy string
7983
}
8084

8185
// RunE is the function run from the cobra command.
@@ -91,6 +95,11 @@ func (r *PreviewRunner) RunE(cmd *cobra.Command, args []string) error {
9195
r.Destroyer.DryRunStrategy = drs
9296
}
9397

98+
inventoryPolicy, err := flagutils.ConvertInventoryPolicy(r.inventoryPolicy)
99+
if err != nil {
100+
return err
101+
}
102+
94103
reader, err := r.loader.ManifestReader(cmd.InOrStdin(), args)
95104
if err != nil {
96105
return err
@@ -128,14 +137,17 @@ func (r *PreviewRunner) RunE(cmd *cobra.Command, args []string) error {
128137
NoPrune: noPrune,
129138
DryRunStrategy: drs,
130139
ServerSideOptions: r.serverSideOptions,
131-
InventoryPolicy: inventory.AdoptIfNoInventory,
140+
InventoryPolicy: inventoryPolicy,
132141
})
133142
} else {
134143
err = r.Destroyer.Initialize()
135144
if err != nil {
136145
return err
137146
}
138-
ch = r.Destroyer.Run(inv)
147+
option := &apply.DestroyerOption{
148+
InventoryPolicy: inventoryPolicy,
149+
}
150+
ch = r.Destroyer.Run(inv, option)
139151
}
140152

141153
// The printer will print updates from the channel. It will block

pkg/apply/destroyer.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ type Destroyer struct {
3939
DryRunStrategy common.DryRunStrategy
4040
}
4141

42+
type DestroyerOption struct {
43+
InventoryPolicy inventory.InventoryPolicy
44+
}
45+
4246
// Initialize sets up the Destroyer for actually doing an destroy against
4347
// a cluster. This involves validating command line inputs and configuring
4448
// clients for communicating with the cluster.
@@ -59,7 +63,7 @@ func (d *Destroyer) Initialize() error {
5963
// Run performs the destroy step. Passes the inventory object. This
6064
// happens asynchronously on progress and any errors are reported
6165
// back on the event channel.
62-
func (d *Destroyer) Run(inv inventory.InventoryInfo) <-chan event.Event {
66+
func (d *Destroyer) Run(inv inventory.InventoryInfo, option *DestroyerOption) <-chan event.Event {
6367
ch := make(chan event.Event)
6468

6569
go func() {
@@ -75,6 +79,7 @@ func (d *Destroyer) Run(inv inventory.InventoryInfo) <-chan event.Event {
7579
err := d.PruneOptions.Prune(inv, nil, sets.NewString(), taskContext, prune.Options{
7680
DryRunStrategy: d.DryRunStrategy,
7781
PropagationPolicy: metav1.DeletePropagationBackground,
82+
InventoryPolicy: option.InventoryPolicy,
7883
})
7984
if err != nil {
8085
ch <- event.Event{

pkg/inventory/fake-inventory-client.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,3 +81,7 @@ func (fic *FakeInventoryClient) SetError(err error) {
8181
func (fic *FakeInventoryClient) ClearError() {
8282
fic.Err = nil
8383
}
84+
85+
func (fic *FakeInventoryClient) GetClusterInventoryInfo(inv InventoryInfo) (*unstructured.Unstructured, error) {
86+
return nil, nil
87+
}

pkg/inventory/inventory-client.go

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ type InventoryClient interface {
4242
SetDryRunStrategy(drs common.DryRunStrategy)
4343
// ApplyInventoryNamespace applies the Namespace that the inventory object should be in.
4444
ApplyInventoryNamespace(invNamespace *unstructured.Unstructured) error
45+
// GetClusterInventoryInfo returns the cluster inventory object.
46+
GetClusterInventoryInfo(inv InventoryInfo) (*unstructured.Unstructured, error)
4547
}
4648

4749
// ClusterInventoryClient is a concrete implementation of the
@@ -97,7 +99,7 @@ func NewInventoryClient(factory cmdutil.Factory,
9799
func (cic *ClusterInventoryClient) Merge(localInv InventoryInfo, objs []object.ObjMetadata) ([]object.ObjMetadata, error) {
98100
pruneIds := []object.ObjMetadata{}
99101
invObj := cic.invToUnstructuredFunc(localInv)
100-
clusterInv, err := cic.getClusterInventoryInfo(invObj)
102+
clusterInv, err := cic.GetClusterInventoryInfo(localInv)
101103
if err != nil {
102104
return pruneIds, err
103105
}
@@ -164,7 +166,7 @@ func (cic *ClusterInventoryClient) Replace(localInv InventoryInfo, objs []object
164166
klog.V(4).Infof("applied objects same as cluster inventory: do nothing")
165167
return nil
166168
}
167-
clusterInv, err := cic.getClusterInventoryInfo(cic.invToUnstructuredFunc(localInv))
169+
clusterInv, err := cic.GetClusterInventoryInfo(localInv)
168170
if err != nil {
169171
return err
170172
}
@@ -202,8 +204,7 @@ func (cic *ClusterInventoryClient) DeleteInventoryObj(localInv InventoryInfo) er
202204
// an error if one occurred.
203205
func (cic *ClusterInventoryClient) GetClusterObjs(localInv InventoryInfo) ([]object.ObjMetadata, error) {
204206
var objs []object.ObjMetadata
205-
invObj := cic.invToUnstructuredFunc(localInv)
206-
clusterInv, err := cic.getClusterInventoryInfo(invObj)
207+
clusterInv, err := cic.GetClusterInventoryInfo(localInv)
207208
if err != nil {
208209
return objs, err
209210
}
@@ -224,7 +225,8 @@ func (cic *ClusterInventoryClient) GetClusterObjs(localInv InventoryInfo) ([]obj
224225
//
225226
// TODO(seans3): Remove the special case code to merge multiple cluster inventory
226227
// objects once we've determined that this case is no longer possible.
227-
func (cic *ClusterInventoryClient) getClusterInventoryInfo(localInv *unstructured.Unstructured) (*unstructured.Unstructured, error) {
228+
func (cic *ClusterInventoryClient) GetClusterInventoryInfo(inv InventoryInfo) (*unstructured.Unstructured, error) {
229+
localInv := cic.invToUnstructuredFunc(inv)
228230
if localInv == nil {
229231
return nil, fmt.Errorf("retrieving cluster inventory object with nil local inventory")
230232
}

pkg/inventory/inventory-client_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ func TestGetClusterInventoryInfo(t *testing.T) {
6666
if tc.inv != nil {
6767
inv = storeObjsInInventory(tc.inv, tc.localObjs)
6868
}
69-
clusterInv, err := invClient.getClusterInventoryInfo(inv)
69+
clusterInv, err := invClient.GetClusterInventoryInfo(WrapInventoryInfoObj(inv))
7070
if tc.isError {
7171
if err == nil {
7272
t.Fatalf("expected error but received none")

test/e2e/apply_and_destroy_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1313
"sigs.k8s.io/cli-utils/pkg/apply"
1414
"sigs.k8s.io/cli-utils/pkg/apply/event"
15+
"sigs.k8s.io/cli-utils/pkg/inventory"
1516
"sigs.k8s.io/controller-runtime/pkg/client"
1617
)
1718

@@ -57,7 +58,8 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
5758
By("Destroy resources")
5859
destroyer := invConfig.DestroyerFactoryFunc()
5960

60-
destroyerEvents := runCollectNoErr(destroyer.Run(inv))
61+
option := &apply.DestroyerOption{InventoryPolicy: inventory.AdoptIfNoInventory}
62+
destroyerEvents := runCollectNoErr(destroyer.Run(inv, option))
6163
err = verifyEvents([]expEvent{
6264
{
6365
eventType: event.DeleteType,

test/e2e/continue_on_error_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1414
"sigs.k8s.io/cli-utils/pkg/apply"
1515
"sigs.k8s.io/cli-utils/pkg/apply/event"
16+
"sigs.k8s.io/cli-utils/pkg/inventory"
1617
"sigs.k8s.io/cli-utils/pkg/object"
1718
"sigs.k8s.io/controller-runtime/pkg/client"
1819
)
@@ -68,7 +69,8 @@ func continueOnErrorTest(_ client.Client, invConfig InventoryConfig, inventoryNa
6869

6970
By("destroy the resources")
7071
destroyer := invConfig.DestroyerFactoryFunc()
71-
destroyerEvents := runCollectNoErr(destroyer.Run(inv))
72+
option := &apply.DestroyerOption{InventoryPolicy: inventory.AdoptIfNoInventory}
73+
destroyerEvents := runCollectNoErr(destroyer.Run(inv, option))
7274
err = verifyEvents([]expEvent{
7375
{
7476
eventType: event.DeleteType,

0 commit comments

Comments
 (0)