diff --git a/commands/live/apply/cmdapply.go b/commands/live/apply/cmdapply.go index 2f24cc9c11..7cfbfd1fd7 100644 --- a/commands/live/apply/cmdapply.go +++ b/commands/live/apply/cmdapply.go @@ -175,6 +175,12 @@ func (r *Runner) runE(c *cobra.Command, args []string) error { return err } + // objs may contain kind List + objs, err = live.Flatten(objs) + if err != nil { + return err + } + invInfo, err := live.ToInventoryInfo(inv) if err != nil { return err diff --git a/pkg/live/flatten.go b/pkg/live/flatten.go new file mode 100644 index 0000000000..a3fba6a055 --- /dev/null +++ b/pkg/live/flatten.go @@ -0,0 +1,42 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package live + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" +) + +// Flatten returns a list containing 'in' objects with objects of kind List +// replaced by their members. +func Flatten(in []*unstructured.Unstructured) ([]*unstructured.Unstructured, error) { + var out []*unstructured.Unstructured + + for _, o := range in { + if o.IsList() { + err := o.EachListItem(func(item runtime.Object) error { + item2 := item.(*unstructured.Unstructured) + out = append(out, item2) + return nil + }) + if err != nil { + return nil, err + } + } else { + out = append(out, o) + } + } + return out, nil +} diff --git a/pkg/live/flatten_test.go b/pkg/live/flatten_test.go new file mode 100644 index 0000000000..93304eed67 --- /dev/null +++ b/pkg/live/flatten_test.go @@ -0,0 +1,78 @@ +// Copyright 2022 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package live + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +func Test_Flatten(t *testing.T) { + tests := []struct { + name string + in []*unstructured.Unstructured + want []*unstructured.Unstructured + }{ + { + name: "simple list", + in: simpleList, + want: simpleList, + }, + { + name: "list with list", + in: []*unstructured.Unstructured{ + { + Object: map[string]interface{}{ + "kind": "List", + "items": anySlice(simpleList), + }, + }, + }, + want: simpleList, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := Flatten(tt.in) + if assert.NoError(t, err) { + assert.Equal(t, tt.want, got) + } + }) + } +} + +func anySlice(in []*unstructured.Unstructured) (out []interface{}) { + for _, o := range in { + out = append(out, o.Object) + } + return +} + +var simpleList = []*unstructured.Unstructured{ + { + Object: map[string]interface{}{ + "kind": "ConfigMap", + "version": "v1", + }, + }, + { + Object: map[string]interface{}{ + "kind": "Pod", + "version": "v1", + }, + }, +}