diff --git a/api/dist/kernel.json b/api/dist/kernel.json index 02d52deade..48299035e4 100644 --- a/api/dist/kernel.json +++ b/api/dist/kernel.json @@ -82,6 +82,10 @@ "Condition": "Development", "Value": { "Ref": "EncryptionKey" } }, + "Internal": { + "Condition": "Development", + "Value": { "Ref": "Internal" } + }, "LogGroup": { "Value": { "Ref": "LogGroup" } }, @@ -198,6 +202,12 @@ "Type": "String", "Default": "" }, + "Internal": { + "Type": "String", + "Description": "Create applications that are only accessible inside the VPC", + "Default": "No", + "AllowedValues": [ "Yes", "No" ] + }, "InstanceBootCommand": { "Type": "String", "Description": "A single line of shell script to run as CloudInit command early during instance boot.", @@ -1576,7 +1586,7 @@ "Tasks": [ { "Command": "api/bin/web", - "CPU": { "Ref": "ApiCpu" }, + "Cpu": { "Ref": "ApiCpu" }, "Environment": { "AWS_REGION": { "Ref": "AWS::Region" }, "AWS_ACCESS": { "Ref": "KernelAccess" }, @@ -1588,6 +1598,7 @@ "DYNAMO_BUILDS": { "Ref": "DynamoBuilds" }, "DYNAMO_RELEASES": { "Ref": "DynamoReleases" }, "ENCRYPTION_KEY": { "Ref": "EncryptionKey" }, + "INTERNAL": { "Ref": "Internal" }, "LOG_GROUP": { "Ref": "LogGroup" }, "NOTIFICATION_HOST": { "Fn::GetAtt": [ "Balancer", "DNSName" ] }, "NOTIFICATION_TOPIC": { "Ref": "NotificationTopic"}, diff --git a/api/models/app.go b/api/models/app.go index 5f1af21ef8..7e305c481c 100644 --- a/api/models/app.go +++ b/api/models/app.go @@ -158,6 +158,7 @@ func (a *App) Create() error { params := map[string]string{ "Cluster": os.Getenv("CLUSTER"), + "Internal": os.Getenv("INTERNAL"), "Private": os.Getenv("PRIVATE"), "Subnets": os.Getenv("SUBNETS"), "SubnetsPrivate": subnetsPrivate, diff --git a/api/models/release.go b/api/models/release.go index e146d49229..a305dca2cc 100644 --- a/api/models/release.go +++ b/api/models/release.go @@ -234,32 +234,30 @@ func (r *Release) Promote() error { proxyParam := fmt.Sprintf("%sPort%dProxy", UpperName(entry.Name), mapping.Balancer) secureParam := fmt.Sprintf("%sPort%dSecure", UpperName(entry.Name), mapping.Balancer) - app.Parameters[protoParam] = entry.Labels[fmt.Sprintf("convox.port.%d.protocol", mapping.Balancer)] + proto := entry.Labels[fmt.Sprintf("convox.port.%d.protocol", mapping.Balancer)] - // default protocol is tcp, or tls if they have a certificate set - if app.Parameters[protoParam] == "" { - if app.Parameters[certParam] == "" { - app.Parameters[protoParam] = "tcp" - } else { - app.Parameters[protoParam] = "tls" + // if the proto param is set and doesnt match the label, error + if ap, ok := app.Parameters[protoParam]; ok { + if ap != proto { + return fmt.Errorf("%s parameter has been deprecated. Please set the convox.port.%d.protocol label instead", protoParam, mapping.Balancer) } } - if entry.Labels[fmt.Sprintf("convox.port.%d.proxy", mapping.Balancer)] == "true" { - app.Parameters[proxyParam] = "Yes" - } else { - app.Parameters[proxyParam] = "No" + // if the proxy param is set and doesnt match the label, error + if ap, ok := app.Parameters[proxyParam]; ok { + if ap == "Yes" && entry.Labels[fmt.Sprintf("convox.port.%d.proxy", mapping.Balancer)] != "true" { + return fmt.Errorf("%s parameter has been deprecated. Please set the convox.port.%d.proxy label instead", proxyParam, mapping.Balancer) + } } - // only change the secure parameter if a label is set for backwards compat - switch entry.Labels[fmt.Sprintf("convox.port.%d.secure", mapping.Balancer)] { - case "true": - app.Parameters[secureParam] = "Yes" - case "false": - app.Parameters[secureParam] = "No" + // if the secure param is set and doesnt match the label, error + if ap, ok := app.Parameters[secureParam]; ok { + if ap == "Yes" && entry.Labels[fmt.Sprintf("convox.port.%d.secure", mapping.Balancer)] != "true" { + return fmt.Errorf("%s parameter has been deprecated. Please set the convox.port.%d.secure label instead", secureParam, mapping.Balancer) + } } - switch app.Parameters[protoParam] { + switch proto { case "https", "tls": if app.Parameters[certParam] == "" { name := fmt.Sprintf("cert-%s-%d-%05d", os.Getenv("RACK"), time.Now().Unix(), rand.Intn(100000)) diff --git a/api/models/templates.go b/api/models/templates.go index 3a93390aa0..23ea205a83 100644 --- a/api/models/templates.go +++ b/api/models/templates.go @@ -76,7 +76,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _templatesAppTmpl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xec\x7c\x7b\x73\xdb\x38\x92\xf8\xff\xf9\x14\x28\xd6\xfc\x4a\x4e\x22\xd3\x4e\x66\x7f\x7b\x7b\x9a\x49\xaa\x1c\x59\x49\x3c\xe3\xd8\x3a\xc9\xc9\xd6\x4d\x92\x9a\xa2\x49\xd8\xe2\x98\x22\x35\x7c\xf8\x31\x2e\x7d\xf7\xeb\x06\x40\x12\x4f\x91\x7e\x24\x5b\xf7\xf0\xee\xc4\x26\xd0\x68\x34\x1a\x8d\x46\x77\xa3\x81\xdb\x5b\x12\xd1\xb3\x38\xa5\xc4\x0b\x56\x2b\x8f\xac\xd7\x4f\x08\x81\xc2\x1f\xe0\x8b\x8c\x5e\x11\x7f\x0f\x7e\x37\x85\xcb\x20\x8d\xcf\x68\x51\xb2\x9a\x0f\xf5\x07\xaf\x86\xff\x08\xf1\xf6\xfe\x39\x3f\xa1\xcb\x55\x12\x94\xf4\x6d\x96\x2f\x83\xf2\x13\xcd\x8b\x38\x4b\x3d\x32\x22\xde\xcb\xdd\x17\xbb\xdb\xbb\xff\x0e\xff\xf7\x86\x1c\x7c\x9c\xa5\x51\x5c\x42\x7d\xe1\x8d\x04\x0a\xd6\x53\x29\x70\x10\xef\x34\x48\x82\x34\xa4\xf9\x76\xd8\x82\xea\x7d\x1b\x8d\x56\x79\x16\xd2\xa2\xb8\x53\x9b\x9c\x9e\xc7\x45\x99\xdf\x74\x35\xf2\xa6\x79\x7c\x09\x2d\x90\x60\xe2\xbd\x4d\x47\xa3\xc9\x9f\x55\x90\xe0\x00\x3e\x63\xc9\x8c\x9e\xc1\x9f\x0d\x14\x59\x0f\x89\xf7\x9f\x14\x70\x7d\x85\x3f\x6b\x1c\x6f\x60\x50\x17\x73\x1a\x56\x79\x5c\xde\xbc\xcb\xb3\x6a\x85\x0c\xba\x95\xd1\xc1\xf7\xe7\x5b\x86\x0d\x59\xa7\xc2\x22\x4e\xef\x2b\xa7\x48\x20\xf5\xa6\x41\x1e\x2c\x69\x09\xec\x66\xa8\x36\xf2\x72\x85\xb0\x77\xe0\xa3\x15\xbe\x1e\xcb\x38\xa9\x0a\xe8\x56\x9a\x40\x28\x3c\xb9\x59\x51\x4e\x78\x99\xc7\xe9\xb9\x37\x6c\xab\xf6\xe9\x59\x50\x25\x25\xab\x55\xcb\x8b\x30\x8f\x57\x65\x2d\x2d\x9e\xa8\x6a\xb9\xb6\x4f\x57\x49\x76\xb3\xa4\x69\xf9\x21\xb8\x8e\x97\xd5\xd2\xd2\x27\x34\x3c\xaa\x96\xa7\x40\x8f\xa5\x4b\x26\x83\xbb\xae\x4e\xa1\x56\xe0\x25\x2b\x9a\x87\xd0\x4d\x70\x4e\x49\x76\x46\x04\x1b\x68\x41\xca\x8c\x5c\x50\xba\x22\x79\x95\xa6\x30\x2c\x72\xb5\x88\x13\x0a\x2b\x08\xe9\xc2\x61\x6e\x22\x39\x4e\xef\x49\xf2\x8b\xcd\x24\x73\xbc\x8f\x47\xf2\x24\xbd\x8c\xf3\x2c\x45\x9a\xed\xc4\xba\xa7\x74\xc3\x8c\x5a\x27\xf4\x57\x7a\xf3\xad\xbb\x90\x56\x6b\xbf\x6e\x14\x7c\xe3\x9c\xe2\x42\x88\x53\x10\xf0\x34\x48\x48\x92\x05\x11\xa9\x97\x51\x01\xe5\xc0\x68\x86\x9f\x14\xd5\x69\x4a\xcb\xc2\x41\xf2\x51\x26\x57\xec\x25\x49\x76\x45\xa3\x4f\x41\x52\x51\xae\x37\x98\x86\x18\x32\x38\xf2\xd5\x18\xc3\x8c\x26\x34\x28\x6c\x63\x78\xec\x15\x36\xa3\xab\xac\x88\xcb\x2c\xb7\xcd\xcb\xc3\x3a\x9b\x67\x15\x08\x28\x09\xb3\x88\x92\xbc\xed\xc6\x20\x41\xd5\x74\x8f\x4d\xc5\xc9\x82\x92\x43\x79\x12\x49\x21\xfa\x23\xe7\xd8\x21\x39\xcb\x72\x52\x2e\xe2\x82\xe0\x76\x68\x12\x27\x66\xd9\x4e\xd6\x21\x6c\x20\x3f\xc3\x0e\x08\x3a\x7c\xfc\x72\x34\xe2\xc0\xa3\xd1\x41\xf4\xfa\x3e\xa4\x7e\x9a\x8e\x6b\xa9\xea\x47\x95\x5b\xd4\xbf\x0d\x71\x9a\xe8\x77\x10\x59\x1b\x02\x0a\x75\xda\x72\xdb\x9a\x4d\xfe\xe3\xe3\xc1\x6c\xb2\xff\x94\x1c\x06\xcb\xd3\x28\x20\x63\xd8\x5b\xb2\xe5\x49\xb6\x8a\x43\xf2\x3e\x48\xa3\x04\x66\x4c\x2c\x07\x52\x63\x94\xc8\x04\x65\x78\x48\xd3\xf3\x72\xc1\x88\x7c\x21\x57\x69\x6b\xde\xa4\x6f\x3a\x76\x70\xae\x65\x1a\xc0\x20\xc7\xee\xcb\xb0\x0e\x06\x4d\xc7\xe3\x83\xfd\xd9\xa3\x8b\x3c\xf6\x8c\x88\xed\xdd\x2b\x36\xc4\x07\xa8\x81\x5e\x64\xf9\xf6\xa6\x59\x5e\x4e\xf3\xac\xcc\xc2\x2c\x51\x69\x5b\x94\xe5\x8a\x5b\x41\x28\x5b\x34\xa5\xb9\x04\xe7\xbd\x3f\x39\x99\xa2\x4a\x3b\x48\x8b\x12\x57\x9a\xad\x8e\xad\x75\xea\x82\x98\x7b\x2d\x77\x44\x77\xc5\xe6\xfe\xe6\x0f\xee\x50\xe9\xb1\x0c\x37\x8c\xef\x64\xec\x1c\x9e\xa8\x72\x77\x36\x9f\x1f\xea\x5d\x25\x1b\x86\x86\xe0\x0f\xeb\x8a\xac\xad\xf3\x3d\xa3\x05\xd3\xca\xca\x84\x4b\x4b\x6e\x96\x25\x8e\x9d\x93\xad\x89\x83\xbd\x0f\xa3\x11\x83\x91\x46\x02\x9d\x83\x29\x52\xc6\x54\xd5\x92\xb8\xed\x15\x45\xb5\xa4\x08\x3f\xcd\x92\x38\xbc\xd9\xcf\xc2\xca\xb0\x32\xf8\x52\x68\x74\x05\xfa\x0c\x2f\xb7\xc1\x6d\x78\xf1\x6f\x52\x27\x0c\x68\x5e\x82\xf2\x11\xed\x3f\x2b\x55\x44\xc3\xc7\xc0\x27\x67\x67\x34\x64\x9b\x31\xdb\x7e\x35\x6c\x82\xf4\x38\x0d\xe3\x55\x90\xf0\xa9\x98\xd3\xfc\x32\x0e\x29\xdf\xa0\x13\xa6\x8f\xfc\x60\x19\xfc\x95\xa5\xc1\x55\xe1\x87\xd9\x52\xb1\xe9\xe5\x81\x86\x42\xa1\x41\xbb\xa2\x2c\x46\xed\xc0\xdb\xdd\xbd\xfe\x59\x2b\xdf\x72\xad\x82\x19\xcc\x7b\x50\x6a\x40\xfc\x8e\xa7\x16\x23\x27\x39\xaf\x55\x1e\xe8\x1c\xe0\x90\x37\x47\xe0\x23\x30\x1e\x44\x4b\xb0\x1b\xc1\xdf\x09\x60\x17\x36\x78\xe1\x75\x4c\x10\x83\xe9\x33\x49\x0c\x50\x99\x28\x64\xac\x31\x15\x12\xcb\xbc\x67\xf8\x59\x0b\x26\x2f\x20\xeb\x0e\xb6\xc9\x5f\x2d\xe4\xda\x50\xb1\x92\x68\x6f\x10\x6b\xbe\xf5\x8c\x46\x6f\xab\x94\x53\xd5\x4b\xba\xc7\x60\xd8\x98\x92\x3c\xff\xf1\x4d\x15\x5e\xd0\xb2\xf5\x16\x7f\xc9\x62\x21\x1a\xdb\x30\x52\xf8\x05\xfe\xe6\x65\x76\x0d\x7f\xb7\xce\x23\x23\x63\x06\x0e\x29\xaa\x70\x18\xbc\x29\x67\x80\x58\x18\xcf\x3a\x56\x8e\x34\xe7\x7b\xe4\x8e\x82\xb6\xf1\xc5\xd1\x7f\xdc\x39\x63\xfe\x39\x7c\xfb\x7f\xc5\x2b\x8f\x77\xe2\x14\x3f\xb1\xf7\x22\x16\xb1\x12\xe8\x35\xb7\x89\x55\x79\xfc\x40\x97\x60\xd5\xcd\xe3\xbf\x18\x3b\x5f\xbc\xfc\x87\x5a\x5d\x2b\x14\x4e\xf4\x3b\x5a\xee\x95\x5c\x2a\x0c\xad\x83\x32\x91\xa7\xc6\x0a\xf3\x66\x55\x5a\xc6\x5c\x86\x53\xe0\xf8\x1f\x85\xda\xc1\x09\xd4\x65\x15\x93\xad\x1f\x77\x3d\xb7\x28\xd8\xfd\xe2\xbc\xd1\x87\xc4\x77\xb8\xc4\x21\xb8\x46\x7f\x64\xa7\x7d\x40\x6b\xef\x59\x06\xed\xe9\x70\x17\x5c\xf5\x6c\x40\xde\x84\x2b\x5c\xd8\x6d\x8d\x6a\x5b\xd7\x73\x20\x2d\x4a\x1e\xb2\x50\x77\x89\xe3\xaa\x5c\x55\x65\x77\x84\x26\x13\x70\xc4\xdf\x3c\xb8\x16\xae\x6f\x48\xc6\xde\xa2\xf5\x18\xca\x52\xb3\x5a\x50\x3d\xa1\x77\xc5\x65\x4d\x88\x7f\x03\xa7\xef\x86\x4f\xf0\x3f\xe8\x99\xa6\x11\xc3\x2b\x05\xc5\x6c\x91\xa4\x3a\x1c\x96\x07\x29\x38\xdb\x3f\x5c\xb0\x68\xd8\x24\x05\x42\x51\xbb\x16\xf5\x60\x78\x90\x07\xe0\xaa\x15\xa8\x0c\x84\x5b\xaf\xdb\x2d\xc5\x8c\x1d\xe1\xca\xf5\x24\x81\x07\x47\x3c\x38\x4d\x68\xa4\x62\x68\x9b\x1e\x65\x6c\xe9\x58\x83\x50\x58\x32\x07\x15\x10\xf2\xd5\xb5\x2b\x6b\x01\x15\xdf\xdb\x5a\x0b\x70\x45\x83\x9a\x61\xfb\x05\xa3\x42\x10\xd2\xf2\x65\x33\x87\xea\x18\x91\xc6\x1d\xea\xe2\x4e\x4b\x06\x55\xc8\x90\x2c\x91\x5a\x2b\x8f\xb3\xe5\x32\xd8\xa7\x49\xbc\x8c\x4b\x1a\xa1\x85\xe4\x49\x01\x96\x36\x4e\x32\xdc\x1d\xbe\xfc\xff\x7f\x97\xeb\x14\xef\x82\x07\x59\x8c\xe8\x48\x5e\xa5\x43\x32\x9e\x7e\x24\x55\x1a\x97\xbc\x84\xe2\xfa\xa3\x43\x02\x4a\x8f\x7c\x78\x83\x2d\x66\x7b\x1f\xa4\x1a\xaf\x5d\x1f\x7d\xd9\xd3\x88\x30\x1b\xbf\x77\x98\x9d\xab\x0e\xae\x45\x5e\x1b\x18\x2e\xa1\xc3\x8e\x1e\x24\x45\xe0\xea\x43\xdd\xe6\xb2\xf3\x82\xfd\xcb\x81\xfa\x74\xd1\xaa\xa5\x5e\x21\x61\x47\x18\x39\x3e\x6b\x9b\xf9\xef\x03\xf0\x5b\xeb\xd9\x10\xb2\xa1\x49\x4f\x0b\x2c\x96\x4f\x21\x45\x63\x25\x31\xf2\x51\xc0\xa0\x6a\x32\x9e\x9f\x04\xc5\xc5\x3e\x12\x1f\x97\x16\x9f\x73\x05\x43\x2c\x8e\xd9\x7e\xa9\x98\x04\xc3\xc6\xe6\x63\x5b\xd0\x57\x8b\xf7\xc8\xc1\xd1\x1d\xd4\xfb\x90\x80\x25\xcb\xe8\x85\xbf\xdb\xcf\x7c\x10\x1d\x9f\x64\x17\x34\xed\xdc\x21\x9d\xbb\xa3\x30\xef\x1c\xa6\x86\x66\x60\x80\x5d\x16\x5e\xb0\x16\x6c\xd9\xe3\x74\x35\x3c\xf4\x4c\xa3\x43\x0e\x43\x35\x88\xea\x32\x0d\x54\x8b\x21\x36\xe0\x72\xb9\xd6\xa4\x31\x67\x04\x28\x7e\x6b\x20\xc8\x71\xae\xe2\x54\x53\x97\x8f\xf6\xe0\x8c\x8f\x55\x53\xbb\xcd\x90\x6a\xdd\xab\x5b\xa8\x16\xd3\xb6\xb6\x92\x55\x96\x58\x4c\xdb\x83\x65\x70\x2e\x41\xb2\x4f\x3b\xe8\xed\x2d\x8a\x3d\xf5\x99\x2e\x4b\x23\x7f\x2f\xcf\x83\x9b\xf5\xda\x80\x23\x42\xdd\xa5\x91\xc5\xad\xa9\x51\xd5\xcb\x23\x4e\x23\x7a\x3d\x04\xb4\x09\xb3\xaf\xd9\x62\xe9\xd3\x85\x4c\x12\xc3\xb1\x5e\x0f\x6f\x6f\x69\x52\xd0\xf5\x1a\x7e\xa7\xd1\x86\x56\x30\xd4\xba\x3f\x18\xa8\x83\x40\x17\x8a\xaf\x36\xc6\x60\xbf\xa8\x14\x52\x2a\x53\xcf\x03\x1e\xb0\x23\x76\x31\x09\xd8\x71\x89\xba\xd3\xd2\x78\x6d\xf1\xce\x5c\xc4\x79\xe3\x55\xd5\x2e\x1d\x69\xf3\x7c\x61\xdf\x3c\x1b\xb9\x30\x76\x50\x13\x35\xb7\x8a\xad\xd8\x5f\x3e\x1c\xbb\x2b\x60\x2f\x81\xec\x4d\xa7\xb5\x94\xa2\x2a\xde\x20\xd2\xb8\xce\xf7\xc6\xbf\x0a\x68\x9a\x5e\x8a\x6f\x27\x34\xa8\x92\xdf\x67\x93\x77\x07\xc7\x47\x72\x1b\xa9\xd4\xd5\x52\xb2\xa0\xe8\x0d\x08\x31\x9f\x44\x2e\xc2\xd2\x90\x88\x75\xfe\x99\xec\xa2\xc0\xf0\x56\x9e\x67\x07\x23\x7c\x87\xc0\x1e\x84\xed\xd4\x08\x0b\xff\x65\x93\x90\x4d\x02\xdc\xee\x8f\x77\x18\x90\x7f\x18\xa7\x17\x9f\x82\xbc\x70\x11\x69\xd0\xd8\x41\x9d\x9b\x06\xef\xf0\xf8\xdd\xef\xef\x66\xc7\x1f\xa7\x2e\x53\xc2\x3a\x89\xd3\xd9\xf1\x78\x32\x9f\x9b\x3a\xcf\x00\xb6\x09\xe0\xa7\x2c\xa9\x96\x96\x18\x84\xce\x16\xea\x7f\xc8\xc0\x7d\x43\xab\x56\x34\x71\x31\x84\x5b\x09\xf4\x4f\xe2\xbf\xcf\xc0\x9c\xf0\x76\x2e\x83\x7c\x07\x0c\xb5\x9d\x28\x03\x6f\x3a\xf7\x0b\xf8\xe5\x9e\x72\x1c\x04\x6b\xb8\x5e\x8f\xe0\xaf\x71\x06\x7d\x82\x1d\x93\x3b\x04\x91\x73\x14\x95\x90\x13\xa1\xc3\xcb\xde\xb9\xe4\xc3\xd8\x31\xbd\x77\x6d\x73\xdd\x41\xad\xc9\xb8\x8a\x1a\xd6\x41\x9c\xcd\xd1\x97\x49\xdc\x20\x78\xee\x3a\xd2\x9c\x21\x33\xba\x8e\x32\x6e\x68\x12\x13\xd8\xa2\x9c\x6b\xb3\xc4\x39\xb7\x0f\xc3\x8e\xb1\x65\x29\xe6\xbc\x51\x7a\x7c\x04\x76\x0b\x8c\x3e\x41\x23\x9c\x21\xf7\x6c\xba\x15\x2e\x76\x03\xc5\xfe\x9b\xfa\x80\x68\xbd\xc6\xd9\x72\xac\x1c\x36\x0c\x04\x6f\xe6\xd1\xba\x6a\x18\x03\x5c\x93\xfb\x0d\xa7\x0f\x8f\x84\xe2\x84\x9e\xd3\xa8\x5d\xda\x6d\x99\x85\x54\x83\x40\x37\x01\x5a\x4c\xae\x6f\x0c\xce\x6e\xb0\x4b\x8e\x71\x6b\x2d\x37\xd9\x21\xdc\x74\xd4\xbc\x61\x9b\x61\xa6\x1a\xf7\x4f\x14\x1e\x73\xfb\x0b\xfc\x0d\x69\x66\xd5\x98\x9a\xec\xcf\x34\xf3\x5f\x87\x22\x59\x67\x0e\x6b\xd0\x36\x83\xaa\xbd\x6e\x31\xf5\x99\x8f\xd1\x96\x77\x78\x1b\xa6\xf5\xfa\x2f\x74\x33\xa4\x94\x8f\x66\x29\xd5\x65\x1a\x28\xf8\xe0\x71\x4e\xa3\x31\x2a\x7e\xab\x01\xe4\x88\x4d\xf4\x32\x80\xbe\xad\xbf\x63\x3a\x91\x9b\xe8\x34\x3d\x42\xdd\x7d\x6a\x62\x9f\x4d\x3c\xaa\x95\x03\x83\x6b\x5a\xda\xc8\x94\x67\x77\xb4\xab\xd8\x80\xd0\x65\xd2\xcc\x96\xd9\x84\x43\xe4\xbd\xe8\x38\xf0\xa8\xbc\x5e\x08\x96\x33\x06\x69\x67\x77\x68\x67\xbb\x5e\x56\x39\xd9\x7f\xcd\x59\xe6\x6d\x68\x51\xbf\x36\x55\x6b\x57\xb2\x9a\x84\x58\xb5\xab\x53\x99\xc9\x28\xbb\xc2\x40\xd6\x34\x36\x35\x54\xd6\x8c\x5e\x8e\x83\xfc\x20\x42\x2f\x6c\xb8\x60\x4a\x72\xa9\xf3\xa7\x52\xa9\x04\x5c\xf7\x32\xcd\xa1\xdb\x6b\x84\x5f\x81\x1f\x54\x9e\x81\x53\x2c\x6a\xfe\x1f\x74\xab\xe0\xd4\x43\x2e\xbe\xbc\x27\xab\x71\x16\x1d\xbd\x75\xaf\x04\xca\xae\xb5\xe4\x11\x67\x8e\x9c\x3e\xbe\x0d\x08\xa5\x34\x3a\xdb\x8e\xd2\x8b\x34\x7e\x48\xfa\x98\xb4\x09\x8c\x4e\xe2\xee\x25\x21\xf6\x40\xaa\x5d\x3a\x9a\x2c\x16\xf4\x32\xee\x32\x97\x42\x7b\xd5\xed\x35\x81\xb2\x0c\xb5\xfe\xd3\x72\x6e\xd6\x9d\x9e\xa0\xe1\xba\x5b\x4e\xd2\x7d\xa8\x1d\xe3\xee\x77\x16\x87\xee\x74\x98\xc7\xcc\x9a\xba\x0f\x85\xcc\xa6\xbc\x27\x2f\x59\xc8\x46\xea\x6c\x16\xa4\x51\xb6\x2c\xc8\x56\x5c\x66\x41\xdb\xcb\xd3\xef\xc2\x6a\xdb\xaa\xea\x39\x14\x35\x2b\xce\x20\xef\x01\x19\x73\xf7\x19\x88\x3d\xc9\xa5\xe7\x50\x30\x7f\xe3\xfe\x63\x61\x99\x34\xc3\x3a\xc5\x65\xc8\x33\x4f\x86\x1c\xeb\xe3\x8d\x4e\xd7\xcb\xff\xda\x59\xba\x97\x6e\x54\x4f\x51\x5c\x07\x0c\x42\xfb\x7d\xd0\xcd\x8a\x6e\xd5\xd9\xec\x93\x0d\x8b\x35\xce\x6a\xcb\x76\xb3\x8b\xa2\xb5\x6d\x0f\xa6\xa4\xb3\x1e\xdd\xfc\xc6\x69\x53\xcc\x1f\x6e\xe3\xec\x1f\xcd\xb9\xe5\xfa\x55\x4d\xe1\xf9\x8e\xba\x7e\xb3\x37\xe6\xc0\xae\xf8\x2b\xc6\x09\xd7\x83\x88\xdb\xe8\x5b\xde\x1d\x5f\xed\x4a\x7c\x8b\x01\x4b\xe2\xe6\xcb\x26\x35\x6b\x53\xe6\x18\x8e\x0c\xda\xa8\xec\x23\xac\x13\xfd\x2c\xf0\x1b\xac\x14\x8b\xa0\xba\x52\x77\x1f\xc8\x49\xf5\xd8\x92\x67\xaf\x2a\x3d\x35\x80\x0e\xbf\xd7\x63\x60\xea\x69\xb0\xe1\x98\x90\x1e\x2e\xe3\xf6\x69\x23\x7c\x9a\x8b\xa1\xa6\x2d\x1f\xa4\xe7\x30\x03\xba\xc3\xd4\xb5\x56\x05\x94\xee\x41\xb1\xc8\x85\x3f\x11\xe9\x36\xa6\x8b\xe5\x8d\xe3\x28\x3f\x40\x7e\x7b\xbb\x3e\xfb\xdf\xce\xae\x79\xc8\xe5\x8a\x70\xb6\xad\xa5\x3c\x21\x91\x89\x6a\x89\x06\x39\x42\x55\xde\xc1\x4a\x4e\x3a\x64\xdb\x97\x0e\xf2\x36\xcf\x96\x38\xf0\xc7\xd4\x00\x46\x27\x27\xd9\x63\x77\xa1\x06\xb9\xba\xa2\x3e\xdd\x0e\xa5\x1c\xe7\xf9\xb4\x0a\x0f\x22\x9d\xf5\x46\x7a\xca\xd0\xb9\xe0\x6c\xc9\x12\x7c\x91\x24\x41\x51\xc6\x61\xab\x6b\x40\xd2\xf0\xac\xbf\x55\x3d\xed\xa2\xb9\xdf\x16\xa6\x04\xda\x7a\x68\x83\x76\xdc\xae\x55\xda\xc6\xfc\xe7\xe1\x82\x02\x0a\xaf\xbe\x76\xa1\x45\xfa\x3d\x5e\x2f\xe6\xb6\x86\xd6\x43\x17\x52\xaa\xbe\x7a\x3e\x5c\xa7\xc9\x0f\x1d\x91\x00\x2d\x9b\xde\x08\x24\xe8\x80\x5a\xb4\x40\x86\xb7\xae\x3a\x95\x32\x03\x97\xda\x5a\x95\x2f\x9c\xab\x94\xb2\xa4\xc4\xfd\x3c\x88\xf1\x3e\x0f\xcf\xd4\xe4\xb8\xc4\xe4\xc1\x07\xee\x29\x43\x39\x1b\xee\xef\xbb\x8a\xb6\x6a\xf1\xc8\xc9\x53\xb0\x8c\xa3\x84\x4a\x29\x74\xc8\x5e\xa9\x48\x84\x60\x24\x34\x79\x56\x14\xbf\x65\x29\xad\xbb\x6c\xab\xde\xd3\x20\x29\x17\xe3\x05\x0d\x2f\xf4\x18\x24\xaf\xba\x39\x59\x80\x8e\x5c\x64\x09\x0b\x4d\xbf\x54\x27\xef\x00\x67\xfe\x92\x25\xe2\x32\x22\x78\x93\xba\xd4\x98\xeb\x93\x20\x3f\xa7\xe6\xe1\xe7\xed\xed\xce\x33\x82\x1a\x9e\x65\xf5\x60\xbe\x23\xf9\x79\x25\xd4\xd4\xeb\xd1\xcf\x2b\x58\xf7\xaf\x77\x7e\x5e\x05\xe5\xe2\x35\x79\xb6\xa3\x47\x83\xe5\xed\x41\x57\x33\x86\x76\x33\x8f\x1a\x6c\xe7\xb0\x7d\x08\x32\x29\xe9\xa6\x47\x40\x8c\x1c\xc7\x5b\xce\x73\x90\xf6\x94\x8d\xf1\x17\x73\x8c\x37\x1d\xa5\x3a\x46\xa5\x50\xc8\x57\xd9\x06\x28\x9b\x91\xdd\xa5\x99\x05\x79\xf0\xd5\x3a\x9c\xae\xd3\x18\x41\x27\x23\xe6\x2d\x78\xca\x07\x29\xec\xb4\x48\x93\x7a\x93\xa1\x75\xb2\x1c\xb9\xf3\x5f\x9d\xe7\x3d\x77\xee\xc1\x82\x7b\x03\x6a\x3d\xd5\xb9\xfd\x71\x52\xd4\x79\x7e\xf9\x3f\x6b\xe2\x6a\x77\xf9\x1b\xce\x5c\xdd\xc5\x77\x99\x3a\xd7\xe1\x1f\xab\xbf\xbb\x1d\xa3\x30\x5d\x9c\x5d\x5a\xb1\xdb\xc8\x35\xcb\x6c\x27\xfe\x52\x37\xa8\x33\xcc\x73\x44\x15\x8d\xfb\x5a\x83\xba\xd9\xb4\x23\xe3\xc8\xa5\x7d\x47\x69\xf5\x31\x5d\x58\xf7\x90\x27\x96\x4e\x9a\x1b\x35\xf7\x34\xc7\xb5\xe4\xb2\xbb\xae\x00\x33\x52\xd6\x23\xff\x4c\x0e\x45\x11\x53\x5a\x89\x2e\xae\x0f\x33\x76\x1b\x44\xcc\xc7\x31\x2e\x20\x39\xb2\x8e\x64\x63\xf2\x5b\x9b\xf5\xc4\x7a\xf9\xe9\xbb\xb3\xc6\xa1\x6f\x1c\x0c\x6a\xe0\x1e\x83\x39\xce\x14\x04\xbc\xe0\x25\x45\xbb\x35\x77\xe2\xa1\xb1\x73\x43\x71\x98\x1e\xe1\xff\x49\xef\x7f\x13\xe9\xfd\xdf\x2d\xb7\xea\x7e\xf4\xd8\x8e\xbc\xe3\x1a\xde\x77\xdf\x62\x78\x94\xbf\xcf\x1a\x55\x6e\x03\x72\xc7\x91\x35\x6e\x85\xcf\xd5\xa8\x0e\x34\x28\xe0\x52\x95\xa5\xe1\x5e\x59\xe6\xf1\x69\x55\x72\x06\xd9\x4d\xd1\x26\xe9\xba\x8b\x0c\x06\x5c\x87\x56\x3d\x74\x3b\x2d\x59\x8a\xb6\x64\x28\x59\xb0\x39\x21\x8f\x21\xda\xc6\xcd\x44\x47\x06\x55\x47\x06\xd7\xa3\x8b\xe4\xe1\x9b\x71\x96\x5d\xc4\x74\x5e\xc6\xe1\x45\x9c\xc2\x50\x9a\x50\x01\x0e\x5c\x15\x80\xe0\x8c\x65\xad\xe0\x39\xbb\x82\x43\x8b\x55\xf3\x58\x76\x8f\x10\xb6\x2b\x30\x2a\x9e\xb5\x69\x04\x9e\xb4\xeb\xc5\xf6\x26\x4e\x8d\xa6\x7d\x07\xa7\x33\xce\xb4\x36\xdb\x68\x00\x2d\xb7\x9a\xb9\x93\x02\x6d\x5d\x21\x76\xcb\xfd\x3f\xe9\x5e\x0b\x4b\xae\x1e\x03\xc8\x2f\xd9\x69\x61\xde\x6f\xc3\x80\x49\xda\x5c\x2b\x75\x05\xef\x9c\xf7\x4f\x9d\xf1\xed\x1a\x52\xba\xb7\xa0\x64\x6e\x6f\x23\xdb\xa4\xbc\xef\x6d\x1c\x85\x7c\x52\x21\x5d\xef\x64\x87\xcb\xfe\x42\x14\x48\x30\x0f\xbc\xbb\xb9\xf1\xe6\xa6\xe4\x07\xbc\xd8\x55\xe2\x54\xc6\xa5\x5a\xef\xb7\x78\xf5\x36\x66\xa4\xe8\x41\x7c\xef\x4b\x6a\x64\x7d\x7a\x83\x0a\x1c\xe3\x02\xf4\x4f\x58\x0e\x7e\xd2\xef\x90\xeb\xdf\x97\x41\x4e\xd8\x21\x2c\x79\x45\x72\xfa\x67\x15\xe7\x74\x6b\xc0\x0a\x06\x4f\x8d\xc6\x08\x1c\x5c\x29\xa0\xf0\xb9\x5d\x44\x17\x0e\xe0\x30\xc9\xaa\xa8\xb9\x76\x0b\xed\x52\x7a\x85\x18\xfc\x31\x56\x34\x89\x6e\x5b\xf6\xd6\x7f\x56\x34\xbf\x29\xf8\xc5\x06\xa9\x4b\xa9\xd8\xd2\xad\x0d\x11\x4f\x30\x01\x1c\xb7\x7a\x2d\xfe\xd3\x1c\x79\x8c\xc8\x40\x97\xa3\x81\xde\x60\xdd\xd9\xa1\xc8\xa1\xf1\x01\x8f\x7f\x74\xbc\x3f\xf9\xfd\xe4\x10\x6f\x06\xfc\x32\x19\x9f\xfc\xfe\xf1\x68\xef\xe3\xc9\xfb\xe3\xd9\xc1\x6f\x93\x7d\x20\x67\xb0\xdb\x3d\x41\xf4\x1a\x83\x64\x45\x2d\x9f\xd0\xea\x4c\xc8\xfe\x16\xbd\xa4\x69\x39\x24\x61\x96\x96\xf4\xba\x7c\x6a\x1f\x1d\xd4\x16\x20\xa2\x7e\x92\x9d\x6f\x0d\xf0\xb5\x91\xc9\xfc\x84\xcc\x26\xe3\xc9\xc1\xa7\xc9\x3e\x8c\x98\x3c\x27\xbf\xcc\x8f\x8f\x7c\xce\xd0\xf8\xec\x86\xa3\x7d\xda\xcd\x59\x86\x5d\x99\x60\x3f\x62\x27\x4e\xa7\x94\xb1\xb4\xd8\xe2\x7c\x1f\x4a\x14\xe7\xf9\x90\x44\x41\x19\x38\x88\xc5\x1f\x50\x2a\x08\xb7\x01\x42\x1f\x16\x42\x1b\xd4\xd6\x7f\xac\x79\xa0\x68\x23\x32\x94\x91\x28\x28\x16\xa7\x59\x90\x47\x4e\x4c\x35\xe4\x2a\x28\x8a\xab\xac\x07\xa0\x38\xbb\x87\x29\xc3\x21\xfb\x9c\x29\x9f\x77\xbf\xfa\xe2\x7e\x71\x8f\x9e\xea\x17\xce\x4c\x1c\xed\xeb\x67\xbd\x26\xaa\xfe\x81\xb9\xda\x42\xd4\xf1\xab\xdd\x9f\x6a\x02\xfd\x84\xbd\x20\xf3\x3a\xfe\x89\xc4\xcf\x9f\x77\x30\x1e\x7f\x70\x8a\x44\xdb\xcf\x71\x3d\x9c\x5f\xe9\x0d\x79\x05\x32\xbd\x5f\x33\x72\xd0\x03\x13\xfe\x34\x9c\x87\x41\x1a\x58\xd9\x8e\xbf\x91\x51\xf8\xa3\x5f\x73\xf0\x36\x56\x76\xf1\x87\xf1\xa6\xe5\xfd\xbd\xd8\xd3\x36\xc7\xb1\x34\x93\x55\x33\x69\x2a\x64\xa8\x2f\x8f\x6a\x99\x03\x16\x39\x30\x7f\x6f\x46\x31\x01\x67\x67\xcb\x4e\xc5\x2a\xff\x2c\xc0\x76\x1c\xb5\x53\x3d\xec\x82\x47\xa5\x37\x22\x7f\xfb\xdb\x8f\xdd\x90\x41\xb9\x00\x3d\xb6\x03\xc6\x58\xb1\x83\xea\x8c\xe9\x2f\x1f\x0f\xff\x9f\x43\x71\x73\xf3\x59\xaa\x13\x65\xac\x3e\xaf\xd2\x41\x67\x1f\xc0\xe1\x45\x16\x41\x2f\xd3\xe3\xf9\x49\x37\xf8\x82\x06\x11\xcc\xcf\xa8\xdf\xdc\x0e\xf6\xc2\x90\xae\xca\x01\xa0\x07\xa2\x13\xf4\xe7\x80\xab\x3b\x7f\x14\x59\x0f\xca\x18\x02\xcc\x05\x86\x71\x6d\xa3\x51\xa5\xa3\xb9\xde\xbe\xba\xba\xda\x46\x15\xbd\x5d\xe5\x20\xc9\xf8\x1c\x59\xd4\x13\xef\xc7\x82\xe6\xdb\x7b\xe7\x80\x1a\xb1\x82\x4d\x99\xec\x18\x1b\xa2\xde\x68\xdd\x89\x3a\xa8\xd8\x84\xf1\x57\x40\x46\x38\x2b\xb5\x74\x6f\x14\xce\x3b\xa9\x39\x94\x4e\x30\x18\x40\x32\x99\x2d\xe3\xa3\xf1\x00\x66\xe9\x96\x90\x58\x69\x4b\x02\xb3\xb6\xc7\x1a\x44\x7c\xa7\x59\x74\x83\x9b\xb6\xb9\x67\xeb\xd0\xca\x9e\x8b\x8f\xc1\x54\xc5\x68\x30\xc4\xbb\xf4\x7e\xc1\xbe\xd0\xca\x73\x6f\x59\x56\x34\xef\x85\x4c\x01\x1e\x6d\xbf\x46\xb4\x42\xe2\x2c\xbb\xb6\x8e\x94\x11\x41\xcb\x09\x0a\x02\x20\xd8\x1a\x54\xe5\xd9\x3f\x2c\x76\x94\xad\x1d\xb0\x6b\x80\xdb\xd0\x40\xe2\x5f\xb8\xa8\xd2\x0b\xe0\x20\x67\xcf\xf3\x57\x84\x15\x90\x75\x7f\x8c\xe0\x73\xc8\x08\x7b\x6a\x44\x99\x39\xd8\x75\x77\x7f\xa2\x15\xda\x4a\x7e\x94\xa5\xd4\x62\x75\xea\xe0\x1d\xa3\xb0\x54\x6f\x02\x07\x21\xe4\x03\xce\xf3\x2c\x1f\xa8\x66\x51\xd6\x65\xf0\xe8\x63\x1e\x4c\xb0\x11\x8a\x03\x6f\xdd\x47\x9a\xd8\xd0\xcf\x82\x38\xd9\xea\xd1\xe6\x8e\x83\x63\xf6\x0a\x28\xf9\x7d\x90\x0f\x58\x25\x92\x91\x2e\x89\x6a\xc7\x08\x41\x27\xb0\xdb\xcc\x03\x70\x62\xb9\xa6\x16\x05\x8f\x3c\x09\x57\xe0\x1c\xd3\xad\x9a\xda\xcd\x6c\x40\x78\x90\xd0\x0d\xc2\x62\xdd\x53\x2d\x54\x81\x06\x93\x0a\xd4\xd7\x87\x2c\x09\x30\x5a\x1a\x9c\x08\xab\x75\xb8\xdb\x2c\x3d\x64\x01\x7b\xa7\xf0\x7b\x67\x95\xf2\x9e\x99\x96\x33\x83\x2c\x2e\x46\x23\x06\xd4\xe9\x72\x4b\xae\xb6\x7f\x98\xa5\xe7\xb5\x67\x5d\x84\x0b\x1a\x55\xea\x93\x68\x73\x51\x36\xb9\x5e\x61\x5a\x98\x48\xb5\xa9\x73\x57\xb0\x46\x4b\x1c\xe4\xf9\x0c\x46\xb0\x8c\x79\xd5\x76\x0f\x5c\x8e\x2b\xb8\x6e\x6d\x1d\x44\x16\x82\x45\xea\x84\x96\x7d\xb1\x12\x47\x72\x5f\xf0\x55\xe8\x2f\xf0\xe7\x17\x4f\x84\x10\x44\xb3\x2f\xd0\xcb\x97\xda\xb9\x6b\x01\x44\xd0\xac\x01\x10\x02\xdb\x02\x88\x0b\xfa\x0c\x40\x3a\x34\xb4\x45\x62\x2c\xf3\xc7\x23\x23\x53\x9a\x2f\xe3\xa2\xb0\x85\x50\x88\x1e\x43\x91\x60\x6d\x53\x4a\x94\x39\x15\x8f\x90\x91\xe6\x91\xab\xd1\x01\x6c\xca\x17\xd4\xf6\x10\x98\x12\x72\x21\xf7\x9c\x14\xe9\xc5\x39\xec\x94\x2d\xf2\x42\x7b\x63\x4e\x96\x23\x16\x71\x62\x68\x9c\xb9\xc3\x86\xb8\x4b\x1d\xdf\x3d\xda\x65\x7d\x14\x9b\xbf\x2e\xc3\x9f\x27\x7b\x1f\x14\x93\xb1\xfc\x66\x25\x23\xea\x38\x57\x02\xe1\xd6\x27\x8a\xac\x4f\x9d\x01\xb1\x55\xb1\x4d\x83\xa2\x64\x8f\x10\xc9\xc9\x50\x77\xc4\x71\x05\x7a\x60\xfb\xe5\x03\x70\xd0\x8a\xe3\x60\x74\x08\x14\x28\xa5\xce\x47\x72\x6c\x2f\x72\xb5\xac\xc2\x1a\xcb\xeb\xba\x96\xab\x9e\x33\x09\x4c\xac\x03\x25\x45\x4f\x61\xbc\x00\xb0\x5e\x05\xb5\xeb\xae\x87\x5f\x01\x95\x5e\x09\x6e\xef\x5f\xba\xb2\x66\x9f\xd4\x12\xd7\xcd\x37\xed\x89\xa4\x9a\x6b\xfc\x68\xa8\x2f\x23\x8c\x1c\x73\x46\x11\xf8\x14\x78\x01\x15\x50\xd5\xb4\x74\x4c\xcb\x5d\x3a\xd2\xd9\x67\xc1\x3b\x34\x98\x26\xd6\xa3\x93\x2b\xda\x53\x6d\xca\x65\x51\xfb\x7b\x4e\xfa\x6b\x9c\x8e\xe9\xef\xf5\x0a\xa7\xf3\x71\x4d\xed\x79\xc3\xf6\xa5\x4b\xa5\x9c\x18\xef\x5e\x2a\xd5\xda\xe1\x4c\xc7\xd3\x9c\xea\xb3\x9c\x7a\x3f\xd2\x23\x9d\x5a\x15\x46\x0b\x43\x5d\x9b\x6a\x30\xee\x2b\xec\x8e\x84\x5d\xeb\x9b\x97\xb5\x5e\x6d\x77\x18\xe3\xb1\x4e\xfb\x09\xa1\xb2\xb9\xab\x27\x32\xf2\x7c\x0f\x4d\x30\xf7\xdb\xa9\x8f\xff\x2c\xaa\x73\x92\x59\x2d\xe5\xa9\xc6\xf8\x32\xfa\x69\x93\x6a\xbc\x2f\x22\x9f\xcf\xac\xe7\x77\xae\x36\x5c\x13\xd0\xbc\x3e\xa8\x2b\x30\x65\xdc\x9a\xb4\xdc\x8d\x6d\xa6\xe3\xfa\x67\x5c\x2e\x7a\xe0\x0a\x5f\x76\x12\x0f\x20\x7b\xe0\xb4\x67\x79\xfc\x17\xb5\xa6\xfd\x1b\xad\x6c\xa7\x91\xd2\x13\xa7\x56\xbe\x3e\xb3\xa0\xd1\x4a\xb4\x13\x44\xab\xf4\xca\x5b\x57\x87\x22\x96\x5f\x7f\x34\x1f\x55\x54\x95\xcd\xfc\xc7\xd1\x48\xbc\x6c\x2a\xb4\xcd\x3e\x4d\x28\xca\x49\x73\xca\x08\x23\xc4\x2b\xd9\x1d\xda\x28\x44\x7b\x11\x23\x36\x39\xbf\x3a\xa0\x67\x67\x83\x2d\xac\xbd\x0d\x72\x5b\xbf\x15\xe6\x15\xe0\x52\xd1\x25\x2a\xd7\xe6\x38\x58\x3c\xa6\x4a\xd4\x5d\x5f\xc0\xe3\xbb\xd7\x43\xe7\x1e\x21\xef\x5a\x36\xb6\x49\x5c\xfb\xaf\x00\x00\x00\xff\xff\x38\xf3\x36\x8f\x36\x65\x00\x00") +var _templatesAppTmpl = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xc4\x3c\x6b\x73\xdb\x38\x92\xdf\xe7\x57\xa0\x58\x73\x25\x67\x22\xd3\x8f\xd9\xdb\xdb\xd3\x5c\xb6\xca\x91\x95\xc4\x33\x7e\xe8\x24\x25\x5b\x37\x89\x6b\x8a\x26\x21\x8b\x63\x8a\xd4\xf0\x61\x5b\x71\xe9\xbf\x5f\x37\x00\x92\x00\x08\x88\xf4\xeb\xce\xbb\x13\x9b\x44\xa3\xd1\xe8\x6e\x34\xba\x1b\x4d\x3c\x3c\x90\x80\xce\xc3\x98\x12\xc7\x5b\xad\x1c\xb2\xd9\xfc\x40\x08\xbc\xfc\x11\x9e\xc8\xe0\x1d\x71\x8f\xe0\x77\xf5\x72\xe9\xc5\xe1\x9c\x66\x39\x6b\x39\x2b\x1f\x78\x33\xfc\x47\x88\x73\xf4\xaf\xe9\x8c\x2e\x57\x91\x97\xd3\x0f\x49\xba\xf4\xf2\x2f\x34\xcd\xc2\x24\x76\xc8\x80\x38\x87\xfb\x07\xfb\xbb\xfb\xff\x09\xff\x77\xfa\x1c\x7c\x98\xc4\x41\x98\x43\x7b\xe6\x0c\x04\x0a\x36\x52\x2e\x70\x10\xe7\xca\x8b\xbc\xd8\xa7\xe9\xae\x5f\x83\xea\x63\x37\x3a\xad\xd2\xc4\xa7\x59\xf6\xa8\x3e\x29\xbd\x0e\xb3\x3c\x5d\xb7\x75\x72\x4e\xe2\x9c\xa6\xb1\x17\x21\xc5\xc4\xf9\x10\x0f\x06\xa3\xbf\x0a\x2f\xc2\x19\x7c\xc5\x37\x13\x3a\x87\x3f\x6b\x30\xb2\xe9\x13\xe7\x7f\x28\x60\xbb\x84\x3f\x4b\x2c\xe3\x34\xbc\x85\x71\x5b\x90\x94\x50\x66\x1c\xef\x81\x35\x37\x53\xea\x17\x69\x98\xaf\x3f\xa6\x49\xb1\x42\x36\x3f\xc8\xe8\xe0\xf9\xeb\x03\xc3\x86\x02\x50\x61\x11\xa7\x73\xc9\xe7\x25\x90\x3a\x63\x2f\xf5\x96\x14\x28\x67\x5d\xb7\x4b\x64\x85\xb0\x8f\x90\x86\x11\xbe\x9c\xcb\x30\x2a\x32\x18\x56\x52\x03\x78\x39\x5b\xaf\x28\x27\x3c\x4f\xc3\xf8\xda\xe9\xd7\x4d\xc7\x74\xee\x15\x51\xce\x5a\xd5\xf7\x99\x9f\x86\xab\xbc\xd4\x39\x47\x34\xd5\x5c\x3b\xa6\xab\x28\x59\x2f\x69\x9c\x9f\x79\xf7\xe1\xb2\x58\x1a\xc6\x84\x8e\xe7\xc5\xf2\x0a\xe8\x31\x0c\xc9\x34\x79\xdf\x36\x28\xb4\x0a\xbc\x64\x45\x53\x1f\x86\xf1\xae\x29\x49\xe6\x44\xb0\x81\x66\x24\x4f\xc8\x0d\xa5\x2b\x92\x16\x71\x0c\xd3\x22\x77\x8b\x30\xa2\xb0\x0e\x91\x2e\x9c\xe6\x36\x92\xc3\xf8\x89\x24\x1f\x6c\x27\x99\xe3\x7d\x39\x92\x47\xf1\x6d\x98\x26\x31\xd2\x6c\x26\xd6\x2e\xd2\x2d\x12\x35\x0a\x54\x5e\x90\xdd\xc6\x51\x10\x5e\xc4\xd1\x9a\x78\x51\x94\xdc\x11\xcf\xc7\xe9\xe2\x64\xf3\x45\x98\x11\xb4\x81\xf3\x34\x59\x92\x30\xce\xc2\x80\xc2\x4b\x4a\xbe\x8c\x87\x16\x9a\xcf\x13\xb9\xe1\x08\x11\xd2\xe0\x8b\x17\x15\x94\xaf\x6a\xb6\x7e\xfb\x0c\x8e\x5c\x36\x26\xf1\x1b\x5d\xbf\x36\x9f\x24\x93\xf3\x04\x36\x7d\xce\x28\x99\x16\x57\x31\xcd\x33\x81\x08\xf9\x94\xad\xa8\x1f\xce\xd7\xc8\x96\x5d\xc6\xa3\x28\xf1\x02\x52\x9a\x08\x42\xe3\x60\x95\x84\x71\x9e\xbd\x0a\xcf\x26\x34\xa2\x5e\x66\x9a\xd0\x4b\xdb\x8c\x09\x5d\x25\x59\x98\x27\xa9\x49\x48\xcf\x1b\x6c\x9a\x14\xb0\xe4\x88\x9f\x00\xf3\xd2\x7a\x98\x06\x09\xaa\xed\x7e\x69\x2a\x66\xa0\xda\xa7\x8a\xe8\x32\x31\x1e\xb9\xc6\x01\xc9\x3c\x49\xab\x45\x61\x20\x8e\x2b\x86\x85\xac\x53\xd8\x58\xff\x0b\x3c\x03\xd8\x95\x86\x87\x83\x01\x07\x1e\x0c\x4e\x82\x7f\x3e\x85\x54\x50\x35\x92\xf1\xf1\xba\x51\x65\xd7\xfb\xd7\x21\x6e\x25\x96\x47\x37\x22\x4b\x07\x49\xa1\x4e\x5b\x7b\x3b\x93\xd1\x7f\x7f\x3e\x99\x8c\x8e\xdf\x90\x53\x6f\x79\x15\x78\x64\x08\xbb\x65\xb2\x9c\x25\xab\xd0\x27\x9f\xbc\x38\x88\x40\x62\x62\x39\x90\x12\xa3\x44\x26\x98\xf7\x53\x1a\x5f\xe7\x0b\x46\xe4\x81\xdc\xa4\x19\x80\x26\x7d\x60\xf0\xcc\x9c\xab\x99\x06\x30\xc8\xb1\xa7\x32\xac\x85\x41\xe3\xe1\xf0\xe4\x78\xf2\xe2\x2a\x8f\x23\x23\x62\xf3\xf0\x8a\x57\x74\x06\x2d\x30\x8a\xac\xdf\xce\x38\x49\xf3\x71\x9a\xe4\x89\x9f\x68\x3b\xcf\x22\xcf\x57\xdc\xaf\x43\xdd\xa2\x31\x4d\x25\x38\xe7\xd3\x6c\x36\x46\x93\x76\x12\x67\x39\xae\x34\x53\x1b\x5b\xeb\xd4\x06\x31\x75\x6a\xee\x88\xe1\xb2\xed\xe3\x4d\x9f\x3d\xa0\x32\x62\xee\x6f\x99\xdf\x6c\x68\x9d\x9e\x68\xb2\x0f\x36\x9d\x9e\xea\x43\x45\x5b\xa6\x86\xe0\xcf\x1b\x8a\x6c\x8c\xf2\x9e\xd0\x8c\x59\x65\x45\xe0\xd2\x92\x9b\x24\x91\x65\x1b\x65\x6b\xe2\xe4\xe8\x6c\x30\x60\x30\xd2\x4c\x60\x70\x70\xae\xf2\x90\xaa\x56\x12\xb7\xbd\x2c\x2b\x96\x14\xe1\xc7\x49\x14\xfa\xeb\xe3\xc4\x2f\x1a\x7e\x13\x5f\x0a\x95\xad\xc0\x58\xea\x70\x17\xc2\xa9\x83\xff\x90\x06\x61\x40\xd3\x1c\x8c\x8f\xe8\xff\x55\x69\x22\x1a\x3e\x06\x3e\x9a\xcf\xa9\xcf\x36\x63\xb6\xfd\x6a\xd8\x04\xe9\x61\xec\x87\xab\x32\xe4\x99\xd2\xf4\x36\xf4\x29\xdf\xa0\x23\x66\x8f\x5c\x6f\xe9\x7d\x4f\x62\xef\x2e\x73\xfd\x64\xa9\x44\x29\xf2\x44\x7d\x61\xd0\xa0\x5f\x96\x67\x83\x7a\xe2\xf5\xee\x5e\xfe\x6c\x94\x67\xb9\x55\xc1\x0c\x01\x0b\x18\x35\x20\x7e\xcf\x51\x5f\x23\x27\x39\xaf\x55\x1e\xe8\x1c\xe0\x90\xeb\x73\x88\x7a\x18\x0f\x82\x25\x78\xc2\x10\x07\x7a\xb0\x0b\x37\x78\xe1\xb4\x08\x88\xc1\x74\x11\x12\x03\x54\x04\x85\x8c\x6d\x88\x42\x62\x99\xf3\x13\x3e\x96\x8a\xc9\x5f\x90\x4d\x0b\xdb\xe4\xa7\x1a\x72\xd3\x30\xb1\x92\x6a\x6f\x51\x6b\xbe\xf5\x0c\x06\x1f\x8a\x98\x53\xd5\x49\xbb\x87\xe0\xd8\x34\x35\x79\xfa\xf3\xfb\xc2\xbf\xa1\x79\x1d\xff\xfe\x0a\x7e\x22\x57\x8d\x5d\x98\x29\xfc\x82\x38\xfc\x36\xb9\x87\xbf\xeb\x70\x98\x91\x31\x81\x40\x1d\x4d\x38\x4c\xbe\xa9\x67\x80\x58\x78\xd2\x3a\x56\x8e\x34\xe5\x7b\xe4\x9e\x82\xb6\xca\x51\x60\x44\xbc\x37\x67\x79\x0b\x78\x76\xbf\x87\x2b\x87\x0f\x62\x55\x3f\xb1\xf7\x22\x16\xb1\x12\xe8\xbd\x88\x46\x14\xb8\x33\xba\x04\xaf\x6e\x1a\x7e\x67\xec\x3c\x38\xfc\x87\xda\x5c\x1a\x14\x4e\xf4\x47\x9a\x1f\xe5\x5c\x2b\x1a\x56\x07\x75\x22\x8d\x1b\x2b\xcc\x99\x14\x71\x1e\x72\x1d\x8e\x81\xe3\x7f\x66\xea\x00\x33\x68\x4b\x0a\xa6\x5b\x3f\xef\x3b\x76\x55\x30\x47\xfa\x69\x65\x0f\x89\x6b\x09\xf2\x7d\x08\xf6\xfe\x4c\xae\xba\x80\x96\xf9\x00\x19\xb4\x63\x0a\x21\xe3\xa6\x67\x0b\xf2\x2a\x8d\x63\xc3\x6e\xea\x54\xfa\xba\x8e\x05\x69\x96\xf3\x24\x8c\xba\x4b\x5c\x14\xf9\xaa\xc8\xdb\x33\x57\x89\x80\x23\xee\xf6\xc9\xd5\x70\x5d\x53\x55\xe6\x1e\x75\xc4\x90\xe7\x9a\xd7\x82\xe6\x09\xa3\x2b\xae\x6b\x42\xfd\x2b\x38\x7d\x37\xfc\x01\xff\x83\x91\x21\x8a\x63\x78\xa5\x64\xa1\x29\xc3\x56\xa6\x09\x53\x2f\xbe\xa6\xe4\xc7\x1b\x96\x25\x1c\xc5\x40\x28\x5a\xd7\xac\x9c\x0c\x4f\x5b\x01\x5c\xb1\x02\x93\x81\x70\x9b\x4d\xbd\xa5\x34\xb3\x61\xb8\x72\x1d\x49\xe1\x9d\x51\xec\x5d\x45\x34\x50\x31\xd4\x5d\xcf\x13\xb6\x74\x8c\x69\x35\x7c\x33\x05\x13\xe0\xf3\xd5\xb5\x2f\x5b\x01\x15\xdf\x87\xd2\x0a\x70\x43\x83\x96\x61\xf7\x80\x51\x21\x08\xa9\xf9\xb2\x9d\x43\x65\xd6\x4b\xe3\x0e\xb5\x71\xa7\x26\x83\x2a\x64\x48\x9e\x48\x69\x95\x87\xc9\x72\xe9\x1d\xd3\x28\x5c\x86\x39\x0d\xd0\x43\x72\xa4\x94\x51\x9d\xf9\xe9\xef\xf7\x0f\xff\xfd\xef\x72\x9b\x12\x5d\xf0\xb4\x51\x23\xdf\x93\x16\x71\x9f\x0c\xc7\x9f\x49\x11\x87\x39\x7f\x43\x71\xfd\xd1\x3e\x01\xa3\x47\xce\xde\x63\x8f\xc9\xd1\x99\xd4\xe2\xd4\xeb\xa3\x2b\x7b\x2a\x15\x66\xf3\x77\x4e\x93\x6b\x35\xc0\x35\xe8\x6b\x05\xc3\x35\xb4\xdf\x32\x82\x64\x08\x6c\x63\xa8\xdb\x5c\x72\x9d\xb1\x7f\x39\x50\x97\x21\x6a\xb3\xd4\x29\x55\x6e\x49\xaf\x87\xf3\xba\x9b\xfb\xc9\x83\xb8\xb5\x94\x86\xd0\x0d\x4d\x7b\x6a\x60\xb1\x7c\x32\x29\x4b\x2d\xa9\x91\x8b\x0a\x06\x4d\xa3\xe1\x74\xe6\x65\x37\xc7\x48\x7c\x98\x1b\x62\xce\x15\x4c\x31\xbb\x60\xfb\xa5\xe2\x12\xf4\x2b\x9f\x8f\x6d\x41\x97\x86\xe8\x91\x83\x63\x38\xa8\x8f\x21\x01\x4b\x9e\xd1\x81\xbb\xdf\xcd\x7d\x10\x03\xcf\x92\x1b\x1a\xb7\xee\x90\xd6\xdd\x51\xb8\x77\x16\x57\x43\x73\x30\xc0\x2f\xf3\x6f\x58\x0f\xb6\xec\x51\x5c\x15\x0f\x9d\xa6\xd3\x21\xa7\xa1\x2a\x44\xe5\x3b\x0d\x54\xcb\x8a\x56\xe0\xf2\x7b\xad\x4b\xe5\xce\x08\x50\x7c\xd6\x40\x90\xe3\xdc\xc4\xa9\xae\x2e\x9f\xed\xc9\x9c\xcf\x55\x33\xbb\xd5\x94\x4a\xdb\xab\x7b\xa8\x06\xd7\xb6\xf4\x92\x55\x96\x18\x5c\xdb\x93\xa5\x77\x2d\x41\xb2\x47\x33\xe8\xc3\x03\xaa\x3d\x75\x99\x2d\x8b\x03\xf7\x28\x4d\xbd\xf5\x66\xd3\x80\x23\xc2\xdc\xc5\x81\x21\xac\x29\x51\x95\xcb\x23\x8c\x03\x7a\xdf\x07\xb4\x11\xf3\xaf\xd9\x62\xe9\x32\x84\x4c\x12\xc3\xb1\xd9\xf4\x1f\x1e\x68\x94\xd1\xcd\x06\x7e\xc7\xc1\x96\x5e\x30\xd5\x72\x3c\x98\xa8\x85\x40\x1b\x8a\x4b\x13\x63\x70\x5c\x34\x0a\x31\x95\xa9\xe7\x09\x0f\xd8\x11\xdb\x98\x04\xec\xb8\x45\xdb\x69\xe8\xbc\x31\x44\x67\x36\xe2\x9c\xe1\xaa\xa8\x97\x8e\xb4\x79\x1e\x98\x37\xcf\x4a\x2f\x1a\x3b\x68\x13\x35\xf7\x8a\x8d\xd8\x0f\x9f\x8f\xdd\x76\x04\x21\x81\x1c\x8d\xc7\xa5\x96\xa2\x29\xde\xa2\xd2\xb8\xce\x8f\x86\xbf\x09\x68\x1a\xdf\x8a\x67\x2b\x34\x98\x92\x3f\x26\xa3\x8f\x27\x17\xe7\x72\x1f\xe9\xad\xad\xa7\xe4\x41\xd1\x35\x28\x31\x17\x22\x57\x61\x69\x4a\xc4\x28\x7f\xa6\xbb\xa8\x30\xbc\x97\xe3\x98\xc1\x08\xdf\x21\x70\x04\xe1\x3b\x55\xca\xc2\x7f\x99\x34\x64\x9b\x02\xd7\xfb\xe3\x23\x26\xe4\x9e\x86\xf1\xcd\x17\x2f\xcd\x6c\x44\x36\x68\x6c\xa1\xce\x4e\x83\x73\x7a\xf1\xf1\x8f\x8f\x93\x8b\xcf\x63\x9b\x2b\x61\x14\xe2\x78\x72\x31\x1c\x4d\xa7\x4d\x9b\xd7\x00\x36\x29\xe0\x97\x24\x2a\x96\x86\x1c\x84\xce\x16\xea\x9e\x25\x10\xbe\xa1\x57\x2b\xba\xd8\x18\xc2\xbd\x04\xfa\x17\x71\x3f\x25\xe0\x4e\x38\x7b\xb7\x5e\xba\x07\x8e\xda\x5e\x90\x40\x34\x9d\xba\x19\xfc\xb2\x8b\x1c\x27\xc1\x3a\x6e\x36\x03\xf8\x6b\x98\xc0\x98\xe0\xc7\xa4\x16\x45\xe4\x1c\x45\x23\x64\x45\x68\x89\xb2\xf7\x6e\xf9\x34\xf6\x9a\xd1\xbb\xb6\xb9\xee\xa1\xd5\x64\x5c\x45\x0b\x6b\x21\xce\x14\xe8\xcb\x24\x6e\x51\x3c\x7b\x1b\xa9\x4e\xc5\x19\x5d\xe7\x09\x77\x34\x49\x13\xd8\x60\x9c\x4b\xb7\xc4\x2a\xdb\xe7\x61\xc7\xdc\xb2\x94\x73\xde\xaa\x3d\x2e\x02\xdb\x15\x46\x17\xd0\x00\x25\x64\x97\xa6\xdd\xe0\xe2\x30\xf0\xda\x7d\x5f\x1e\x10\x6d\x36\x28\x2d\xcb\xca\x61\xd3\x40\xf0\x4a\x8e\xc6\x55\xc3\x18\x60\x13\xee\x2b\x8a\x0f\x8f\x84\xc2\x88\x5e\xd3\xa0\x5e\xda\xf5\x3b\x03\xa9\x0d\x02\xed\x04\x68\x39\xb9\xae\x39\x38\xb3\xc3\x2e\x05\xc6\xb5\xb7\x5c\x55\xcd\x70\xd7\x51\x8b\x86\x4d\x8e\x99\xea\xdc\xff\xa0\xf0\x98\xfb\x5f\x10\x6f\x48\x92\x55\x73\x6a\x72\x3c\x53\xc9\xbf\x4c\x45\xb2\xc1\x2c\xde\xa0\x49\x82\xaa\xbf\x6e\x70\xf5\x59\x8c\x51\xbf\x6f\x89\x36\x9a\xde\xeb\xff\x63\x98\x21\x15\xb1\x54\x4b\xa9\x7c\xa7\x81\x42\x0c\x1e\xa6\x34\x18\xa2\xe1\x37\x3a\x40\x96\xdc\x44\x27\x07\xe8\x75\xe3\x9d\x66\x10\xb9\x8d\xce\x66\x44\xa8\x87\x4f\x55\xee\xb3\xca\x47\xd5\x7a\xd0\xe0\x9a\x56\x08\x33\xe6\xf5\x2a\xf5\x2a\x6e\x40\xe8\x3a\xd9\xac\xff\xd9\x86\x43\x54\xf2\xe8\x38\xf0\xa8\xbc\x5c\x08\x86\x33\x06\x69\x67\xb7\x58\x67\xb3\x5d\x56\x39\xd9\x7d\xcd\x19\xe4\xd6\x37\x98\x5f\x93\xa9\x35\x1b\x59\x4d\x43\x8c\xd6\xd5\x6a\xcc\x64\x94\x6d\x69\x20\x63\x79\x9f\x9a\x2a\xab\x66\x2f\xe7\x41\x7e\x14\xa9\x17\x36\x5d\x70\x25\xb9\xd6\xb9\x63\xe9\xad\x04\x5c\x8e\x32\x4e\x61\xd8\x7b\x84\x5f\x41\x1c\x94\xcf\x21\x28\x16\x2d\xff\x06\xc3\x2a\x38\xf5\x94\x8b\x2b\xef\xc9\x52\x9e\xa5\x8c\xaa\xf5\x31\x8c\x1b\xe6\x10\x8d\xcf\x3c\xf4\x1b\xd5\x08\xd6\x02\x40\x7d\xaa\xad\x68\x99\x2a\x34\x8a\x65\x9e\x24\x12\x73\xe6\xd2\x2c\x8e\xaa\x6c\x04\xdd\xfa\xce\xcc\xab\xcd\x45\xd9\x5f\x93\xe0\x63\x78\xf8\x2a\x85\x3f\x4f\xa1\x90\xb9\x45\x4f\x21\x0d\x37\x63\xcc\x3a\x48\x83\x4d\x20\x6a\x4f\x96\x19\xd9\x09\xf3\xc4\xab\x47\x79\xd3\xd8\xde\xb7\x4e\xe4\x49\xe2\x57\x33\xb3\xb6\xa4\xa5\x10\xf0\x99\x6e\xaa\xda\xb5\xa3\x5a\x7b\x15\x8f\x35\xd6\x6a\x7c\xdc\xee\xf6\x68\x7d\xeb\x64\xb7\x94\x3f\xd6\xb7\x74\x94\x9b\x62\x52\xb9\xdd\x3c\x3e\x9f\xf2\xdd\xf0\x52\x2d\x0b\x78\x15\x75\x2e\xff\x7c\x8c\x87\x67\xc1\xae\xf8\x40\x62\xd6\x8e\x36\xdc\xcb\x68\x78\xf9\x67\xe9\x66\xbc\x02\xe1\xb2\xda\xb8\xf2\x76\xcb\xfa\xe4\x29\xa6\x2a\xbc\x3a\x63\xf3\x02\xfa\xae\x9f\x13\xbc\x82\xc6\x1b\x14\xce\x56\xd6\xf7\x4c\x4e\xaa\x47\x1a\xbc\xb2\x4d\x19\x49\xaa\x0a\x35\xfa\xc4\x0e\x03\x53\x4f\x8a\x1a\x4e\x0b\xe9\xe0\x4e\xee\x96\xa4\x36\xdc\x0f\xb5\xa4\xf1\x24\xbe\x06\x09\xe8\xce\x54\xdb\x9a\x13\x50\xba\x77\xc5\xa2\x1a\x77\x24\x8e\xe2\x9b\xee\x97\x33\x0c\x83\xf4\x04\xf9\xed\xec\xbb\xec\x7f\x7b\xfb\xcd\x04\xb8\x2d\xfb\x51\xf7\x96\x6a\x08\x44\x95\x9a\x21\x52\xb4\x84\xb1\xce\xc9\x4a\x2e\x48\xc2\xa2\xaa\x46\xbd\xc9\x87\x34\x59\xe2\xc4\x4d\x2b\xb9\x01\x3c\x4b\x6c\xa0\x6a\x40\xda\x16\xa1\xb5\x3b\x7f\x72\x4c\xf6\x65\xe5\x9f\x04\x3a\x2b\x1a\x47\xc9\x7d\xeb\x02\x30\x1d\x6c\x72\xa5\x8d\xbc\x2c\x0f\xfd\x7a\xed\x83\xe4\xf1\x5c\xae\x36\x05\xb5\x12\x3f\x6d\x6b\x50\x82\xe2\x0e\xab\xb3\x9e\xb7\x75\xd5\x4c\xfd\x05\x95\x43\xaf\xf2\xf0\xa5\xaa\x51\x57\xc2\x88\xd0\xf4\xb6\xce\xf1\x71\x64\x12\x58\x23\x32\xaf\x5a\x34\x91\x1a\xd4\xb6\x8b\x4b\xdf\xd4\x06\x6d\xc1\xd6\x65\xbe\xea\xf4\xca\x12\xdb\xbe\x51\x8d\xb4\x3a\x5c\x4d\x03\x75\x30\x45\xd1\x94\xe1\x41\xca\x31\x65\xa5\x47\xc7\x29\x04\x35\xa0\x0f\xbc\x1e\x8b\xd3\x23\xc4\x0e\x0f\xb8\x3b\xf4\xe5\x9a\x97\xbf\xef\x5b\xf0\xc8\x25\x12\x20\xa4\x20\xa2\x52\xa1\x0c\xea\x83\xf4\x4a\x04\x5a\x12\x9a\x34\xc9\xb2\xdf\x93\x98\x96\x43\xd6\x4d\x9f\xa8\x17\xe5\x8b\xe1\x82\xfa\x37\x7a\xa6\x81\x37\xad\x67\x0b\xb0\x76\x8b\x24\x62\x09\xa8\x43\x55\x2d\x98\xb2\xdc\xb2\x72\x3b\x46\x04\xef\x52\xbe\x6d\x04\xa3\x33\x2f\xbd\x36\x57\x52\x35\x72\x7d\x12\xba\xd2\xf6\x00\xba\x81\x66\x4b\x0c\xf1\xbc\xc5\x27\x10\xa8\xe0\xc9\x96\x0e\x94\x47\xf4\xf2\x85\x66\x8d\x0c\xc9\x05\x95\xff\xbc\xa7\x24\x01\x05\xf8\x73\xbc\x30\x72\xb3\x8e\x4c\x25\x99\x94\x15\xa4\x2f\xb9\xc5\x28\xfb\x30\x67\xa7\x6b\x4a\x58\x3a\xb2\xa5\x57\x5d\x1b\xad\xae\x95\xf5\xef\xbe\x15\xa9\xa8\x4d\x27\xbe\x0d\x2f\xfb\x89\xb1\x56\xbf\x2e\xaa\xc5\xd2\x59\x43\xce\xd6\xba\xd1\xc9\x36\xbb\xf3\x6e\x66\x2a\xda\x55\x38\xa7\x03\x98\x39\x57\xe3\xe1\x03\x9b\x72\x55\x8f\x0c\xed\x9a\x33\x47\x96\x48\xbc\x2a\xf7\xc3\xd7\x93\x45\x43\x0b\xac\xd6\x7d\x1b\xe8\x73\xc9\x68\x24\xdb\x2f\xf5\xfa\xd3\x97\x75\x35\x2c\x45\xbd\x1d\x17\x70\x73\xc1\xde\xaf\xb7\xad\x5a\x43\xfd\x83\x5a\x2b\xcc\x37\x1c\x05\x8f\xb1\x7a\x9a\x75\x2a\x5d\x1b\x05\x5c\x6a\x32\x95\x4b\xe7\x79\x1a\x5e\x15\x39\x9f\xb0\xe9\xfc\x5a\x2a\xc9\x68\x23\x83\x01\x57\x51\x21\x6e\x57\x86\x33\x4c\xd3\x51\x89\xbc\x7e\x38\x21\x2f\xb1\x82\x1a\x75\xcb\xed\x59\xc9\xe7\xeb\xcf\xe9\xfb\x61\x92\xdc\x84\x74\x0a\x6e\xe5\x0d\x04\x7f\x59\x56\xf9\x0f\x38\x2b\x55\xba\xde\x9c\x25\xac\xb1\xd8\x46\xc1\xa1\x85\xa2\x3c\x54\xed\x10\xa1\xda\xe2\x1e\xf1\x8d\x6e\x65\x2d\x48\xad\xdc\xa6\x0f\x7c\xab\x42\xdd\xea\xf8\xa9\xd5\x6d\xdd\x34\xfb\x68\x00\x35\xb7\x2a\xc1\x48\x7e\x7b\x5b\x04\x6d\x28\xfd\x95\x4a\xda\x58\x5d\x05\xb8\x4a\xf1\xaf\xc9\x55\xd6\x2c\x6d\x45\x2f\x2a\xae\x2a\xca\x6d\xb1\x80\xb5\xf4\xdc\xea\x88\x97\x90\x52\xc9\x92\x52\xb4\xb1\x8b\x6c\x93\x4a\x3e\x76\x71\x16\x72\x22\x42\xaa\xec\x66\x49\x39\x77\x21\x5e\x48\x30\xcf\x2c\xdb\xde\x5a\xb4\x2d\x79\x42\x07\xfb\x8a\xf3\xda\xa8\xa7\x77\x7e\x0f\x57\x1f\x42\x46\x8a\xee\x03\x3a\xdf\xe2\xa6\x13\xd8\x2b\xc0\x95\xc8\xc0\xb8\xf8\x79\xef\x17\xfd\xf3\x11\xfd\xf9\xd6\x4b\x09\xfb\xc4\x88\xbc\x23\x29\xfd\xab\x08\x53\xba\xd3\x63\x2f\x7a\x6f\x1a\x9d\x11\xd8\xbb\x53\x40\xe1\x71\x37\x0b\x6e\x2c\xc0\x7e\x94\x14\x41\x55\x71\x0f\xfd\x62\x7a\x87\x18\xdc\x21\x36\x54\x67\x5c\x3b\xe6\xde\x7f\x15\x34\x5d\x67\xbc\xa6\x49\x1a\x52\x7a\x6d\x18\xd6\x84\x88\xa7\xba\x01\xc7\x83\xde\x8a\xff\x54\x19\x8d\x01\xe9\xe9\x7a\xd4\xd3\x3b\x6c\x5a\x07\x14\xf9\x7c\x17\xf0\xb8\xe7\x17\xc7\xa3\x3f\x66\xa7\x58\x14\xf4\xeb\x68\x38\xfb\xe3\xf3\xf9\xd1\xe7\xd9\xa7\x8b\xc9\xc9\xef\xa3\x63\x20\xa7\xb7\xdf\x2e\x20\x7a\xbf\x42\xd3\x5c\xea\x27\xf4\x9a\x0b\xdd\xdf\xa1\xb7\x34\xce\xfb\xc4\x4f\x20\x74\xb8\xcf\xdf\x98\x67\x07\xad\x19\xa8\xa8\x1b\x25\xd7\x3b\x3d\xfc\xd0\x70\x34\x9d\x91\xc9\x68\x38\x3a\xf9\x32\x3a\x86\x19\x93\xb7\xe4\xd7\xe9\xc5\xb9\xcb\x19\x1a\xce\xd7\x1c\xed\x9b\x76\xce\x32\xec\x8a\x80\xdd\x80\x25\x94\xae\x28\x63\x69\xb6\xc3\xf9\xde\x97\x28\x4e\xd3\x3e\x09\xbc\xdc\xb3\x10\x8b\x3f\x60\x54\x10\x6e\x0b\x84\x3e\x2d\x84\x6e\x50\x5b\xfe\xb1\xe1\xae\xf5\x56\x64\xa8\x23\x81\x97\x2d\xae\x12\x2f\x0d\xac\x98\x4a\xc8\x95\x97\x65\x77\x49\x07\x40\x91\x62\x07\x91\xe1\x94\x5d\xce\x94\xaf\xfb\x97\xae\xf8\xb4\xa0\xc3\x48\xe5\x75\x0d\x4d\x1c\xf5\x55\x0e\x9d\x04\x55\xfe\x80\xac\x76\x10\x75\xf8\x6e\xff\x97\x92\x40\x37\x62\x1f\x8f\xfe\x33\xfc\x85\x84\x6f\xdf\xb6\x30\x1e\x7f\x50\x44\xa2\xef\xd7\xb0\x9c\xce\x6f\x74\x4d\xde\x81\x4e\x1f\x97\x8c\xec\x75\xc0\x84\x3f\x15\xe7\x61\x92\x0d\xac\x6c\xc7\xdf\xca\x28\xfc\xd1\x03\x03\x67\x6b\x63\x1b\x7f\x18\x6f\x6a\xde\x3f\x89\x3d\x75\x77\x9c\x4b\x25\xac\x92\x49\x63\xa1\x43\x5d\x79\x54\xea\x1c\xb0\xc8\x82\xf9\xff\x9a\x51\x4c\xc1\x59\xea\xd8\x6a\x58\xe5\x9f\x05\x38\x86\x83\x5a\xd4\xfd\x36\x78\x34\x7a\x03\xf2\xb7\xbf\xfd\xdc\x0e\xe9\xe5\x0b\xb0\x63\x7b\xe0\x8c\x65\x7b\x68\xce\x98\xfd\x72\x31\xb7\xff\x16\x5e\x57\x1f\x3d\x48\x6d\xe2\x1d\x6b\x4f\x8b\xb8\xd7\x3a\x06\x70\x78\x91\x04\x30\xca\xf8\x62\x3a\x6b\x07\x5f\x50\x2f\x00\xf9\x0c\xba\xc9\xb6\x77\xe4\xfb\x74\x95\xf7\x00\x3d\x10\x1d\x61\xf0\x05\x5c\xdd\xfb\x33\x4b\x3a\x50\xc6\x10\x60\x19\x00\xcc\x6b\x17\x9d\x2a\x1d\xcd\xfd\xee\xdd\xdd\xdd\x2e\x9a\xe8\xdd\x22\x05\x4d\xc6\x9b\x08\x82\x8e\x78\x3f\x67\x34\xdd\x3d\xba\x06\xd4\x88\x15\x7c\xca\x68\xaf\xb1\x21\xea\x9d\x36\xad\xa8\xbd\x82\x09\x8c\x7f\x00\x38\x40\xa9\x94\xda\xbd\x55\x39\x1f\x65\xe6\x50\x3b\xc1\x61\x00\xcd\x64\xbe\x8c\x8b\xce\x03\xb8\xa5\x3b\x42\x63\xa5\x2d\x09\xdc\xda\x0e\x6b\x10\xf1\x5d\x25\xc1\x1a\x37\xed\xe6\x9e\xad\x43\x2b\x7b\x2e\x7e\x07\x5a\x64\x83\x5e\x1f\x3f\xa3\x71\x33\xf6\x84\x5e\x9e\x7d\xcb\x32\xa2\xf9\x24\x74\x0a\xf0\x68\xfb\x35\xa2\x15\x1a\x67\xd8\xb5\x75\xa4\x8c\x08\x9a\x8f\x50\x11\x00\xc1\x4e\xaf\xc8\xe7\xff\x30\xf8\x51\xa6\x7e\xc0\xae\x1e\x6e\x43\x3d\x89\x7f\xfe\xa2\x88\x6f\x80\x83\x9c\x3d\x6f\xdf\x11\xf6\x82\x6c\xba\x63\x84\x98\x43\x46\xd8\xd1\x22\xca\xcc\xc1\xa1\xdb\xc7\x13\xbd\xd0\x57\x72\x83\x24\xa6\x06\xaf\x53\x07\x6f\x99\x85\xa1\x79\x1b\x38\x28\x21\x9f\x70\x9a\x26\x69\x4f\x75\x8b\x92\x36\x87\x47\x9f\x73\x6f\x84\x9d\x50\x1d\x78\xef\x2e\xda\xc4\xa6\x3e\xf7\xc2\x68\xa7\x43\x9f\x47\x4e\x8e\xf9\x2b\x60\xe4\x8f\x41\x3f\x60\x95\x48\x4e\xba\xa4\xaa\x2d\x33\x04\x9b\xc0\x3e\x64\xe8\x41\x10\xcb\x2d\xb5\x78\xf1\xc2\x42\xb8\x83\xe0\x98\xee\x94\xd4\x6e\x67\x03\xc2\x83\x86\x6e\x51\x16\xe3\x9e\x6a\xa0\x0a\x2c\x98\xf4\x42\xfd\xf0\xd8\x70\x9e\xa6\x9d\x72\x8b\x1c\x58\x4b\xb8\x8d\x61\xef\x74\x01\x7b\xa7\x88\x7b\x27\x85\x72\x95\x81\x76\x04\x87\x2c\xce\x06\x03\x06\xd4\x1a\x72\x4b\xa1\xb6\x7b\x9a\xc4\xd7\x65\x64\x9d\xf9\x0b\x1a\x14\xea\x6d\x08\x53\xf1\x6e\x74\xbf\xc2\x53\x5f\x71\x72\xc7\x88\x13\x2d\x5a\x5d\x00\x3f\xe4\x68\x64\xc2\x58\x54\x6d\x8e\xc0\xe5\xbc\x82\xad\x60\xf3\x24\x30\x10\x2c\xce\x53\xb4\x23\x99\x95\x38\x94\xf8\x86\x17\xe5\x7d\x83\x3f\xbf\x39\x22\x85\x20\xba\x7d\x83\x51\xbe\x95\xc1\x5d\x0d\x20\x32\x62\x15\x80\x50\xd8\x1a\x40\x7c\x9b\xc3\x00\xa4\xc3\x11\x53\x26\xc6\x20\x3f\x9e\x19\x19\xd3\x74\x19\x66\x99\x29\x85\x42\xf4\x1c\x8a\x04\x6b\x12\x29\x51\x64\x2a\xee\x1f\x20\xd5\xf7\xed\x83\x13\xd8\x94\x6f\xa8\xe9\x0e\x00\x25\xe5\x42\x9e\x28\x14\xe9\xb2\x09\x1c\x94\x2d\xf2\x4c\xbb\x5e\x42\xd6\x23\x96\x71\x62\x68\xac\x25\x3e\x0d\x75\x97\x06\x7e\x7c\xb6\xcb\x78\x4f\x20\xff\xb0\x94\xdf\x4c\xf0\xc9\xcb\x46\x43\xf9\xba\x1a\x46\xd4\x45\xaa\x64\xad\xb7\x5d\xfa\xa7\xde\x72\x00\xc4\x16\xd9\x2e\xf5\xb2\x9c\x7d\x7f\x2c\xb1\xea\xb1\x38\xee\xc0\x0e\xec\x1e\x3e\x03\x07\x2d\x38\x0e\x46\x87\x40\x81\x5a\x6a\xfd\x3e\xd6\xf4\x31\x7e\xcd\x2a\x6c\x31\x5c\xac\x65\xa8\xf2\x9e\x48\x60\x62\x1d\x28\x27\xfe\x0a\xe3\x05\x80\xb1\x0a\xdc\x6c\xbb\x9e\x5f\xfd\x2d\x5d\x10\x56\x97\x5e\xdb\x8a\x62\x7e\x28\x35\xae\x9d\x6f\xda\xd7\xd1\x25\xd7\xf8\x01\x53\x57\x46\x34\x3e\xa0\x66\x14\x41\x4c\x81\xb5\xe7\x80\xaa\xa4\xa5\x45\x2c\x8f\x19\x48\x67\x9f\x01\x6f\xbf\xc1\x34\xb1\x1e\xad\x5c\xd1\x6e\x69\x50\xea\xc4\xcd\x9f\x72\xeb\x17\xf1\x58\xc4\xdf\xe9\x02\x1e\xeb\xbd\x3a\xda\xcd\x26\xf5\x25\x37\xca\x7b\xd2\xb8\xf2\x46\x69\xd6\x4e\x5e\x5a\x6e\xe5\x51\x6f\xe4\xd1\xc7\x91\xee\xe7\xd1\x9a\x30\x5b\xe8\xeb\xd6\x54\x83\xb1\x7f\xbd\x62\xa9\xff\x31\x5e\x77\x53\xda\xd5\x7a\x87\x69\xdc\xd3\x63\x3e\xce\x53\x36\x77\xf5\x44\x46\x96\x77\xbf\x09\x66\xbf\x36\xe9\xe5\x6f\x44\xb2\x0a\x99\xb5\x52\x5e\xb9\x84\x57\x21\x5e\x55\x95\x4b\xc7\x22\xf3\xf9\x93\xf1\x70\xce\xd6\x87\x5b\x02\x9a\x96\xa7\x70\x19\x56\x84\x19\x6b\xa0\xda\xb1\x4d\x74\x5c\xff\x0a\xf3\x45\x07\x5c\xfe\x61\x2b\xf1\x00\x72\x04\x41\x7b\x92\x86\xdf\xa9\xb1\xaa\xaf\xd1\xcb\x74\xd4\x28\xdd\x6e\x64\xe4\xeb\x4f\x06\x34\xda\x1b\xf5\x10\xf7\xd2\xa8\xbd\xf2\xd6\xd5\x62\x88\xe5\x8b\x5f\x9a\xf7\xa9\xa8\xc6\x66\xfa\xf3\x60\x20\x2e\x35\x12\xd6\xe6\x98\x46\x14\xf5\xa4\x3a\x65\x84\x19\xe2\xd7\x18\x2d\xd6\x88\x5d\x42\x8a\x19\x9b\x94\x57\x3d\xe8\xc5\x55\xe0\x0b\x6b\x9f\x05\x3e\x94\xd7\x04\x38\x19\x84\x54\x74\x89\xc6\xb5\x3a\xeb\x15\xf7\x28\x11\x75\xd7\x17\xf0\x78\xe5\x5d\xdf\xba\x47\xc8\xbb\x96\x89\x6d\x12\xd7\xfe\x37\x00\x00\xff\xff\xbf\x00\x26\x85\x49\x5a\x00\x00") func templatesAppTmplBytes() ([]byte, error) { return bindataRead( diff --git a/api/models/templates/app.tmpl b/api/models/templates/app.tmpl index f6556ede46..1a644a33a1 100644 --- a/api/models/templates/app.tmpl +++ b/api/models/templates/app.tmpl @@ -7,6 +7,7 @@ {{ template "balancer-conditions" .Manifest }} {{ template "process-conditions" .Manifest }} {{ template "registry-conditions" .Manifest }} + "Internal": { "Fn::Equals": [ { "Ref": "Internal" }, "Yes" ] }, "Private": { "Fn::Equals": [ { "Ref": "Private" }, "Yes" ] }, "BlankSecurityGroup" : {"Fn::Equals" : [{"Ref" : "SecurityGroup"}, ""]} }, @@ -34,6 +35,12 @@ "Default": "", "Description": "" }, + "Internal": { + "Type": "String", + "Description": "Only allow access to this app from inside the VPC", + "Default": "No", + "AllowedValues": [ "Yes", "No" ] + }, "Key": { "Type": "String", "Default": "", @@ -41,7 +48,7 @@ }, "Private": { "Type": "String", - "Description": "Create internal load balancers in private subnets", + "Description": "Use SubnetsPrivate to specify VPC-side load balancer endpoints", "Default": "No", "AllowedValues": [ "Yes", "No" ] }, @@ -297,11 +304,8 @@ {{ $processName := upper .ProcessName }} {{ $balancerPrefix := printf "Balancer%s" $processName }} {{ range .PortMappings }} - "{{ $balancerPrefix }}Port{{ .Balancer }}Proxy": { - "Fn::Equals": [ { "Ref": "{{ $processName }}Port{{ .Balancer }}Proxy" }, "Yes" ] - }, - "{{ $balancerPrefix }}Port{{ .Balancer }}Secure": { - "Fn::Equals": [ { "Ref": "{{ $processName }}Port{{ .Balancer }}Secure" }, "Yes" ] + "Blank{{ $balancerPrefix }}Port{{ .Balancer }}Certificate": { + "Fn::Equals": [ { "Ref": "{{ $processName }}Port{{ .Balancer }}Certificate" }, "" ] }, {{ end }} {{ end }} @@ -311,11 +315,6 @@ {{ range .Balancers }} {{ $balancer := . }} {{ range .PortMappings }} - "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Balancer": { - "Type" : "String", - "Default" : "{{ .Balancer }}", - "Description" : "" - }, "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Certificate": { "Type" : "String", "Default" : "", @@ -326,24 +325,6 @@ "Default" : "{{ index $balancer.Randoms (itoa .Balancer) }}", "Description" : "" }, - "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Secure": { - "Type" : "String", - "Default" : "No", - "Description" : "", - "AllowedValues": [ "Yes", "No" ] - }, - "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Protocol": { - "Type" : "String", - "Default" : "tls", - "Description" : "", - "AllowedValues": [ "http", "https", "tcp", "tls" ] - }, - "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Proxy": { - "Type" : "String", - "Default" : "No", - "Description" : "", - "AllowedValues": [ "Yes", "No" ] - }, {{ end }} {{ end }} {{ end }} @@ -359,7 +340,7 @@ {{ range .PortMappings }} "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Balancer": { "Condition": "Enabled{{ upper $balancer.ProcessName }}", - "Value": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Balancer" } + "Value": "{{ .Balancer }}" }, "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}BalancerName": { "Condition": "Enabled{{ upper $balancer.ProcessName }}", @@ -387,8 +368,8 @@ "CidrIp": { "Ref": "VPCCIDR" }, {{ end }} "IpProtocol": "tcp", - "FromPort": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Balancer" }, - "ToPort": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Balancer" } + "FromPort": "{{ .Balancer }}", + "ToPort": "{{ .Balancer }}" }, {{ end }} { "Ref": "AWS::NoValue" } @@ -401,83 +382,54 @@ "Condition": "Enabled{{ upper .ProcessName }}", "DependsOn": [ "{{ .ResourceName }}SecurityGroup" ], "Properties": { - {{ if eq .Scheme "internal" }} - "Scheme": "{{ .Scheme }}", - "Subnets": { "Fn::If": [ "Private", - { "Ref": "SubnetsPrivate" }, - { "Ref": "Subnets" } - ] }, - {{ else }} - "Subnets": { "Ref": "Subnets" }, - {{ end }} + "Scheme": { "Fn::If": [ "Internal", + "internal", + {{ if eq .Scheme "internal" }} + "internal" + {{ else }} + { "Ref": "AWS::NoValue" } + {{ end }} + ] }, + "Subnets": { "Fn::If": [ "Private", + { "Ref": "SubnetsPrivate" }, + { "Ref": "Subnets" } + ] }, "ConnectionDrainingPolicy": { "Enabled": true, "Timeout": 60 }, "ConnectionSettings": { "IdleTimeout": "{{ .IdleTimeout }}" }, "CrossZone": true, "HealthCheck": { "HealthyThreshold": "2", "Interval": "{{ .HealthInterval }}", - "Target": { - {{/* Joins to form :/ */}} - "Fn::Join": [ - "", - [ - { - {{/* Joins to form : */}} - "Fn::Join": [ - ":", - [ - {{ if eq .HealthPath "" }} - { - "Fn::If": [ - "Balancer{{ upper $balancer.ProcessName }}Port{{ .HealthPort }}Secure", - {"Fn::FindInMap": ["PortProtocol", "tcp", "SecureInstanceProtocol"]}, - {"Fn::FindInMap": ["PortProtocol", "tcp", "InstanceProtocol"]} - ] - }, - {{ else }} - { - "Fn::If": [ - "Balancer{{ upper $balancer.ProcessName }}Port{{ .HealthPort }}Secure", - {"Fn::FindInMap": ["PortProtocol", "http", "SecureInstanceProtocol"]}, - {"Fn::FindInMap": ["PortProtocol", "http", "InstanceProtocol"]} - ] - }, - {{ end }} - { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .HealthPort }}Host" } - ] - ] - }, - "{{ .HealthPath }}" - ] - ] - }, - "Timeout": "{{ $balancer.HealthTimeout }}", + "Target": { "Fn::Join": [ "", [ + "{{ .HealthProtocol }}:", + { "Ref": "{{ upper .ProcessName }}Port{{ .HealthPort }}Host" }, + "{{ .HealthPath }}" + ] ] }, + "Timeout": "{{ .HealthTimeout }}", "UnhealthyThreshold": "2" }, "Listeners": [ {{ range .PortMappings }} - { "Fn::If": [ "Balancer{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Secure", - { - "Protocol": { "Fn::FindInMap": [ "PortProtocol", { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Protocol" }, "ListenerProtocol" ] }, - "LoadBalancerPort": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Balancer" }, - "InstanceProtocol": { "Fn::FindInMap": [ "PortProtocol", { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Protocol" }, "SecureInstanceProtocol" ] }, - "InstancePort": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Host" }, - "SSLCertificateId": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Certificate" } - }, - { - "Protocol": { "Fn::FindInMap": [ "PortProtocol", { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Protocol" }, "ListenerProtocol" ] }, - "LoadBalancerPort": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Balancer" }, - "InstanceProtocol": { "Fn::FindInMap": [ "PortProtocol", { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Protocol" }, "InstanceProtocol" ] }, - "InstancePort": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Host" }, - "SSLCertificateId": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Certificate" } - } - ] }, + { + {{ if $balancer.Protocol . }} + "Protocol": "{{ $balancer.ListenerProtocol . }}", + {{ else }} + "Protocol": { "Fn::If": [ "BlankBalancer{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Certificate", "TCP", "SSL" ] }, + {{ end }} + "LoadBalancerPort": "{{ .Balancer }}", + "InstanceProtocol": "{{ $balancer.InstanceProtocol . }}", + "InstancePort": { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Host" }, + "SSLCertificateId": { "Fn::If": [ "BlankBalancer{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Certificate", + { "Ref": "AWS::NoValue" }, + { "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Certificate" } + ] } + }, {{ end }} { "Ref": "AWS::NoValue" } ], "Policies": [ {{ range .PortMappings }} - { "Fn::If": [ "Balancer{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Proxy", + {{ if $balancer.ProxyProtocol . }} { "PolicyName": "EnableProxyProtocol", "PolicyType": "ProxyProtocolPolicyType", @@ -487,8 +439,7 @@ }], "InstancePorts": [{ "Ref": "{{ upper $balancer.ProcessName }}Port{{ .Balancer }}Host" }] }, - { "Ref": "AWS::NoValue" } - ] }, + {{ end }} {{ end }} { "Ref": "AWS::NoValue" } ], diff --git a/docker-compose.yml b/docker-compose.yml index 366f2958cf..87d7979b1a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -15,6 +15,7 @@ web: - DYNAMO_BUILDS - DYNAMO_RELEASES - ENCRYPTION_KEY + - INTERNAL - NOTIFICATION_HOST - NOTIFICATION_TOPIC - PASSWORD diff --git a/manifest/balancer.go b/manifest/balancer.go index 3a3cf116fe..588e157f32 100644 --- a/manifest/balancer.go +++ b/manifest/balancer.go @@ -150,6 +150,51 @@ func (mb ManifestBalancer) Scheme() string { return "internal" } +// Protocol returns the desired listener protocol of the balancer +func (mb ManifestBalancer) Protocol(p Port) string { + return mb.Entry.Labels[fmt.Sprintf("convox.port.%d.protocol", p.Balancer)] +} + +// ListenerProtocol returns the protocol the balancer should use to listen +func (mb ManifestBalancer) ListenerProtocol(p Port) string { + switch mb.Protocol(p) { + case "tls": + return "SSL" + case "tcp": + return "TCP" + case "https": + return "HTTPS" + case "http": + return "HTTP" + } + return "TCP" +} + +// InstanceProtocol returns protocol the container is listening with +func (mb ManifestBalancer) InstanceProtocol(p Port) string { + secure := mb.Entry.Labels[fmt.Sprintf("convox.port.%d.secure", p.Balancer)] == "true" + + switch mb.Protocol(p) { + case "tcp", "tls": + if secure { + return "SSL" + } + return "TCP" + case "https", "http": + if secure { + return "HTTPS" + } + return "HTTP" + } + + return "TCP" +} + +// ProxyProtocol returns true if the container is listening for PROXY protocol +func (mb ManifestBalancer) ProxyProtocol(p Port) bool { + return mb.Entry.Labels[fmt.Sprintf("convox.port.%d.proxy", p.Balancer)] == "true" +} + func UpperName(name string) string { // myapp -> Myapp; my-app -> MyApp us := strings.ToUpper(name[0:1]) + name[1:] @@ -181,14 +226,6 @@ func (mb ManifestBalancer) Randoms() map[string]int { return mb.Entry.Randoms() } -// HealthTimeout The default health timeout when one is not specified -func (mb ManifestBalancer) HealthTimeout() string { - if timeout := mb.Entry.Labels["convox.health.timeout"]; timeout != "" { - return timeout - } - return "3" -} - // HealthPath The path to check for health. If unset, then implies TCP check func (mb ManifestBalancer) HealthPath() string { return mb.Entry.Labels["convox.health.path"] @@ -196,20 +233,48 @@ func (mb ManifestBalancer) HealthPath() string { // HealthPort The balancer port that maps to the container port specified in // manifest -func (mb ManifestBalancer) HealthPort() (string, error) { - mappings := mb.PortMappings() +func (mb ManifestBalancer) HealthPort() string { + if len(mb.Entry.Ports) == 0 { + return "" + } + if port := mb.Entry.Labels["convox.health.port"]; port != "" { - for _, mapping := range mappings { - if strconv.Itoa(mapping.Container) == port { - return strconv.Itoa(mapping.Balancer), nil + for _, p := range mb.Entry.Ports { + if strconv.Itoa(p.Container) == port { + return strconv.Itoa(p.Balancer) } } - return "", fmt.Errorf("Failed to find matching port for health port %#v", port) - } else if len(mappings) > 0 { - return strconv.Itoa(mappings[0].Balancer), nil + + // couldnt find the port they are talking about + return "" + } + + return coalesce(mb.Entry.Labels["convox.health.port"], strconv.Itoa(mb.Entry.Ports[0].Balancer)) +} + +// HealthProtocol returns the protocol to use for the health check +func (mb ManifestBalancer) HealthProtocol() string { + secure := mb.Entry.Labels[fmt.Sprintf("convox.port.%s.secure", mb.HealthPort())] == "true" + + if path := mb.Entry.Labels["convox.health.path"]; path != "" { + if secure { + return "HTTPS" + } + return "HTTP" } - return "", nil + if secure { + return "SSL" + } + return "TCP" +} + +// HealthTimeout The default health timeout when one is not specified +func (mb ManifestBalancer) HealthTimeout() string { + if timeout := mb.Entry.Labels["convox.health.timeout"]; timeout != "" { + return timeout + } + return "3" } // HealthInterval The amount of time in between health checks. diff --git a/manifest/balancer_test.go b/manifest/balancer_test.go new file mode 100644 index 0000000000..d281c25095 --- /dev/null +++ b/manifest/balancer_test.go @@ -0,0 +1,50 @@ +package manifest_test + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestBalancer(t *testing.T) { + m, err := manifestFixture("balancer") + + if assert.Nil(t, err) { + if assert.Equal(t, len(m.Balancers()), 1) { + balancer := m.Balancers()[0] + + assert.Equal(t, "TCP", balancer.HealthProtocol()) + assert.Equal(t, "80", balancer.HealthPort()) + assert.Equal(t, "", balancer.HealthPath()) + assert.Equal(t, "3", balancer.HealthTimeout()) + } + } +} + +func TestBalancerLabels(t *testing.T) { + m, err := manifestFixture("balancer-labels") + + if assert.Nil(t, err) { + if assert.Equal(t, len(m.Balancers()), 1) { + balancer := m.Balancers()[0] + + assert.Equal(t, "HTTP", balancer.HealthProtocol()) + assert.Equal(t, "443", balancer.HealthPort()) + assert.Equal(t, "/foo", balancer.HealthPath()) + assert.Equal(t, "20", balancer.HealthTimeout()) + } + } +} + +func TestBalancerSecure(t *testing.T) { + m, err := manifestFixture("balancer-secure") + + if assert.Nil(t, err) { + if assert.Equal(t, len(m.Balancers()), 1) { + balancer := m.Balancers()[0] + + assert.Equal(t, "SSL", balancer.HealthProtocol()) + assert.Equal(t, "443", balancer.HealthPort()) + } + } +} diff --git a/manifest/fixtures/balancer-labels.yml b/manifest/fixtures/balancer-labels.yml new file mode 100644 index 0000000000..0ed2d395c0 --- /dev/null +++ b/manifest/fixtures/balancer-labels.yml @@ -0,0 +1,12 @@ +version: "2" +services: + web: + build: . + labels: + - convox.health.port=5001 + - convox.health.path=/foo + - convox.health.timeout=20 + - convox.port.443.protocol=https + ports: + - 80:5000 + - 443:5001 diff --git a/manifest/fixtures/balancer-secure.yml b/manifest/fixtures/balancer-secure.yml new file mode 100644 index 0000000000..b5cc929dda --- /dev/null +++ b/manifest/fixtures/balancer-secure.yml @@ -0,0 +1,10 @@ +version: "2" +services: + web: + labels: + - convox.health.port=5001 + - convox.port.443.protocol=https + - convox.port.443.secure=true + ports: + - 80:5000 + - 443:5001 diff --git a/manifest/fixtures/balancer.yml b/manifest/fixtures/balancer.yml new file mode 100644 index 0000000000..24eea8d8ff --- /dev/null +++ b/manifest/fixtures/balancer.yml @@ -0,0 +1,9 @@ +version: "2" +services: + web: + build: . + labels: + - convox.port.443.protocol=https + ports: + - 80:5000 + - 443:5001