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 }