func GetEnvironment(app string) (Environment, error) { a, err := GetApp(app) if err != nil { return nil, err } data, err := s3Get(a.Outputs["Settings"], "env") if err != nil { // if we get a 404 from aws just return an empty environment if awsError, ok := err.(awserr.RequestFailure); ok && awsError.StatusCode() == 404 { return Environment{}, nil } return nil, err } if a.Parameters["Key"] != "" { cr := crypt.New(os.Getenv("AWS_REGION"), os.Getenv("AWS_ACCESS"), os.Getenv("AWS_SECRET")) if d, err := cr.Decrypt(a.Parameters["Key"], data); err == nil { data = d } } return LoadEnvironment(data), nil }
func (r *Release) Save() error { if r.Id == "" { return fmt.Errorf("Id must not be blank") } if r.Created.IsZero() { r.Created = time.Now() } req := &dynamodb.PutItemInput{ Item: &map[string]*dynamodb.AttributeValue{ "id": &dynamodb.AttributeValue{S: aws.String(r.Id)}, "app": &dynamodb.AttributeValue{S: aws.String(r.App)}, "created": &dynamodb.AttributeValue{S: aws.String(r.Created.Format(SortableTime))}, }, TableName: aws.String(releasesTable(r.App)), } if r.Build != "" { (*req.Item)["build"] = &dynamodb.AttributeValue{S: aws.String(r.Build)} } if r.Env != "" { (*req.Item)["env"] = &dynamodb.AttributeValue{S: aws.String(r.Env)} } if r.Manifest != "" { (*req.Item)["manifest"] = &dynamodb.AttributeValue{S: aws.String(r.Manifest)} } _, err := DynamoDB().PutItem(req) if err != nil { return err } app, err := GetApp(r.App) if err != nil { return err } env := []byte(r.Env) if app.Parameters["Key"] != "" { cr := crypt.New(os.Getenv("AWS_REGION"), os.Getenv("AWS_ACCESS"), os.Getenv("AWS_SECRET")) env, err = cr.Encrypt(app.Parameters["Key"], []byte(env)) if err != nil { return err } } return s3Put(app.Outputs["Settings"], fmt.Sprintf("releases/%s/env", r.Id), env, true) }
func ECSTaskDefinitionCreate(req Request) (string, map[string]string, error) { // return "", fmt.Errorf("fail") tasks := req.ResourceProperties["Tasks"].([]interface{}) r := &ecs.RegisterTaskDefinitionInput{ Family: aws.String(req.ResourceProperties["Name"].(string)), } // download environment var env models.Environment if envUrl, ok := req.ResourceProperties["Environment"].(string); ok && envUrl != "" { res, err := http.Get(envUrl) if err != nil { return "", nil, err } defer res.Body.Close() data, err := ioutil.ReadAll(res.Body) if key, ok := req.ResourceProperties["Key"].(string); ok && key != "" { cr := crypt.New(Region(&req), os.Getenv("AWS_ACCESS_KEY_ID"), os.Getenv("AWS_SECRET_ACCESS_KEY")) cr.AwsToken = os.Getenv("AWS_SESSION_TOKEN") dec, err := cr.Decrypt(key, data) if err != nil { return "", nil, err } data = dec } env = models.LoadEnvironment(data) } r.ContainerDefinitions = make([]*ecs.ContainerDefinition, len(tasks)) for i, itask := range tasks { task := itask.(map[string]interface{}) cpu, _ := strconv.Atoi(task["CPU"].(string)) memory, _ := strconv.Atoi(task["Memory"].(string)) r.ContainerDefinitions[i] = &ecs.ContainerDefinition{ Name: aws.String(task["Name"].(string)), Essential: aws.Boolean(true), Image: aws.String(task["Image"].(string)), CPU: aws.Long(int64(cpu)), Memory: aws.Long(int64(memory)), } if command, ok := task["Command"].(string); ok && command != "" { r.ContainerDefinitions[i].Command = []*string{aws.String("sh"), aws.String("-c"), aws.String(command)} } // set environment for key, val := range env { r.ContainerDefinitions[i].Environment = append(r.ContainerDefinitions[i].Environment, &ecs.KeyValuePair{ Name: aws.String(key), Value: aws.String(val), }) } // set task environment overrides if oenv, ok := task["Environment"].(map[string]interface{}); ok { for key, val := range oenv { r.ContainerDefinitions[i].Environment = append(r.ContainerDefinitions[i].Environment, &ecs.KeyValuePair{ Name: aws.String(key), Value: aws.String(val.(string)), }) } } // put release in environment if release, ok := req.ResourceProperties["Release"].(string); ok { r.ContainerDefinitions[i].Environment = append(r.ContainerDefinitions[i].Environment, &ecs.KeyValuePair{ Name: aws.String("RELEASE"), Value: aws.String(release), }) } // link to Service Stacks via environment if task["Services"] != nil { services := task["Services"].([]interface{}) for _, service := range services { parts := strings.Split(service.(string), ":") res, err := CloudFormation(req).DescribeStacks(&cloudformation.DescribeStacksInput{StackName: aws.String(parts[0])}) if err != nil { return "", nil, fmt.Errorf("SERVICE CREATION: %s", err) } s := models.ServiceFromStack(res.Stacks[0]) // convert Port5432TcpAddr to POSTGRES_PORT_5432_TCP_ADDR re := regexp.MustCompile("([a-z])([A-Z0-9])") // lower case letter followed by upper case or number, i.e. Port5432 re2 := regexp.MustCompile("([0-9])([A-Z])") // number followed by upper case letter, i.e. 5432Tcp for k, v := range s.Outputs { u := re.ReplaceAllString(k, "${1}_${2}") u = re2.ReplaceAllString(u, "${1}_${2}") u = parts[1] + "_" + u u = strings.ToUpper(u) r.ContainerDefinitions[i].Environment = append(r.ContainerDefinitions[i].Environment, &ecs.KeyValuePair{ Name: aws.String(u), Value: aws.String(v), }) } } } // set links if links, ok := task["Links"].([]interface{}); ok { r.ContainerDefinitions[i].Links = make([]*string, len(links)) for j, link := range links { r.ContainerDefinitions[i].Links[j] = aws.String(link.(string)) } } // set portmappings if ports, ok := task["PortMappings"].([]interface{}); ok { r.ContainerDefinitions[i].PortMappings = make([]*ecs.PortMapping, len(ports)) for j, port := range ports { parts := strings.Split(port.(string), ":") host, _ := strconv.Atoi(parts[0]) container, _ := strconv.Atoi(parts[1]) r.ContainerDefinitions[i].PortMappings[j] = &ecs.PortMapping{ ContainerPort: aws.Long(int64(container)), HostPort: aws.Long(int64(host)), } } } // set volumes if volumes, ok := task["Volumes"].([]interface{}); ok { for j, volume := range volumes { name := fmt.Sprintf("%s-%d-%d", task["Name"].(string), i, j) parts := strings.Split(volume.(string), ":") r.Volumes = append(r.Volumes, &ecs.Volume{ Name: aws.String(name), Host: &ecs.HostVolumeProperties{ SourcePath: aws.String(parts[0]), }, }) r.ContainerDefinitions[i].MountPoints = append(r.ContainerDefinitions[i].MountPoints, &ecs.MountPoint{ SourceVolume: aws.String(name), ContainerPath: aws.String(parts[1]), ReadOnly: aws.Boolean(false), }) } } } res, err := ECS(req).RegisterTaskDefinition(r) if err != nil { return "", nil, err } return *res.TaskDefinition.TaskDefinitionARN, nil, nil }
func PutEnvironment(app string, env Environment) error { a, err := GetApp(app) if err != nil { return err } release, err := a.ForkRelease() if err != nil { return err } release.Env = env.Raw() err = release.Save() if err != nil { return err } // eold := strings.Split(release.Env, "\n") // enew := strings.Split(env.Raw(), "\n") // diff := difflib.Diff(eold, enew) // metadata, err := diffMetadata(diff) // if err != nil { // return err // } // change := &Change{ // App: app, // Created: time.Now(), // Metadata: metadata, // TargetId: release.Id, // Type: "RELEASE", // Status: "complete", // User: "******", // } // err = change.Save() // if err != nil { // fmt.Fprintf(os.Stderr, "error: %s\n", err) // } e := []byte(env.Raw()) if a.Parameters["Key"] != "" { cr := crypt.New(os.Getenv("AWS_REGION"), os.Getenv("AWS_ACCESS"), os.Getenv("AWS_SECRET")) e, err = cr.Encrypt(a.Parameters["Key"], e) if err != nil { return err } } return s3Put(a.Outputs["Settings"], "env", []byte(e), true) }