github.com/wmuizelaar/kpt@v0.0.0-20221018115725-bd564717b2ed/pkg/live/planner/cluster_test.go (about) 1 // Copyright 2022 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package planner 16 17 import ( 18 "context" 19 "testing" 20 21 "github.com/google/go-cmp/cmp" 22 "github.com/stretchr/testify/require" 23 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" 24 "sigs.k8s.io/cli-utils/pkg/apply" 25 "sigs.k8s.io/cli-utils/pkg/apply/event" 26 "sigs.k8s.io/cli-utils/pkg/inventory" 27 "sigs.k8s.io/cli-utils/pkg/object" 28 "sigs.k8s.io/cli-utils/pkg/testutil" 29 ) 30 31 var ( 32 deploymentYAML = ` 33 apiVersion: apps/v1 34 kind: Deployment 35 metadata: 36 name: foo 37 namespace: default 38 spec: 39 replicas: 1 40 ` 41 ) 42 43 func TestClusterPlanner(t *testing.T) { 44 testCases := map[string]struct { 45 resources []*unstructured.Unstructured 46 clusterResources []*unstructured.Unstructured 47 events []event.Event 48 49 expectedPlan *Plan 50 }{ 51 "single new resource": { 52 resources: []*unstructured.Unstructured{ 53 testutil.Unstructured(t, deploymentYAML), 54 }, 55 clusterResources: []*unstructured.Unstructured{}, 56 events: []event.Event{ 57 { 58 Type: event.InitType, 59 InitEvent: event.InitEvent{ 60 ActionGroups: event.ActionGroupList{ 61 { 62 Action: event.ApplyAction, 63 Name: "apply-1", 64 Identifiers: []object.ObjMetadata{ 65 testutil.ToIdentifier(t, deploymentYAML), 66 }, 67 }, 68 }, 69 }, 70 }, 71 { 72 Type: event.ApplyType, 73 ApplyEvent: event.ApplyEvent{ 74 GroupName: "apply-1", 75 Identifier: testutil.ToIdentifier(t, deploymentYAML), 76 Status: event.ApplySuccessful, 77 Resource: testutil.Unstructured(t, deploymentYAML), 78 }, 79 }, 80 }, 81 expectedPlan: &Plan{ 82 Actions: []Action{ 83 { 84 Type: Create, 85 Name: "foo", 86 Namespace: "default", 87 Group: "apps", 88 Kind: "Deployment", 89 Updated: testutil.Unstructured(t, deploymentYAML), 90 }, 91 }, 92 }, 93 }, 94 } 95 96 for tn := range testCases { 97 tc := testCases[tn] 98 t.Run(tn, func(t *testing.T) { 99 ctx := context.Background() 100 101 applier := &FakeApplier{ 102 events: tc.events, 103 } 104 105 fakeResourceFetcher := &FakeResourceFetcher{ 106 resources: tc.clusterResources, 107 } 108 109 plan, err := (&ClusterPlanner{ 110 applier: applier, 111 resourceFetcher: fakeResourceFetcher, 112 }).BuildPlan(ctx, &FakeInventoryInfo{}, []*unstructured.Unstructured{}, Options{}) 113 require.NoError(t, err) 114 115 if diff := cmp.Diff(tc.expectedPlan, plan); diff != "" { 116 t.Errorf("plan mismatch (-want +got):\n%s", diff) 117 } 118 }) 119 } 120 } 121 122 type FakeApplier struct { 123 events []event.Event 124 } 125 126 func (f *FakeApplier) Run(context.Context, inventory.Info, object.UnstructuredSet, apply.ApplierOptions) <-chan event.Event { 127 eventChannel := make(chan event.Event) 128 go func() { 129 defer close(eventChannel) 130 for i := range f.events { 131 eventChannel <- f.events[i] 132 } 133 }() 134 return eventChannel 135 } 136 137 type FakeResourceFetcher struct { 138 resources []*unstructured.Unstructured 139 } 140 141 func (frf *FakeResourceFetcher) FetchResource(_ context.Context, id object.ObjMetadata) (*unstructured.Unstructured, bool, error) { 142 for i := range frf.resources { 143 r := frf.resources[i] 144 rid := object.UnstructuredToObjMetadata(r) 145 if rid == id { 146 return r, true, nil 147 } 148 } 149 return nil, false, nil 150 } 151 152 type FakeInventoryInfo struct{} 153 154 func (fii *FakeInventoryInfo) Namespace() string { 155 return "" 156 } 157 158 func (fii *FakeInventoryInfo) Name() string { 159 return "" 160 } 161 162 func (fii *FakeInventoryInfo) ID() string { 163 return "" 164 } 165 166 func (fii *FakeInventoryInfo) Strategy() inventory.Strategy { 167 return inventory.NameStrategy 168 }