1
2
3
4 package apply
5
6 import (
7 "context"
8 "fmt"
9 "strings"
10 "time"
11
12 "github.com/spf13/cobra"
13 "k8s.io/cli-runtime/pkg/genericclioptions"
14 cmdutil "k8s.io/kubectl/pkg/cmd/util"
15 "k8s.io/kubectl/pkg/util/i18n"
16 "sigs.k8s.io/cli-utils/cmd/flagutils"
17 "sigs.k8s.io/cli-utils/pkg/apply"
18 "sigs.k8s.io/cli-utils/pkg/common"
19 "sigs.k8s.io/cli-utils/pkg/inventory"
20 "sigs.k8s.io/cli-utils/pkg/manifestreader"
21 "sigs.k8s.io/cli-utils/pkg/printers"
22 )
23
24 func GetRunner(factory cmdutil.Factory, invFactory inventory.ClientFactory,
25 loader manifestreader.ManifestLoader, ioStreams genericclioptions.IOStreams) *Runner {
26 r := &Runner{
27 ioStreams: ioStreams,
28 factory: factory,
29 invFactory: invFactory,
30 loader: loader,
31 }
32 cmd := &cobra.Command{
33 Use: "apply (DIRECTORY | STDIN)",
34 DisableFlagsInUseLine: true,
35 Short: i18n.T("Apply a configuration to a resource by package directory or stdin"),
36 RunE: r.RunE,
37 }
38
39 cmd.Flags().BoolVar(&r.serverSideOptions.ServerSideApply, "server-side", false,
40 "If true, apply merge patch is calculated on API server instead of client.")
41 cmd.Flags().BoolVar(&r.serverSideOptions.ForceConflicts, "force-conflicts", false,
42 "If true, overwrite applied fields on server if field manager conflict.")
43 cmd.Flags().StringVar(&r.serverSideOptions.FieldManager, "field-manager", common.DefaultFieldManager,
44 "The client owner of the fields being applied on the server-side.")
45
46 cmd.Flags().StringVar(&r.output, "output", printers.DefaultPrinter(),
47 fmt.Sprintf("Output format, must be one of %s", strings.Join(printers.SupportedPrinters(), ",")))
48 cmd.Flags().DurationVar(&r.reconcileTimeout, "reconcile-timeout", time.Duration(0),
49 "Timeout threshold for waiting for all resources to reach the Current status.")
50 cmd.Flags().BoolVar(&r.noPrune, "no-prune", r.noPrune,
51 "If true, do not prune previously applied objects.")
52 cmd.Flags().StringVar(&r.prunePropagationPolicy, "prune-propagation-policy",
53 "Background", "Propagation policy for pruning")
54 cmd.Flags().DurationVar(&r.pruneTimeout, "prune-timeout", time.Duration(0),
55 "Timeout threshold for waiting for all pruned resources to be deleted")
56 cmd.Flags().StringVar(&r.inventoryPolicy, flagutils.InventoryPolicyFlag, flagutils.InventoryPolicyStrict,
57 "It determines the behavior when the resources don't belong to current inventory. Available options "+
58 fmt.Sprintf("%q, %q and %q.", flagutils.InventoryPolicyStrict, flagutils.InventoryPolicyAdopt, flagutils.InventoryPolicyForceAdopt))
59 cmd.Flags().DurationVar(&r.timeout, "timeout", 0,
60 "How long to wait before exiting")
61 cmd.Flags().BoolVar(&r.printStatusEvents, "status-events", false,
62 "Print status events (always enabled for table output)")
63
64 r.Command = cmd
65 return r
66 }
67
68 func Command(f cmdutil.Factory, invFactory inventory.ClientFactory, loader manifestreader.ManifestLoader,
69 ioStreams genericclioptions.IOStreams) *cobra.Command {
70 return GetRunner(f, invFactory, loader, ioStreams).Command
71 }
72
73 type Runner struct {
74 Command *cobra.Command
75 ioStreams genericclioptions.IOStreams
76 factory cmdutil.Factory
77 invFactory inventory.ClientFactory
78 loader manifestreader.ManifestLoader
79
80 serverSideOptions common.ServerSideOptions
81 output string
82 reconcileTimeout time.Duration
83 noPrune bool
84 prunePropagationPolicy string
85 pruneTimeout time.Duration
86 inventoryPolicy string
87 timeout time.Duration
88 printStatusEvents bool
89 }
90
91 func (r *Runner) RunE(cmd *cobra.Command, args []string) error {
92 ctx := cmd.Context()
93
94 if r.timeout != 0 {
95 var cancel context.CancelFunc
96 ctx, cancel = context.WithTimeout(ctx, r.timeout)
97 defer cancel()
98 }
99
100 prunePropPolicy, err := flagutils.ConvertPropagationPolicy(r.prunePropagationPolicy)
101 if err != nil {
102 return err
103 }
104 inventoryPolicy, err := flagutils.ConvertInventoryPolicy(r.inventoryPolicy)
105 if err != nil {
106 return err
107 }
108
109 if found := printers.ValidatePrinterType(r.output); !found {
110 return fmt.Errorf("unknown output type %q", r.output)
111 }
112
113
114
115 _, err = common.DemandOneDirectory(args)
116 if err != nil {
117 return err
118 }
119 reader, err := r.loader.ManifestReader(cmd.InOrStdin(), flagutils.PathFromArgs(args))
120 if err != nil {
121 return err
122 }
123 objs, err := reader.Read()
124 if err != nil {
125 return err
126 }
127
128 invObj, objs, err := inventory.SplitUnstructureds(objs)
129 if err != nil {
130 return err
131 }
132 inv := inventory.WrapInventoryInfoObj(invObj)
133
134 invClient, err := r.invFactory.NewClient(r.factory)
135 if err != nil {
136 return err
137 }
138
139
140
141 a, err := apply.NewApplierBuilder().
142 WithFactory(r.factory).
143 WithInventoryClient(invClient).
144 Build()
145 if err != nil {
146 return err
147 }
148
149
150 if r.output == printers.TablePrinter {
151 r.printStatusEvents = true
152 }
153
154 ch := a.Run(ctx, inv, objs, apply.ApplierOptions{
155 ServerSideOptions: r.serverSideOptions,
156 ReconcileTimeout: r.reconcileTimeout,
157
158
159 EmitStatusEvents: r.printStatusEvents,
160 NoPrune: r.noPrune,
161 DryRunStrategy: common.DryRunNone,
162 PrunePropagationPolicy: prunePropPolicy,
163 PruneTimeout: r.pruneTimeout,
164 InventoryPolicy: inventoryPolicy,
165 })
166
167
168
169 printer := printers.GetPrinter(r.output, r.ioStreams)
170 return printer.Print(ch, common.DryRunNone, r.printStatusEvents)
171 }
172
View as plain text