github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/render/amazoneks/render_test.go (about)

     1  package amazoneks
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"testing"
     7  	"text/template"
     8  
     9  	"github.com/go-kit/kit/log"
    10  	"github.com/golang/mock/gomock"
    11  	"github.com/pmezard/go-difflib/difflib"
    12  	"github.com/replicatedhq/libyaml"
    13  	"github.com/replicatedhq/ship/pkg/api"
    14  	"github.com/replicatedhq/ship/pkg/api/amazoneks"
    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.EKSAsset
    30  		kubeconfig string
    31  	}{
    32  		{
    33  			name:       "empty",
    34  			asset:      api.EKSAsset{ExistingVPC: &amazoneks.EKSExistingVPC{}},
    35  			kubeconfig: "kubeconfig_",
    36  		},
    37  		{
    38  			name: "named",
    39  			asset: api.EKSAsset{
    40  				ClusterName: "aClusterName",
    41  				ExistingVPC: &amazoneks.EKSExistingVPC{},
    42  			},
    43  			kubeconfig: "kubeconfig_aClusterName",
    44  		},
    45  		{
    46  			name: "named, custom path",
    47  			asset: api.EKSAsset{
    48  				ClusterName: "aClusterName",
    49  				AssetShared: api.AssetShared{
    50  					Dest: "eks.tf",
    51  				},
    52  				ExistingVPC: &amazoneks.EKSExistingVPC{},
    53  			},
    54  			kubeconfig: "kubeconfig_aClusterName",
    55  		},
    56  		{
    57  			name: "named, in a directory",
    58  			asset: api.EKSAsset{
    59  				ClusterName: "aClusterName",
    60  				AssetShared: api.AssetShared{
    61  					Dest: "k8s/eks.tf",
    62  				},
    63  				ExistingVPC: &amazoneks.EKSExistingVPC{},
    64  			},
    65  			kubeconfig: "k8s/kubeconfig_aClusterName",
    66  		},
    67  	}
    68  	for _, test := range tests {
    69  		t.Run(test.name, func(t *testing.T) {
    70  			req := require.New(t)
    71  			mc := gomock.NewController(t)
    72  			mockInline := inline.NewMockRenderer(mc)
    73  			testLogger := &logger.TestLogger{T: t}
    74  			v := viper.New()
    75  			bb := templates.NewBuilderBuilder(testLogger, v, &state.MockManager{})
    76  			renderer := &LocalRenderer{
    77  				Logger:         testLogger,
    78  				BuilderBuilder: bb,
    79  				Inline:         mockInline,
    80  			}
    81  
    82  			assetMatcher := &matchers.Is{
    83  				Describe: "inline asset",
    84  				Test: func(v interface{}) bool {
    85  					_, ok := v.(api.InlineAsset)
    86  					return ok
    87  				},
    88  			}
    89  
    90  			rootFs := root.Fs{
    91  				Afero:    afero.Afero{Fs: afero.NewMemMapFs()},
    92  				RootPath: "",
    93  			}
    94  			metadata := api.ReleaseMetadata{}
    95  			groups := []libyaml.ConfigGroup{}
    96  			templateContext := map[string]interface{}{}
    97  
    98  			mockInline.EXPECT().Execute(
    99  				rootFs,
   100  				assetMatcher,
   101  				metadata,
   102  				templateContext,
   103  				groups,
   104  			).Return(func(ctx context.Context) error { return nil })
   105  
   106  			err := renderer.Execute(
   107  				rootFs,
   108  				test.asset,
   109  				metadata,
   110  				templateContext,
   111  				groups,
   112  			)(context.Background())
   113  
   114  			req.NoError(err)
   115  
   116  			// test that the template function returns the correct kubeconfig path
   117  			builder := getBuilder()
   118  
   119  			eksTemplateFunc := `{{repl AmazonEKS "%s" }}`
   120  			kubeconfig, err := builder.String(fmt.Sprintf(eksTemplateFunc, test.asset.ClusterName))
   121  			req.NoError(err)
   122  
   123  			req.Equal(test.kubeconfig, kubeconfig, "Did not get expected kubeconfig path")
   124  
   125  			otherKubeconfig, err := builder.String(fmt.Sprintf(eksTemplateFunc, "doesnotexist"))
   126  			req.NoError(err)
   127  			req.Empty(otherKubeconfig, "Expected path to nonexistent kubeconfig to be empty")
   128  		})
   129  	}
   130  }
   131  
   132  func getBuilder() templates.Builder {
   133  	builderBuilder := templates.NewBuilderBuilder(log.NewNopLogger(), viper.New(), &state.MockManager{})
   134  
   135  	builder := builderBuilder.NewBuilder(
   136  		&templates.ShipContext{},
   137  	)
   138  	return builder
   139  }
   140  
   141  // this function allows testing the worker template independently
   142  func testRenderEKS(asset api.EKSAsset) (string, error) {
   143  	t, err := template.New("asgsTemplate").Parse(workerTempl)
   144  	if err != nil {
   145  		return "", err
   146  	}
   147  	return executeTemplate(t, asset)
   148  }
   149  
   150  func TestRenderEKSs(t *testing.T) {
   151  	tests := []struct {
   152  		name     string
   153  		expected string
   154  		asset    api.EKSAsset
   155  	}{
   156  		{
   157  			name:  "empty",
   158  			asset: api.EKSAsset{},
   159  			expected: `
   160  locals {
   161    "worker_group_count" = "0"
   162  }
   163  
   164  locals {
   165    "worker_groups" = [
   166    ]
   167  }
   168  
   169  provider "aws" {
   170    version = "~> 2.7.0"
   171    region  = ""
   172  }
   173  
   174  variable "eks-cluster-name" {
   175    default = ""
   176    type    = "string"
   177  }
   178  
   179  module "eks" {
   180    source  = "terraform-aws-modules/eks/aws"
   181    version = "3.0.0"
   182  
   183    cluster_name = "${var.eks-cluster-name}"
   184  
   185    subnets = ["${local.eks_vpc_private_subnets}", "${local.eks_vpc_public_subnets}"]
   186  
   187    vpc_id = "${local.eks_vpc}"
   188  
   189    worker_group_count = "${local.worker_group_count}"
   190    worker_groups      = "${local.worker_groups}"
   191  }
   192  `,
   193  		},
   194  		{
   195  			name: "one",
   196  			asset: api.EKSAsset{
   197  				AutoscalingGroups: []amazoneks.EKSAutoscalingGroup{
   198  					{
   199  						Name:        "onegroup",
   200  						GroupSize:   "3",
   201  						MachineType: "m5.large",
   202  					},
   203  				},
   204  				Region:      "test-region",
   205  				ClusterName: "a-test-cluster",
   206  			},
   207  			expected: `
   208  locals {
   209    "worker_group_count" = "1"
   210  }
   211  
   212  locals {
   213    "worker_groups" = [
   214      {
   215        name                 = "onegroup"
   216        asg_min_size         = "3"
   217        asg_max_size         = "3"
   218        asg_desired_capacity = "3"
   219        instance_type        = "m5.large"
   220  
   221        subnets = "${join(",", local.eks_vpc_private_subnets)}"
   222      },
   223    ]
   224  }
   225  
   226  provider "aws" {
   227    version = "~> 2.7.0"
   228    region  = "test-region"
   229  }
   230  
   231  variable "eks-cluster-name" {
   232    default = "a-test-cluster"
   233    type    = "string"
   234  }
   235  
   236  module "eks" {
   237    source  = "terraform-aws-modules/eks/aws"
   238    version = "3.0.0"
   239  
   240    cluster_name = "${var.eks-cluster-name}"
   241  
   242    subnets = ["${local.eks_vpc_private_subnets}", "${local.eks_vpc_public_subnets}"]
   243  
   244    vpc_id = "${local.eks_vpc}"
   245  
   246    worker_group_count = "${local.worker_group_count}"
   247    worker_groups      = "${local.worker_groups}"
   248  }
   249  `,
   250  		},
   251  		{
   252  			name: "two",
   253  			asset: api.EKSAsset{
   254  				AutoscalingGroups: []amazoneks.EKSAutoscalingGroup{
   255  					{
   256  						Name:        "onegroup",
   257  						GroupSize:   "3",
   258  						MachineType: "m5.large",
   259  					},
   260  					{
   261  						Name:        "twogroup",
   262  						GroupSize:   "1",
   263  						MachineType: "m5.xlarge",
   264  					},
   265  				},
   266  				Region:      "double-test-region",
   267  				ClusterName: "double-test-cluster",
   268  			},
   269  			expected: `
   270  locals {
   271    "worker_group_count" = "2"
   272  }
   273  
   274  locals {
   275    "worker_groups" = [
   276      {
   277        name                 = "onegroup"
   278        asg_min_size         = "3"
   279        asg_max_size         = "3"
   280        asg_desired_capacity = "3"
   281        instance_type        = "m5.large"
   282  
   283        subnets = "${join(",", local.eks_vpc_private_subnets)}"
   284      },
   285      {
   286        name                 = "twogroup"
   287        asg_min_size         = "1"
   288        asg_max_size         = "1"
   289        asg_desired_capacity = "1"
   290        instance_type        = "m5.xlarge"
   291  
   292        subnets = "${join(",", local.eks_vpc_private_subnets)}"
   293      },
   294    ]
   295  }
   296  
   297  provider "aws" {
   298    version = "~> 2.7.0"
   299    region  = "double-test-region"
   300  }
   301  
   302  variable "eks-cluster-name" {
   303    default = "double-test-cluster"
   304    type    = "string"
   305  }
   306  
   307  module "eks" {
   308    source  = "terraform-aws-modules/eks/aws"
   309    version = "3.0.0"
   310  
   311    cluster_name = "${var.eks-cluster-name}"
   312  
   313    subnets = ["${local.eks_vpc_private_subnets}", "${local.eks_vpc_public_subnets}"]
   314  
   315    vpc_id = "${local.eks_vpc}"
   316  
   317    worker_group_count = "${local.worker_group_count}"
   318    worker_groups      = "${local.worker_groups}"
   319  }
   320  `,
   321  		},
   322  	}
   323  	for _, test := range tests {
   324  		t.Run(test.name, func(t *testing.T) {
   325  			req := require.New(t)
   326  			actual, err := testRenderEKS(test.asset)
   327  			req.NoError(err)
   328  			if actual != test.expected {
   329  				diff := difflib.UnifiedDiff{
   330  					A:        difflib.SplitLines(test.expected),
   331  					B:        difflib.SplitLines(actual),
   332  					FromFile: "expected contents",
   333  					ToFile:   "actual contents",
   334  					Context:  3,
   335  				}
   336  
   337  				diffText, err := difflib.GetUnifiedDiffString(diff)
   338  				req.NoError(err)
   339  
   340  				t.Errorf("Test %s did not match, diff:\n%s", test.name, diffText)
   341  			}
   342  		})
   343  	}
   344  }
   345  
   346  // this function allows testing the new VPC template independently
   347  func testRenderNewVPC(vpc api.EKSAsset) (string, error) {
   348  	t, err := template.New("eksTemplate").Parse(newVPCTempl)
   349  	if err != nil {
   350  		return "", err
   351  	}
   352  	return executeTemplate(t, vpc)
   353  }
   354  
   355  func TestRenderVPC(t *testing.T) {
   356  	tests := []struct {
   357  		name     string
   358  		expected string
   359  		asset    api.EKSAsset
   360  	}{
   361  		{
   362  			name: "empty",
   363  			asset: api.EKSAsset{
   364  				CreatedVPC: &amazoneks.EKSCreatedVPC{},
   365  			},
   366  			expected: `
   367  variable "vpc_cidr" {
   368    type    = "string"
   369    default = ""
   370  }
   371  
   372  variable "vpc_public_subnets" {
   373    default = [
   374    ]
   375  }
   376  
   377  variable "vpc_private_subnets" {
   378    default = [
   379    ]
   380  }
   381  
   382  variable "vpc_azs" {
   383    default = [
   384    ]
   385  }
   386  
   387  module "vpc" {
   388    source  = "terraform-aws-modules/vpc/aws"
   389    version = "1.60.0"
   390    name    = "eks-vpc"
   391    cidr    = "${var.vpc_cidr}"
   392    azs     = "${var.vpc_azs}"
   393  
   394    private_subnets = "${var.vpc_private_subnets}"
   395    public_subnets  = "${var.vpc_public_subnets}"
   396  
   397    map_public_ip_on_launch = true
   398    enable_nat_gateway      = true
   399    single_nat_gateway      = true
   400  
   401    tags = "${map("kubernetes.io/cluster/${var.eks-cluster-name}", "shared")}"
   402  }
   403  
   404  locals {
   405    "eks_vpc"                 = "${module.vpc.vpc_id}"
   406    "eks_vpc_public_subnets"  = "${module.vpc.public_subnets}"
   407    "eks_vpc_private_subnets" = "${module.vpc.private_subnets}"
   408  }
   409  `,
   410  		},
   411  		{
   412  			name: "basic vpc",
   413  			asset: api.EKSAsset{
   414  				CreatedVPC: &amazoneks.EKSCreatedVPC{
   415  					VPCCIDR:        "10.0.0.0/16",
   416  					PublicSubnets:  []string{"10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"},
   417  					PrivateSubnets: []string{"10.128.1.0/24", "10.128.2.0/24", "10.128.3.0/24", "10.128.4.0/24"},
   418  					Zones:          []string{"us-west-2a", "us-west-2b", "us-west-2c", "us-west-2d"},
   419  				},
   420  			},
   421  			expected: `
   422  variable "vpc_cidr" {
   423    type    = "string"
   424    default = "10.0.0.0/16"
   425  }
   426  
   427  variable "vpc_public_subnets" {
   428    default = [
   429      "10.0.1.0/24",
   430      "10.0.2.0/24",
   431      "10.0.3.0/24",
   432      "10.0.4.0/24",
   433    ]
   434  }
   435  
   436  variable "vpc_private_subnets" {
   437    default = [
   438      "10.128.1.0/24",
   439      "10.128.2.0/24",
   440      "10.128.3.0/24",
   441      "10.128.4.0/24",
   442    ]
   443  }
   444  
   445  variable "vpc_azs" {
   446    default = [
   447      "us-west-2a",
   448      "us-west-2b",
   449      "us-west-2c",
   450      "us-west-2d",
   451    ]
   452  }
   453  
   454  module "vpc" {
   455    source  = "terraform-aws-modules/vpc/aws"
   456    version = "1.60.0"
   457    name    = "eks-vpc"
   458    cidr    = "${var.vpc_cidr}"
   459    azs     = "${var.vpc_azs}"
   460  
   461    private_subnets = "${var.vpc_private_subnets}"
   462    public_subnets  = "${var.vpc_public_subnets}"
   463  
   464    map_public_ip_on_launch = true
   465    enable_nat_gateway      = true
   466    single_nat_gateway      = true
   467  
   468    tags = "${map("kubernetes.io/cluster/${var.eks-cluster-name}", "shared")}"
   469  }
   470  
   471  locals {
   472    "eks_vpc"                 = "${module.vpc.vpc_id}"
   473    "eks_vpc_public_subnets"  = "${module.vpc.public_subnets}"
   474    "eks_vpc_private_subnets" = "${module.vpc.private_subnets}"
   475  }
   476  `,
   477  		},
   478  	}
   479  	for _, test := range tests {
   480  		t.Run(test.name, func(t *testing.T) {
   481  			req := require.New(t)
   482  			actual, err := testRenderNewVPC(test.asset)
   483  			req.NoError(err)
   484  			if actual != test.expected {
   485  				diff := difflib.UnifiedDiff{
   486  					A:        difflib.SplitLines(test.expected),
   487  					B:        difflib.SplitLines(actual),
   488  					FromFile: "expected contents",
   489  					ToFile:   "actual contents",
   490  					Context:  3,
   491  				}
   492  
   493  				diffText, err := difflib.GetUnifiedDiffString(diff)
   494  				req.NoError(err)
   495  
   496  				t.Errorf("Test %s did not match, diff:\n%s", test.name, diffText)
   497  			}
   498  		})
   499  	}
   500  }
   501  
   502  // this function allows testing the existing VPC template independently
   503  func testRenderExistingVPC(vpc api.EKSAsset) (string, error) {
   504  	t, err := template.New("eksTemplate").Parse(existingVPCTempl)
   505  	if err != nil {
   506  		return "", err
   507  	}
   508  	return executeTemplate(t, vpc)
   509  }
   510  
   511  func TestRenderExistingVPC(t *testing.T) {
   512  	tests := []struct {
   513  		name     string
   514  		expected string
   515  		asset    api.EKSAsset
   516  	}{
   517  		{
   518  			name:  "empty",
   519  			asset: api.EKSAsset{ExistingVPC: &amazoneks.EKSExistingVPC{}},
   520  			expected: `
   521  locals {
   522    "eks_vpc"                 = ""
   523    "eks_vpc_public_subnets"  = [
   524    ]
   525    "eks_vpc_private_subnets" = [
   526    ]
   527  }
   528  `,
   529  		},
   530  		{
   531  			name: "basic vpc",
   532  			asset: api.EKSAsset{
   533  				ExistingVPC: &amazoneks.EKSExistingVPC{
   534  					VPCID:          "vpcid",
   535  					PublicSubnets:  []string{"abc123-a", "abc123-b"},
   536  					PrivateSubnets: []string{"xyz789-a", "xyz789-b"},
   537  				},
   538  			},
   539  			expected: `
   540  locals {
   541    "eks_vpc"                 = "vpcid"
   542    "eks_vpc_public_subnets"  = [
   543      "abc123-a",
   544      "abc123-b",
   545    ]
   546    "eks_vpc_private_subnets" = [
   547      "xyz789-a",
   548      "xyz789-b",
   549    ]
   550  }
   551  `,
   552  		},
   553  	}
   554  	for _, test := range tests {
   555  		t.Run(test.name, func(t *testing.T) {
   556  			req := require.New(t)
   557  			actual, err := testRenderExistingVPC(test.asset)
   558  			req.NoError(err)
   559  			if actual != test.expected {
   560  				diff := difflib.UnifiedDiff{
   561  					A:        difflib.SplitLines(test.expected),
   562  					B:        difflib.SplitLines(actual),
   563  					FromFile: "expected contents",
   564  					ToFile:   "actual contents",
   565  					Context:  3,
   566  				}
   567  
   568  				diffText, err := difflib.GetUnifiedDiffString(diff)
   569  				req.NoError(err)
   570  
   571  				t.Errorf("Test %s did not match, diff:\n%s", test.name, diffText)
   572  			}
   573  		})
   574  	}
   575  }
   576  
   577  func TestRenderTerraform(t *testing.T) {
   578  	tests := []struct {
   579  		name     string
   580  		expected string
   581  		vpc      api.EKSAsset
   582  	}{
   583  		{
   584  			name: "empty",
   585  			vpc:  api.EKSAsset{ExistingVPC: &amazoneks.EKSExistingVPC{}},
   586  			expected: `
   587  locals {
   588    "eks_vpc"                 = ""
   589    "eks_vpc_public_subnets"  = [
   590    ]
   591    "eks_vpc_private_subnets" = [
   592    ]
   593  }
   594  
   595  locals {
   596    "worker_group_count" = "0"
   597  }
   598  
   599  locals {
   600    "worker_groups" = [
   601    ]
   602  }
   603  
   604  provider "aws" {
   605    version = "~> 2.7.0"
   606    region  = ""
   607  }
   608  
   609  variable "eks-cluster-name" {
   610    default = ""
   611    type    = "string"
   612  }
   613  
   614  module "eks" {
   615    source  = "terraform-aws-modules/eks/aws"
   616    version = "3.0.0"
   617  
   618    cluster_name = "${var.eks-cluster-name}"
   619  
   620    subnets = ["${local.eks_vpc_private_subnets}", "${local.eks_vpc_public_subnets}"]
   621  
   622    vpc_id = "${local.eks_vpc}"
   623  
   624    worker_group_count = "${local.worker_group_count}"
   625    worker_groups      = "${local.worker_groups}"
   626  }
   627  `,
   628  		},
   629  		{
   630  			name: "existing vpc",
   631  			vpc: api.EKSAsset{
   632  				ClusterName: "existing-vpc-cluster",
   633  				Region:      "us-east-1",
   634  				ExistingVPC: &amazoneks.EKSExistingVPC{
   635  					VPCID:          "existing_vpcid",
   636  					PublicSubnets:  []string{"abc123-a", "abc123-b"},
   637  					PrivateSubnets: []string{"xyz789-a", "xyz789-b"},
   638  				},
   639  				AutoscalingGroups: []amazoneks.EKSAutoscalingGroup{
   640  					{
   641  						Name:        "onegroup",
   642  						GroupSize:   "3",
   643  						MachineType: "m5.large",
   644  					},
   645  				},
   646  			},
   647  			expected: `
   648  locals {
   649    "eks_vpc"                 = "existing_vpcid"
   650    "eks_vpc_public_subnets"  = [
   651      "abc123-a",
   652      "abc123-b",
   653    ]
   654    "eks_vpc_private_subnets" = [
   655      "xyz789-a",
   656      "xyz789-b",
   657    ]
   658  }
   659  
   660  locals {
   661    "worker_group_count" = "1"
   662  }
   663  
   664  locals {
   665    "worker_groups" = [
   666      {
   667        name                 = "onegroup"
   668        asg_min_size         = "3"
   669        asg_max_size         = "3"
   670        asg_desired_capacity = "3"
   671        instance_type        = "m5.large"
   672  
   673        subnets = "${join(",", local.eks_vpc_private_subnets)}"
   674      },
   675    ]
   676  }
   677  
   678  provider "aws" {
   679    version = "~> 2.7.0"
   680    region  = "us-east-1"
   681  }
   682  
   683  variable "eks-cluster-name" {
   684    default = "existing-vpc-cluster"
   685    type    = "string"
   686  }
   687  
   688  module "eks" {
   689    source  = "terraform-aws-modules/eks/aws"
   690    version = "3.0.0"
   691  
   692    cluster_name = "${var.eks-cluster-name}"
   693  
   694    subnets = ["${local.eks_vpc_private_subnets}", "${local.eks_vpc_public_subnets}"]
   695  
   696    vpc_id = "${local.eks_vpc}"
   697  
   698    worker_group_count = "${local.worker_group_count}"
   699    worker_groups      = "${local.worker_groups}"
   700  }
   701  `,
   702  		},
   703  		{
   704  			name: "new vpc",
   705  			vpc: api.EKSAsset{
   706  				ClusterName: "new-vpc-cluster",
   707  				Region:      "us-east-1",
   708  				CreatedVPC: &amazoneks.EKSCreatedVPC{
   709  					VPCCIDR:        "10.0.0.0/16",
   710  					PublicSubnets:  []string{"10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24", "10.0.4.0/24"},
   711  					PrivateSubnets: []string{"10.128.1.0/24", "10.128.2.0/24", "10.128.3.0/24", "10.128.4.0/24"},
   712  					Zones:          []string{"us-west-2a", "us-west-2b", "us-west-2c", "us-west-2d"},
   713  				},
   714  				AutoscalingGroups: []amazoneks.EKSAutoscalingGroup{
   715  					{
   716  						Name:        "onegroup",
   717  						GroupSize:   "3",
   718  						MachineType: "m5.large",
   719  					},
   720  					{
   721  						Name:        "twogroup",
   722  						GroupSize:   "2",
   723  						MachineType: "m4.large",
   724  					},
   725  				},
   726  			},
   727  			expected: `
   728  variable "vpc_cidr" {
   729    type    = "string"
   730    default = "10.0.0.0/16"
   731  }
   732  
   733  variable "vpc_public_subnets" {
   734    default = [
   735      "10.0.1.0/24",
   736      "10.0.2.0/24",
   737      "10.0.3.0/24",
   738      "10.0.4.0/24",
   739    ]
   740  }
   741  
   742  variable "vpc_private_subnets" {
   743    default = [
   744      "10.128.1.0/24",
   745      "10.128.2.0/24",
   746      "10.128.3.0/24",
   747      "10.128.4.0/24",
   748    ]
   749  }
   750  
   751  variable "vpc_azs" {
   752    default = [
   753      "us-west-2a",
   754      "us-west-2b",
   755      "us-west-2c",
   756      "us-west-2d",
   757    ]
   758  }
   759  
   760  module "vpc" {
   761    source  = "terraform-aws-modules/vpc/aws"
   762    version = "1.60.0"
   763    name    = "eks-vpc"
   764    cidr    = "${var.vpc_cidr}"
   765    azs     = "${var.vpc_azs}"
   766  
   767    private_subnets = "${var.vpc_private_subnets}"
   768    public_subnets  = "${var.vpc_public_subnets}"
   769  
   770    map_public_ip_on_launch = true
   771    enable_nat_gateway      = true
   772    single_nat_gateway      = true
   773  
   774    tags = "${map("kubernetes.io/cluster/${var.eks-cluster-name}", "shared")}"
   775  }
   776  
   777  locals {
   778    "eks_vpc"                 = "${module.vpc.vpc_id}"
   779    "eks_vpc_public_subnets"  = "${module.vpc.public_subnets}"
   780    "eks_vpc_private_subnets" = "${module.vpc.private_subnets}"
   781  }
   782  
   783  locals {
   784    "worker_group_count" = "2"
   785  }
   786  
   787  locals {
   788    "worker_groups" = [
   789      {
   790        name                 = "onegroup"
   791        asg_min_size         = "3"
   792        asg_max_size         = "3"
   793        asg_desired_capacity = "3"
   794        instance_type        = "m5.large"
   795  
   796        subnets = "${join(",", local.eks_vpc_private_subnets)}"
   797      },
   798      {
   799        name                 = "twogroup"
   800        asg_min_size         = "2"
   801        asg_max_size         = "2"
   802        asg_desired_capacity = "2"
   803        instance_type        = "m4.large"
   804  
   805        subnets = "${join(",", local.eks_vpc_private_subnets)}"
   806      },
   807    ]
   808  }
   809  
   810  provider "aws" {
   811    version = "~> 2.7.0"
   812    region  = "us-east-1"
   813  }
   814  
   815  variable "eks-cluster-name" {
   816    default = "new-vpc-cluster"
   817    type    = "string"
   818  }
   819  
   820  module "eks" {
   821    source  = "terraform-aws-modules/eks/aws"
   822    version = "3.0.0"
   823  
   824    cluster_name = "${var.eks-cluster-name}"
   825  
   826    subnets = ["${local.eks_vpc_private_subnets}", "${local.eks_vpc_public_subnets}"]
   827  
   828    vpc_id = "${local.eks_vpc}"
   829  
   830    worker_group_count = "${local.worker_group_count}"
   831    worker_groups      = "${local.worker_groups}"
   832  }
   833  `,
   834  		},
   835  	}
   836  	for _, test := range tests {
   837  		t.Run(test.name, func(t *testing.T) {
   838  			req := require.New(t)
   839  			actual, err := renderTerraformContents(test.vpc)
   840  			req.NoError(err)
   841  			if actual != test.expected {
   842  				diff := difflib.UnifiedDiff{
   843  					A:        difflib.SplitLines(test.expected),
   844  					B:        difflib.SplitLines(actual),
   845  					FromFile: "expected contents",
   846  					ToFile:   "actual contents",
   847  					Context:  3,
   848  				}
   849  
   850  				diffText, err := difflib.GetUnifiedDiffString(diff)
   851  				req.NoError(err)
   852  
   853  				t.Errorf("Test %s did not match, diff:\n%s", test.name, diffText)
   854  			}
   855  		})
   856  	}
   857  }
   858  
   859  func TestBuildAsset(t *testing.T) {
   860  	type args struct {
   861  		asset   api.EKSAsset
   862  		builder *templates.Builder
   863  	}
   864  	tests := []struct {
   865  		name    string
   866  		args    args
   867  		want    api.EKSAsset
   868  		wantErr bool
   869  	}{
   870  		{
   871  			name: "basic",
   872  			args: args{
   873  				asset: api.EKSAsset{
   874  					ClusterName: `{{repl "cluster_name_built"}}`,
   875  					Region:      `{{repl "region_built"}}`,
   876  				},
   877  				builder: &templates.Builder{},
   878  			},
   879  			want: api.EKSAsset{
   880  				ClusterName: "cluster_name_built",
   881  				Region:      "region_built",
   882  			},
   883  		},
   884  		{
   885  			name: "created vpc",
   886  			args: args{
   887  				asset: api.EKSAsset{
   888  					CreatedVPC: &amazoneks.EKSCreatedVPC{
   889  						VPCCIDR: `{{repl "vpc_cidr_built"}}`,
   890  						Zones: []string{
   891  							`{{repl "zone_0_built"}}`,
   892  							`{{repl "zone_1_built"}}`,
   893  						},
   894  						PublicSubnets: []string{
   895  							`{{repl "public_0_built"}}`,
   896  							`{{repl "public_1_built"}}`,
   897  						},
   898  						PrivateSubnets: []string{
   899  							`{{repl "private_0_built"}}`,
   900  							`{{repl "private_1_built"}}`,
   901  						},
   902  					},
   903  				},
   904  				builder: &templates.Builder{},
   905  			},
   906  			want: api.EKSAsset{
   907  				CreatedVPC: &amazoneks.EKSCreatedVPC{
   908  					VPCCIDR: "vpc_cidr_built",
   909  					Zones: []string{
   910  						"zone_0_built",
   911  						"zone_1_built",
   912  					},
   913  					PublicSubnets: []string{
   914  						"public_0_built",
   915  						"public_1_built",
   916  					},
   917  					PrivateSubnets: []string{
   918  						"private_0_built",
   919  						"private_1_built",
   920  					},
   921  				},
   922  			},
   923  		},
   924  		{
   925  			name: "existing vpc",
   926  			args: args{
   927  				asset: api.EKSAsset{
   928  					ExistingVPC: &amazoneks.EKSExistingVPC{
   929  						VPCID: `{{repl "vpc_id_built"}}`,
   930  						PublicSubnets: []string{
   931  							`{{repl "public_0_built"}}`,
   932  							`{{repl "public_1_built"}}`,
   933  						},
   934  						PrivateSubnets: []string{
   935  							`{{repl "private_0_built"}}`,
   936  							`{{repl "private_1_built"}}`,
   937  						},
   938  					},
   939  				},
   940  				builder: &templates.Builder{},
   941  			},
   942  			want: api.EKSAsset{
   943  				ExistingVPC: &amazoneks.EKSExistingVPC{
   944  					VPCID: "vpc_id_built",
   945  					PublicSubnets: []string{
   946  						"public_0_built",
   947  						"public_1_built",
   948  					},
   949  					PrivateSubnets: []string{
   950  						"private_0_built",
   951  						"private_1_built",
   952  					},
   953  				},
   954  			},
   955  		},
   956  		{
   957  			name: "multiple groups",
   958  			args: args{
   959  				asset: api.EKSAsset{
   960  					ClusterName: `{{repl "cluster_name_built"}}`,
   961  					AutoscalingGroups: []amazoneks.EKSAutoscalingGroup{
   962  						{
   963  							Name:        `{{repl "asg_0_name_built"}}`,
   964  							GroupSize:   `{{repl "asg_0_size_built"}}`,
   965  							MachineType: `{{repl "asg_0_type_built"}}`,
   966  						},
   967  						{
   968  							Name:        `{{repl "asg_1_name_built"}}`,
   969  							GroupSize:   `{{repl "asg_1_size_built"}}`,
   970  							MachineType: `{{repl "asg_1_type_built"}}`,
   971  						},
   972  					},
   973  				},
   974  				builder: &templates.Builder{},
   975  			},
   976  			want: api.EKSAsset{
   977  				ClusterName: "cluster_name_built",
   978  				AutoscalingGroups: []amazoneks.EKSAutoscalingGroup{
   979  					{
   980  						Name:        "asg_0_name_built",
   981  						GroupSize:   "asg_0_size_built",
   982  						MachineType: "asg_0_type_built",
   983  					},
   984  					{
   985  						Name:        "asg_1_name_built",
   986  						GroupSize:   "asg_1_size_built",
   987  						MachineType: "asg_1_type_built",
   988  					},
   989  				},
   990  			},
   991  		},
   992  	}
   993  	for _, tt := range tests {
   994  		t.Run(tt.name, func(t *testing.T) {
   995  			req := require.New(t)
   996  
   997  			got, err := buildAsset(tt.args.asset, tt.args.builder)
   998  			if !tt.wantErr {
   999  				req.NoErrorf(err, "buildAsset() error = %v", err)
  1000  			} else {
  1001  				req.Error(err)
  1002  			}
  1003  
  1004  			req.Equal(tt.want, got)
  1005  		})
  1006  	}
  1007  }