github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/render/googlegke/render_test.go (about) 1 package googlegke 2 3 import ( 4 "context" 5 "encoding/base64" 6 "fmt" 7 "io/ioutil" 8 "testing" 9 10 "github.com/go-kit/kit/log" 11 "github.com/golang/mock/gomock" 12 "github.com/pmezard/go-difflib/difflib" 13 "github.com/replicatedhq/libyaml" 14 "github.com/replicatedhq/ship/pkg/api" 15 "github.com/replicatedhq/ship/pkg/lifecycle/render/root" 16 "github.com/replicatedhq/ship/pkg/templates" 17 "github.com/replicatedhq/ship/pkg/test-mocks/inline" 18 "github.com/replicatedhq/ship/pkg/test-mocks/state" 19 "github.com/replicatedhq/ship/pkg/testing/logger" 20 "github.com/replicatedhq/ship/pkg/testing/matchers" 21 "github.com/spf13/afero" 22 "github.com/spf13/viper" 23 "github.com/stretchr/testify/require" 24 ) 25 26 func TestRenderer(t *testing.T) { 27 tests := []struct { 28 name string 29 asset api.GKEAsset 30 kubeconfig string 31 }{ 32 { 33 name: "empty", 34 asset: api.GKEAsset{}, 35 kubeconfig: "kubeconfig_", 36 }, 37 { 38 name: "named", 39 asset: api.GKEAsset{ 40 ClusterName: "aClusterName", 41 }, 42 kubeconfig: "kubeconfig_aClusterName", 43 }, 44 { 45 name: "named, custom path", 46 asset: api.GKEAsset{ 47 ClusterName: "aClusterName", 48 AssetShared: api.AssetShared{ 49 Dest: "gke.tf", 50 }, 51 }, 52 kubeconfig: "kubeconfig_aClusterName", 53 }, 54 { 55 name: "named, in a directory", 56 asset: api.GKEAsset{ 57 ClusterName: "aClusterName", 58 AssetShared: api.AssetShared{ 59 Dest: "k8s/gke.tf", 60 }, 61 }, 62 kubeconfig: "k8s/kubeconfig_aClusterName", 63 }, 64 } 65 for _, test := range tests { 66 t.Run(test.name, func(t *testing.T) { 67 req := require.New(t) 68 mc := gomock.NewController(t) 69 mockInline := inline.NewMockRenderer(mc) 70 testLogger := &logger.TestLogger{T: t} 71 v := viper.New() 72 bb := templates.NewBuilderBuilder(testLogger, v, &state.MockManager{}) 73 renderer := &LocalRenderer{ 74 Logger: testLogger, 75 BuilderBuilder: bb, 76 Inline: mockInline, 77 } 78 79 assetMatcher := &matchers.Is{ 80 Describe: "inline asset", 81 Test: func(v interface{}) bool { 82 _, ok := v.(api.InlineAsset) 83 return ok 84 }, 85 } 86 87 rootFs := root.Fs{ 88 Afero: afero.Afero{Fs: afero.NewMemMapFs()}, 89 RootPath: "", 90 } 91 metadata := api.ReleaseMetadata{} 92 groups := []libyaml.ConfigGroup{} 93 templateContext := map[string]interface{}{} 94 95 mockInline.EXPECT().Execute( 96 rootFs, 97 assetMatcher, 98 metadata, 99 templateContext, 100 groups, 101 ).Return(func(ctx context.Context) error { return nil }) 102 103 err := renderer.Execute( 104 rootFs, 105 test.asset, 106 metadata, 107 templateContext, 108 groups, 109 )(context.Background()) 110 111 req.NoError(err) 112 113 // test that the template function returns the correct kubeconfig path 114 builder := getBuilder() 115 116 gkeTemplateFunc := `{{repl GoogleGKE "%s" }}` 117 kubeconfig, err := builder.String(fmt.Sprintf(gkeTemplateFunc, test.asset.ClusterName)) 118 req.NoError(err) 119 120 req.Equal(test.kubeconfig, kubeconfig, "Did not get expected kubeconfig path") 121 122 otherKubeconfig, err := builder.String(fmt.Sprintf(gkeTemplateFunc, "doesnotexist")) 123 req.NoError(err) 124 req.Empty(otherKubeconfig, "Expected path to nonexistent kubeconfig to be empty") 125 }) 126 } 127 } 128 129 func getBuilder() templates.Builder { 130 builderBuilder := templates.NewBuilderBuilder(log.NewNopLogger(), viper.New(), &state.MockManager{}) 131 132 builder := builderBuilder.NewBuilder( 133 &templates.ShipContext{}, 134 ) 135 return builder 136 } 137 138 func TestRenderTerraformContents(t *testing.T) { 139 tests := []struct { 140 name string 141 asset api.GKEAsset 142 expected string 143 }{ 144 { 145 name: "simple", 146 asset: api.GKEAsset{ 147 ClusterName: "simple-cluster", 148 }, 149 expected: mustAsset("testassets/simple.tf"), 150 }, 151 { 152 name: "complex", 153 asset: api.GKEAsset{ 154 GCPProvider: api.GCPProvider{ 155 Credentials: base64.StdEncoding.EncodeToString( 156 []byte("{\n \"type\": \"service_account\",\n \"project_id\": \"my-project\",\n ...\n}"), 157 ), 158 Project: "my-project", 159 Region: "us-east", 160 }, 161 ClusterName: "complex-cluster", 162 Zone: "us-east1-b", 163 InitialNodeCount: "5", 164 MachineType: "n1-standard-4", 165 AdditionalZones: "us-east1-c,us-east1-d", 166 MinMasterVersion: "1.10.6-gke.1", 167 }, 168 expected: mustAsset("testassets/complex.tf"), 169 }, 170 } 171 for _, test := range tests { 172 t.Run(test.name, func(t *testing.T) { 173 req := require.New(t) 174 actual, err := renderTerraformContents(test.asset) 175 req.NoError(err) 176 if actual != test.expected { 177 diff := difflib.UnifiedDiff{ 178 A: difflib.SplitLines(test.expected), 179 B: difflib.SplitLines(actual), 180 FromFile: "expected contents", 181 ToFile: "actual contents", 182 Context: 3, 183 } 184 185 diffText, err := difflib.GetUnifiedDiffString(diff) 186 req.NoError(err) 187 188 t.Errorf("Test %s did not match, diff:\n%s", test.name, diffText) 189 } 190 }) 191 } 192 } 193 194 func mustAsset(name string) string { 195 b, err := ioutil.ReadFile(name) 196 if err != nil { 197 panic(err) 198 } 199 return string(b) 200 } 201 202 func TestBuildAsset(t *testing.T) { 203 type args struct { 204 asset api.GKEAsset 205 builder *templates.Builder 206 } 207 tests := []struct { 208 name string 209 args args 210 want api.GKEAsset 211 wantErr bool 212 }{ 213 { 214 name: "basic", 215 args: args{ 216 asset: api.GKEAsset{ 217 ClusterName: `{{repl "cluster_name_built"}}`, 218 Zone: `{{repl "zone_built"}}`, 219 InitialNodeCount: `{{repl "initial_node_count_built"}}`, 220 MachineType: `{{repl "machine_type_built"}}`, 221 AdditionalZones: `{{repl "additional_zones_built"}}`, 222 MinMasterVersion: `{{repl "min_master_version_built"}}`, // not built 223 }, 224 builder: &templates.Builder{}, 225 }, 226 want: api.GKEAsset{ 227 ClusterName: "cluster_name_built", 228 Zone: "zone_built", 229 InitialNodeCount: "initial_node_count_built", 230 MachineType: "machine_type_built", 231 AdditionalZones: "additional_zones_built", 232 MinMasterVersion: `{{repl "min_master_version_built"}}`, // not built 233 }, 234 }, 235 } 236 for _, tt := range tests { 237 t.Run(tt.name, func(t *testing.T) { 238 req := require.New(t) 239 240 got, err := buildAsset(tt.args.asset, tt.args.builder) 241 if !tt.wantErr { 242 req.NoErrorf(err, "buildAsset() error = %v", err) 243 } else { 244 req.Error(err) 245 } 246 247 req.Equal(tt.want, got) 248 }) 249 } 250 }