diff --git a/api/resmap/factory.go b/api/resmap/factory.go index 6e8f4a7d6..cdbeb2086 100644 --- a/api/resmap/factory.go +++ b/api/resmap/factory.go @@ -9,6 +9,7 @@ import ( "sigs.k8s.io/kustomize/api/internal/kusterr" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/yaml" ) // Merginator merges resources. @@ -148,3 +149,20 @@ func newResMapFromResourceSlice( } return result, nil } + +// NewResMapFromRNodeSlice returns a ResMap from a slice of RNodes +func (rmF *Factory) NewResMapFromRNodeSlice(rnodes []*yaml.RNode) (ResMap, error) { + var resources []*resource.Resource + for _, rnode := range rnodes { + s, err := rnode.String() + if err != nil { + return nil, err + } + r, err := rmF.resF.FromBytes([]byte(s)) + if err != nil { + return nil, err + } + resources = append(resources, r) + } + return newResMapFromResourceSlice(resources) +} diff --git a/api/resmap/factory_test.go b/api/resmap/factory_test.go index aee067ee5..5050f9975 100644 --- a/api/resmap/factory_test.go +++ b/api/resmap/factory_test.go @@ -17,6 +17,7 @@ import ( resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest" valtest_test "sigs.k8s.io/kustomize/api/testutils/valtest" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/yaml" ) func TestFromFile(t *testing.T) { @@ -280,3 +281,56 @@ func TestNewResMapFromSecretArgs(t *testing.T) { t.Fatalf("error: %s", err) } } + +func TestFromRNodeSlice(t *testing.T) { + input := `apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: namespace-reader +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - watch + - list + ` + rnodes := []*yaml.RNode{ + yaml.MustParse(input), + } + + rm, err := rmF.NewResMapFromRNodeSlice(rnodes) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + expected := resmaptest_test.NewRmBuilder(t, rf).Add( + map[string]interface{}{ + "apiVersion": "rbac.authorization.k8s.io/v1", + "kind": "ClusterRole", + "metadata": map[string]interface{}{ + "name": "namespace-reader", + }, + "rules": []interface{}{ + map[string]interface{}{ + "apiGroups": []interface{}{ + "", + }, + "resources": []interface{}{ + "namespaces", + }, + "verbs": []interface{}{ + "get", + "watch", + "list", + }, + }, + }, + }).ResMap() + + if err = expected.ErrorIfNotEqualLists(rm); err != nil { + t.Fatalf("error: %s", err) + } +} diff --git a/api/resmap/resmap.go b/api/resmap/resmap.go index 2afa95a1a..83fa75461 100644 --- a/api/resmap/resmap.go +++ b/api/resmap/resmap.go @@ -10,6 +10,7 @@ import ( "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/kustomize/kyaml/yaml" ) // A Transformer modifies an instance of ResMap. @@ -235,4 +236,8 @@ type ResMap interface { // Select returns a list of resources that // are selected by a Selector Select(types.Selector) ([]*resource.Resource, error) + + // ToRNodeSlice converts the resources in the resmp + // to a list of RNodes + ToRNodeSlice() ([]*yaml.RNode, error) } diff --git a/api/resmap/reswrangler.go b/api/resmap/reswrangler.go index f439831ba..213c90c5f 100644 --- a/api/resmap/reswrangler.go +++ b/api/resmap/reswrangler.go @@ -11,6 +11,7 @@ import ( "sigs.k8s.io/kustomize/api/resid" "sigs.k8s.io/kustomize/api/resource" "sigs.k8s.io/kustomize/api/types" + kyaml_yaml "sigs.k8s.io/kustomize/kyaml/yaml" "sigs.k8s.io/yaml" ) @@ -561,3 +562,21 @@ func (m *resWrangler) Select(s types.Selector) ([]*resource.Resource, error) { } return result, nil } + +// ToRNodeSlice converts the resources in the resmp +// to a list of RNodes +func (m *resWrangler) ToRNodeSlice() ([]*kyaml_yaml.RNode, error) { + var rnodes []*kyaml_yaml.RNode + for _, r := range m.Resources() { + s, err := r.MarshalJSON() + if err != nil { + return nil, err + } + rnode, err := kyaml_yaml.Parse(string(s)) + if err != nil { + return nil, err + } + rnodes = append(rnodes, rnode) + } + return rnodes, nil +} diff --git a/api/resmap/reswrangler_test.go b/api/resmap/reswrangler_test.go index 7468c9170..0674fcc6f 100644 --- a/api/resmap/reswrangler_test.go +++ b/api/resmap/reswrangler_test.go @@ -4,6 +4,7 @@ package resmap_test import ( + "bytes" "fmt" "reflect" "strings" @@ -15,6 +16,7 @@ import ( "sigs.k8s.io/kustomize/api/resource" resmaptest_test "sigs.k8s.io/kustomize/api/testutils/resmaptest" "sigs.k8s.io/kustomize/api/types" + "sigs.k8s.io/yaml" ) var rf = resource.NewFactory( @@ -732,3 +734,50 @@ func TestAbsorbAll(t *testing.T) { t.Fatalf("expected error with unspecified behavior") } } + +func TestToRNodeSlice(t *testing.T) { + input := `apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: namespace-reader +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get + - watch + - list +` + rm, err := rmF.NewResMapFromBytes([]byte(input)) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + rnodes, err := rm.ToRNodeSlice() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + b := bytes.NewBufferString("") + for i, n := range rnodes { + if i != 0 { + b.WriteString("---\n") + } + s, err := n.String() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + y, err := yaml.JSONToYAML([]byte(s)) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + b.WriteString(string(y)) + } + + if !reflect.DeepEqual(input, b.String()) { + t.Fatalf("actual doesn't match expected.\nActual:\n%s\n===\nExpected:\n%s\n", + b.String(), input) + } +}