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  }