github.com/mweagle/Sparta@v1.15.0/sparta_test.go (about)

     1  package sparta
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"strings"
     8  	"testing"
     9  	"time"
    10  
    11  	spartaCFResources "github.com/mweagle/Sparta/aws/cloudformation/resources"
    12  	gocf "github.com/mweagle/go-cloudformation"
    13  )
    14  
    15  type StructHandler1 struct {
    16  }
    17  
    18  func (handler *StructHandler1) handler(ctx context.Context,
    19  	props map[string]interface{}) (string, error) {
    20  	return "StructHandler1 handler", nil
    21  }
    22  
    23  type StructHandler2 struct {
    24  }
    25  
    26  func (handler *StructHandler2) handler(ctx context.Context,
    27  	props map[string]interface{}) (string, error) {
    28  	return "StructHandler2 handler", nil
    29  }
    30  
    31  func testLambdaStructData() []*LambdaAWSInfo {
    32  	var lambdaFunctions []*LambdaAWSInfo
    33  
    34  	handler1 := &StructHandler1{}
    35  	lambdaFn1, _ := NewAWSLambda(LambdaName(handler1.handler),
    36  		handler1.handler,
    37  		lambdaTestExecuteARN)
    38  	lambdaFunctions = append(lambdaFunctions, lambdaFn1)
    39  
    40  	handler2 := &StructHandler2{}
    41  	lambdaFn2, _ := NewAWSLambda(LambdaName(handler2.handler),
    42  		handler2.handler,
    43  		lambdaTestExecuteARN)
    44  	lambdaFunctions = append(lambdaFunctions, lambdaFn2)
    45  
    46  	return lambdaFunctions
    47  }
    48  
    49  func testLambdaDoubleStructPtrData() []*LambdaAWSInfo {
    50  	var lambdaFunctions []*LambdaAWSInfo
    51  
    52  	handler1 := &StructHandler1{}
    53  	lambdaFn1, _ := NewAWSLambda(LambdaName(handler1.handler),
    54  		handler1.handler,
    55  		lambdaTestExecuteARN)
    56  	lambdaFunctions = append(lambdaFunctions, lambdaFn1)
    57  
    58  	handler2 := &StructHandler1{}
    59  	lambdaFn2, _ := NewAWSLambda(LambdaName(handler2.handler),
    60  		handler2.handler,
    61  		lambdaTestExecuteARN)
    62  	lambdaFunctions = append(lambdaFunctions, lambdaFn2)
    63  
    64  	return lambdaFunctions
    65  }
    66  
    67  func userDefinedCustomResource1(ctx context.Context,
    68  	event spartaCFResources.CloudFormationLambdaEvent) (map[string]interface{}, error) {
    69  	return nil, nil
    70  }
    71  
    72  func userDefinedCustomResource2(ctx context.Context,
    73  	event spartaCFResources.CloudFormationLambdaEvent) (map[string]interface{}, error) {
    74  	return nil, nil
    75  }
    76  
    77  func TestStruct(t *testing.T) {
    78  	testProvision(t, testLambdaStructData(), nil)
    79  }
    80  
    81  func TestDoubleRefStruct(t *testing.T) {
    82  	testProvision(t,
    83  		testLambdaDoubleStructPtrData(),
    84  		assertError("Failed to reject struct exporting duplicate targets"))
    85  }
    86  
    87  func TestCustomResource(t *testing.T) {
    88  	lambdaFuncs := testLambdaStructData()
    89  	lambdaFuncs[0].RequireCustomResource(IAMRoleDefinition{},
    90  		userDefinedCustomResource1,
    91  		nil,
    92  		nil)
    93  
    94  	lambdaFuncs[1].RequireCustomResource(IAMRoleDefinition{},
    95  		userDefinedCustomResource2,
    96  		nil,
    97  		nil)
    98  	testProvision(t, lambdaFuncs, nil)
    99  }
   100  
   101  func TestDoubleRefCustomResource(t *testing.T) {
   102  	lambdaFuncs := testLambdaStructData()
   103  
   104  	for _, eachLambda := range lambdaFuncs {
   105  		eachLambda.RequireCustomResource(IAMRoleDefinition{},
   106  			userDefinedCustomResource1,
   107  			nil,
   108  			nil)
   109  	}
   110  	testProvision(t,
   111  		lambdaFuncs,
   112  		assertError("Failed to reject multiply included custom resource"))
   113  }
   114  
   115  func TestSignatureVersion(t *testing.T) {
   116  	lambdaFunctions := testLambdaDoubleStructPtrData()
   117  	lambdaFunctions[0].Options = &LambdaFunctionOptions{
   118  		SpartaOptions: &SpartaOptions{
   119  			Name: "Handler0",
   120  		},
   121  	}
   122  	lambdaFunctions[1].Options = &LambdaFunctionOptions{
   123  		SpartaOptions: &SpartaOptions{
   124  			Name: "Handler1",
   125  		},
   126  	}
   127  	testProvision(t,
   128  		lambdaFunctions,
   129  		nil)
   130  }
   131  
   132  func TestUserDefinedOverlappingLambdaNames(t *testing.T) {
   133  	lambdaFunctions := testLambdaDoubleStructPtrData()
   134  	for _, eachLambda := range lambdaFunctions {
   135  		eachLambda.Options = &LambdaFunctionOptions{
   136  			SpartaOptions: &SpartaOptions{
   137  				Name: "HandlerX",
   138  			},
   139  		}
   140  	}
   141  	testProvision(t,
   142  		lambdaFunctions,
   143  		assertError("Failed to reject duplicate lambdas with overlapping user supplied names"))
   144  }
   145  
   146  func invalidFuncSignature(ctx context.Context) string {
   147  	return "Hello World!"
   148  }
   149  
   150  func TestInvalidFunctionSignature(t *testing.T) {
   151  	var lambdaFunctions []*LambdaAWSInfo
   152  	invalidSigHandler, _ := NewAWSLambda("InvalidSignature",
   153  		invalidFuncSignature,
   154  		IAMRoleDefinition{})
   155  	lambdaFunctions = append(lambdaFunctions, invalidSigHandler)
   156  
   157  	testProvision(t,
   158  		lambdaFunctions,
   159  		assertError("Failed to reject invalid lambda function signature"))
   160  }
   161  
   162  func TestNOP(t *testing.T) {
   163  	template := gocf.NewTemplate()
   164  	s3Resources := gocf.S3Bucket{
   165  		BucketEncryption: &gocf.S3BucketBucketEncryption{
   166  			ServerSideEncryptionConfiguration: &gocf.S3BucketServerSideEncryptionRuleList{
   167  				gocf.S3BucketServerSideEncryptionRule{
   168  					ServerSideEncryptionByDefault: &gocf.S3BucketServerSideEncryptionByDefault{
   169  						KMSMasterKeyID: gocf.String("SomeKey"),
   170  					},
   171  				},
   172  				gocf.S3BucketServerSideEncryptionRule{
   173  					ServerSideEncryptionByDefault: &gocf.S3BucketServerSideEncryptionByDefault{
   174  						KMSMasterKeyID: gocf.String("SomeOtherKey"),
   175  					},
   176  				},
   177  			},
   178  		},
   179  	}
   180  	template.AddResource("S3Bucket", s3Resources)
   181  	json, _ := json.MarshalIndent(template, "", " ")
   182  	fmt.Printf("\n%s\n", string(json))
   183  }
   184  
   185  func TestGlobalTransform(t *testing.T) {
   186  	transformName := fmt.Sprintf("Echo%d", time.Now().Unix())
   187  	template := gocf.NewTemplate()
   188  	s3Resources := gocf.S3Bucket{
   189  		BucketEncryption: &gocf.S3BucketBucketEncryption{
   190  			ServerSideEncryptionConfiguration: &gocf.S3BucketServerSideEncryptionRuleList{
   191  				gocf.S3BucketServerSideEncryptionRule{
   192  					ServerSideEncryptionByDefault: &gocf.S3BucketServerSideEncryptionByDefault{
   193  						KMSMasterKeyID: gocf.String("SomeKey"),
   194  					},
   195  				},
   196  				gocf.S3BucketServerSideEncryptionRule{
   197  					ServerSideEncryptionByDefault: &gocf.S3BucketServerSideEncryptionByDefault{
   198  						KMSMasterKeyID: gocf.String("SomeOtherKey"),
   199  					},
   200  				},
   201  			},
   202  		},
   203  	}
   204  	template.AddResource("S3Bucket", s3Resources)
   205  	template.Transform = []string{transformName}
   206  	json, _ := json.MarshalIndent(template, "", " ")
   207  	output := string(json)
   208  	fmt.Printf("\n%s\n", output)
   209  
   210  	if !strings.Contains(output, transformName) {
   211  		t.Fatalf("Failed to find global Transform in template")
   212  	}
   213  }
   214  
   215  func TestResourceTransform(t *testing.T) {
   216  	transformName := fmt.Sprintf("Echo%d", time.Now().Unix())
   217  	template := gocf.NewTemplate()
   218  	s3Resources := gocf.S3Bucket{
   219  		BucketEncryption: &gocf.S3BucketBucketEncryption{
   220  			ServerSideEncryptionConfiguration: &gocf.S3BucketServerSideEncryptionRuleList{
   221  				gocf.S3BucketServerSideEncryptionRule{
   222  					ServerSideEncryptionByDefault: &gocf.S3BucketServerSideEncryptionByDefault{
   223  						KMSMasterKeyID: gocf.String("SomeKey"),
   224  					},
   225  				},
   226  				gocf.S3BucketServerSideEncryptionRule{
   227  					ServerSideEncryptionByDefault: &gocf.S3BucketServerSideEncryptionByDefault{
   228  						KMSMasterKeyID: gocf.String("SomeOtherKey"),
   229  					},
   230  				},
   231  			},
   232  		},
   233  	}
   234  	bucketResource := template.AddResource("S3Bucket", s3Resources)
   235  	bucketResource.Transform = &gocf.FnTransform{
   236  		Name: gocf.String(transformName),
   237  		Parameters: map[string]interface{}{
   238  			"SomeValue": gocf.Integer(42),
   239  		},
   240  	}
   241  
   242  	template.Transform = []string{transformName}
   243  	json, _ := json.MarshalIndent(template, "", " ")
   244  	output := string(json)
   245  	fmt.Printf("\n%s\n", output)
   246  
   247  	if !strings.Contains(output, transformName) {
   248  		t.Fatalf("Failed to find resource Transform in template")
   249  	}
   250  	if !strings.Contains(output, "SomeValue") {
   251  		t.Fatalf("Failed to find resource Parameters in template")
   252  	}
   253  }
   254  func TestProvisionID(t *testing.T) {
   255  	logger, _ := NewLogger("info")
   256  	testUserValues := []string{
   257  		"",
   258  		"DEFAULT_VALUE",
   259  	}
   260  	for _, eachTestValue := range testUserValues {
   261  		buildID, buildIDErr := provisionBuildID(eachTestValue, logger)
   262  		if buildIDErr != nil {
   263  			t.Fatalf("Failed to compute buildID: %s", buildIDErr)
   264  		}
   265  		if eachTestValue == "" && buildID == "" {
   266  			t.Fatalf("Failed to extract buildID. User: %s, Computed: %s", eachTestValue, buildID)
   267  		}
   268  		if eachTestValue != "" &&
   269  			buildID != eachTestValue {
   270  			t.Fatalf("Failed to roundTrip buildID. User: %s, Computed: %s", eachTestValue, buildID)
   271  		}
   272  	}
   273  
   274  }