Skip to content

Commit cf4f629

Browse files
authored
Merge pull request #275 from justinsb/take_objects_not_strings
Change ApplierOptions to take Objects, not a manifest.
2 parents ecacd65 + 24d9bea commit cf4f629

File tree

9 files changed

+97
-58
lines changed

9 files changed

+97
-58
lines changed

pkg/patterns/declarative/metrics_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ func TestAddIfNotPresent(t *testing.T) {
525525
if st.actions[i] == "Create" || st.actions[i] == "Update" {
526526
var options applier.ApplierOptions
527527
options.Namespace = st.defaultNamespace
528-
options.Manifest = yobj
528+
options.Objects = objList
529529
options.RESTMapper = restMapper
530530
options.RESTConfig = restConfig
531531
applier := applier.NewApplySetApplier(metav1.PatchOptions{FieldManager: "kdp-test"})

pkg/patterns/declarative/pkg/applier/applylib.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"k8s.io/client-go/dynamic"
1010

1111
"sigs.k8s.io/kubebuilder-declarative-pattern/applylib/applyset"
12-
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
1312
)
1413

1514
type ApplySetApplier struct {
@@ -23,10 +22,6 @@ func NewApplySetApplier(patchOptions metav1.PatchOptions) *ApplySetApplier {
2322
}
2423

2524
func (a *ApplySetApplier) Apply(ctx context.Context, opt ApplierOptions) error {
26-
objects, err := manifest.ParseObjects(ctx, opt.Manifest)
27-
if err != nil {
28-
return fmt.Errorf("error parsing manifest: %w", err)
29-
}
3025

3126
patchOptions := a.patchOptions
3227

@@ -61,7 +56,7 @@ func (a *ApplySetApplier) Apply(ctx context.Context, opt ApplierOptions) error {
6156

6257
// Populate the namespace on any namespace-scoped objects
6358
if opt.Namespace != "" {
64-
for _, obj := range objects.Items {
59+
for _, obj := range opt.Objects {
6560
gvk := obj.GroupVersionKind()
6661
restMapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
6762
if err != nil {
@@ -81,7 +76,7 @@ func (a *ApplySetApplier) Apply(ctx context.Context, opt ApplierOptions) error {
8176
}
8277

8378
var applyableObjects []applyset.ApplyableObject
84-
for _, obj := range objects.Items {
79+
for _, obj := range opt.Objects {
8580
applyableObject := obj.UnstructuredObject()
8681
applyableObjects = append(applyableObjects, applyableObject)
8782
}

pkg/patterns/declarative/pkg/applier/applylib_test.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"k8s.io/client-go/rest"
1515
"k8s.io/klog/v2"
1616
"sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver"
17+
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
1718
controllerrestmapper "sigs.k8s.io/kubebuilder-declarative-pattern/pkg/restmapper"
1819
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/test/httprecorder"
1920
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/test/testharness"
@@ -69,15 +70,20 @@ func runApplierGoldenTests(t *testing.T, testDir string, interceptHTTPServer boo
6970
t.Fatalf("error precreating objects: %v", err)
7071
}
7172
}
72-
manifest := string(h.MustReadFile(filepath.Join(testdir, "manifest.yaml")))
73+
p := filepath.Join(testdir, "manifest.yaml")
74+
manifestYAML := string(h.MustReadFile(p))
75+
objects, err := manifest.ParseObjects(ctx, manifestYAML)
76+
if err != nil {
77+
t.Errorf("error parsing manifest %q: %v", p, err)
78+
}
7379

7480
restMapper, err := controllerrestmapper.NewControllerRESTMapper(restConfig)
7581
if err != nil {
7682
t.Fatalf("error from controllerrestmapper.NewControllerRESTMapper: %v", err)
7783
}
7884

7985
options := ApplierOptions{
80-
Manifest: manifest,
86+
Objects: objects.GetItems(),
8187
RESTConfig: restConfig,
8288
RESTMapper: restMapper,
8389
}

pkg/patterns/declarative/pkg/applier/direct.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"k8s.io/kubectl/pkg/cmd/apply"
2121
cmdDelete "k8s.io/kubectl/pkg/cmd/delete"
2222
cmdutil "k8s.io/kubectl/pkg/cmd/util"
23+
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
2324
)
2425

2526
type DirectApplier struct {
@@ -68,12 +69,18 @@ func NewDirectApplier() Applier {
6869
}
6970

7071
func (d *DirectApplier) Apply(ctx context.Context, opt ApplierOptions) error {
72+
objects := manifest.Objects{Items: opt.Objects}
73+
manifestStr, err := objects.JSONManifest()
74+
if err != nil {
75+
return fmt.Errorf("error creating JSON manifest: %w", err)
76+
}
77+
7178
ioStreams := genericclioptions.IOStreams{
7279
In: os.Stdin,
7380
Out: os.Stdout,
7481
ErrOut: os.Stderr,
7582
}
76-
ioReader := strings.NewReader(opt.Manifest)
83+
ioReader := strings.NewReader(manifestStr)
7784

7885
b := d.inner.NewBuilder(opt)
7986
f := d.inner.NewFactory(opt)

pkg/patterns/declarative/pkg/applier/direct_test.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
kubectltesting "k8s.io/kubectl/pkg/cmd/testing"
3232
cmdutil "k8s.io/kubectl/pkg/cmd/util"
3333
"k8s.io/kubectl/pkg/scheme"
34+
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
3435
)
3536

3637
type directApplierTestSite struct {
@@ -183,18 +184,24 @@ metadata:
183184

184185
for _, test := range tests {
185186
t.Run(test.name, func(t *testing.T) {
187+
ctx := context.TODO()
188+
186189
d := &directApplierTestSite{}
187190
testApplier := newDirectApplierTest(d)
188191

192+
objects, err := manifest.ParseObjects(ctx, test.manifest)
193+
if err != nil {
194+
t.Errorf("error parsing manifest: %v", err)
195+
}
196+
189197
opts := ApplierOptions{
190198
Namespace: test.namespace,
191-
Manifest: test.manifest,
199+
Objects: objects.GetItems(),
192200
Validate: test.validate,
193201
ExtraArgs: test.args,
194202
}
195203

196-
err := testApplier.Apply(context.Background(), opts)
197-
if err != nil {
204+
if err := testApplier.Apply(ctx, opts); err != nil {
198205
t.Errorf("unexpected error on call Apply: %v", err)
199206
}
200207

pkg/patterns/declarative/pkg/applier/exec.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
3232
"k8s.io/klog/v2"
3333
"sigs.k8s.io/controller-runtime/pkg/log"
34+
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
3435
)
3536

3637
// New creates a Client that runs kubectl avaliable on the path
@@ -93,6 +94,12 @@ func buildKubeconfig(restConfig *rest.Config) ([]byte, error) {
9394
func (c *ExecKubectl) Apply(ctx context.Context, opt ApplierOptions) error {
9495
log := log.FromContext(ctx)
9596

97+
objects := manifest.Objects{Items: opt.Objects}
98+
manifestStr, err := objects.JSONManifest()
99+
if err != nil {
100+
return fmt.Errorf("error creating JSON manifest: %w", err)
101+
}
102+
96103
log.Info("applying manifest")
97104

98105
args := []string{"apply"}
@@ -142,7 +149,7 @@ func (c *ExecKubectl) Apply(ctx context.Context, opt ApplierOptions) error {
142149
log.Info("applying manifest with kubectl %s", strings.Join(args, " "))
143150

144151
cmd := exec.Command("kubectl", args...)
145-
cmd.Stdin = strings.NewReader(opt.Manifest)
152+
cmd.Stdin = strings.NewReader(manifestStr)
146153

147154
var stdout bytes.Buffer
148155
var stderr bytes.Buffer
@@ -151,10 +158,9 @@ func (c *ExecKubectl) Apply(ctx context.Context, opt ApplierOptions) error {
151158

152159
log.WithValues("command", "kubectl").WithValues("args", args).Info("executing kubectl")
153160

154-
err := c.cmdSite.Run(cmd)
155-
if err != nil {
161+
if err := c.cmdSite.Run(cmd); err != nil {
156162
log.WithValues("stdout", stdout.String()).WithValues("stderr", stderr.String()).Error(err, "error from running kubectl apply")
157-
log.Info(fmt.Sprintf("manifest:\n%v", opt.Manifest))
163+
log.Info(fmt.Sprintf("manifest:\n%v", manifestStr))
158164
return fmt.Errorf("error from running kubectl apply: %v", err)
159165
}
160166

pkg/patterns/declarative/pkg/applier/exec_test.go

Lines changed: 55 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ import (
2222
"io"
2323
"os/exec"
2424
"reflect"
25+
"strings"
2526
"testing"
27+
28+
"github.com/google/go-cmp/cmp"
29+
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
2630
)
2731

2832
// collector is a commandSite implementation that stubs cmd.Run() calls for tests
@@ -37,59 +41,80 @@ func (s *collector) Run(c *exec.Cmd) error {
3741
}
3842

3943
func TestKubectlApply(t *testing.T) {
44+
configMapYAML := `
45+
apiVersion: v1
46+
kind: ConfigMap
47+
metadata:
48+
name: foo
49+
`
50+
configMapJSON := `{"apiVersion":"v1","kind":"ConfigMap","metadata":{"name":"foo"}}`
51+
4052
tests := []struct {
41-
name string
42-
namespace string
43-
manifest string
44-
validate bool
45-
args []string
46-
err error
47-
expectArgs []string
53+
name string
54+
namespace string
55+
manifest string
56+
validate bool
57+
args []string
58+
err error
59+
expectStdin string
60+
expectArgs []string
4861
}{
4962
{
50-
name: "manifest",
51-
namespace: "",
52-
manifest: "foo",
53-
expectArgs: []string{"kubectl", "apply", "--validate=false", "-f", "-"},
63+
name: "manifest",
64+
namespace: "",
65+
manifest: configMapYAML,
66+
expectStdin: configMapJSON,
67+
expectArgs: []string{"kubectl", "apply", "--validate=false", "-f", "-"},
5468
},
5569
{
56-
name: "manifest with apply",
57-
namespace: "kube-system",
58-
manifest: "heynow",
59-
expectArgs: []string{"kubectl", "apply", "-n", "kube-system", "--validate=false", "-f", "-"},
70+
name: "manifest with apply",
71+
namespace: "kube-system",
72+
manifest: configMapYAML,
73+
expectStdin: configMapJSON,
74+
expectArgs: []string{"kubectl", "apply", "-n", "kube-system", "--validate=false", "-f", "-"},
6075
},
6176
{
62-
name: "manifest with validate",
63-
namespace: "",
64-
manifest: "foo",
65-
validate: true,
66-
expectArgs: []string{"kubectl", "apply", "--validate=true", "-f", "-"},
77+
name: "manifest with validate",
78+
namespace: "",
79+
manifest: configMapYAML,
80+
expectStdin: configMapJSON,
81+
validate: true,
82+
expectArgs: []string{"kubectl", "apply", "--validate=true", "-f", "-"},
6783
},
6884
{
6985
name: "error propagation",
7086
expectArgs: []string{"kubectl", "apply", "--validate=false", "-f", "-"},
7187
err: errors.New("error"),
7288
},
7389
{
74-
name: "manifest with prune",
75-
namespace: "kube-system",
76-
manifest: "heynow",
77-
args: []string{"--prune=true", "--prune-whitelist=hello-world"},
78-
expectArgs: []string{"kubectl", "apply", "-n", "kube-system", "--validate=false", "--prune=true", "--prune-whitelist=hello-world", "-f", "-"},
90+
name: "manifest with prune",
91+
namespace: "kube-system",
92+
manifest: configMapYAML,
93+
expectStdin: configMapJSON,
94+
args: []string{"--prune=true", "--prune-whitelist=hello-world"},
95+
expectArgs: []string{"kubectl", "apply", "-n", "kube-system", "--validate=false", "--prune=true", "--prune-whitelist=hello-world", "-f", "-"},
7996
},
8097
}
8198

8299
for _, test := range tests {
83100
t.Run(test.name, func(t *testing.T) {
101+
ctx := context.TODO()
102+
84103
cs := collector{Error: test.err}
85104
kubectl := &ExecKubectl{cmdSite: &cs}
105+
106+
objects, err := manifest.ParseObjects(ctx, test.manifest)
107+
if err != nil {
108+
t.Fatalf("error parsing manifest: %v", err)
109+
}
110+
86111
opts := ApplierOptions{
87112
Namespace: test.namespace,
88-
Manifest: test.manifest,
113+
Objects: objects.GetItems(),
89114
Validate: test.validate,
90115
ExtraArgs: test.args,
91116
}
92-
err := kubectl.Apply(context.Background(), opts)
117+
err = kubectl.Apply(ctx, opts)
93118

94119
if test.err != nil && err == nil {
95120
t.Error("expected error to occur")
@@ -110,8 +135,9 @@ func TestKubectlApply(t *testing.T) {
110135
if err != nil {
111136
t.Fatalf("error reading manifest from stdin: %v", err)
112137
}
113-
if stdin := string(stdinBytes); stdin != test.manifest {
114-
t.Errorf("manifest mismatch, expected: %v, got: %v", test.manifest, stdin)
138+
if got, want := strings.TrimSpace(string(stdinBytes)), test.expectStdin; got != want {
139+
t.Errorf("manifest mismatch: got: %v, want: %v", got, want)
140+
t.Errorf("diff=%v", cmp.Diff(got, want))
115141
}
116142
})
117143
}

pkg/patterns/declarative/pkg/applier/type.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@ import (
66
"k8s.io/apimachinery/pkg/api/meta"
77
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
88
"k8s.io/client-go/rest"
9+
"sigs.k8s.io/kubebuilder-declarative-pattern/pkg/patterns/declarative/pkg/manifest"
910
)
1011

1112
type Applier interface {
1213
Apply(ctx context.Context, options ApplierOptions) error
1314
}
1415

1516
type ApplierOptions struct {
16-
Manifest string
17+
Objects []*manifest.Object
1718

1819
RESTConfig *rest.Config
1920
RESTMapper meta.RESTMapper

pkg/patterns/declarative/reconciler.go

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -255,15 +255,6 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN
255255
}
256256
objects.Items = newItems
257257

258-
var manifestStr string
259-
260-
m, err := objects.JSONManifest()
261-
if err != nil {
262-
log.Error(err, "creating final manifest")
263-
return objects, fmt.Errorf("error creating manifest: %v", err)
264-
}
265-
manifestStr = m
266-
267258
extraArgs := []string{}
268259

269260
// allow user disable prune in CR
@@ -306,7 +297,7 @@ func (r *Reconciler) reconcileExists(ctx context.Context, name types.NamespacedN
306297
RESTConfig: r.config,
307298
RESTMapper: r.restMapper,
308299
Namespace: ns,
309-
Manifest: manifestStr,
300+
Objects: objects.GetItems(),
310301
Validate: r.options.validate,
311302
ExtraArgs: extraArgs,
312303
Force: true,

0 commit comments

Comments
 (0)