func (e *IAMRole) Find(c *fi.Context) (*IAMRole, error) { cloud := c.Cloud.(*awsup.AWSCloud) request := &iam.GetRoleInput{RoleName: e.Name} response, err := cloud.IAM.GetRole(request) if awsErr, ok := err.(awserr.Error); ok { if awsErr.Code() == "NoSuchEntity" { return nil, nil } } if err != nil { return nil, fmt.Errorf("error getting role: %v", err) } r := response.Role actual := &IAMRole{} actual.ID = r.RoleId actual.Name = r.RoleName if r.AssumeRolePolicyDocument != nil { // The AssumeRolePolicyDocument is URI encoded (?) actualPolicy := *r.AssumeRolePolicyDocument actualPolicy, err = url.QueryUnescape(actualPolicy) if err != nil { return nil, fmt.Errorf("error parsing AssumeRolePolicyDocument for IAMRole %q: %v", e.Name, err) } // The RolePolicyDocument is reformatted by AWS // We parse both as JSON; if the json forms are equal we pretend the actual value is the expected value if e.RolePolicyDocument != nil { expectedPolicy, err := e.RolePolicyDocument.AsString() if err != nil { return nil, fmt.Errorf("error reading expected RolePolicyDocument for IAMRole %q: %v", e.Name, err) } expectedJson := make(map[string]interface{}) err = json.Unmarshal([]byte(expectedPolicy), &expectedJson) if err != nil { return nil, fmt.Errorf("error parsing expected RolePolicyDocument for IAMRole %q: %v", e.Name, err) } actualJson := make(map[string]interface{}) err = json.Unmarshal([]byte(actualPolicy), &actualJson) if err != nil { return nil, fmt.Errorf("error parsing actual RolePolicyDocument for IAMRole %q: %v", e.Name, err) } if reflect.DeepEqual(actualJson, expectedJson) { glog.V(2).Infof("actual RolePolicyDocument was json-equal to expected; returning expected value") actualPolicy = expectedPolicy } } actual.RolePolicyDocument = fi.WrapResource(fi.NewStringResource(actualPolicy)) } glog.V(2).Infof("found matching IAMRole %q", *actual.ID) e.ID = actual.ID return actual, nil }
func (e *IAMRolePolicy) Find(c *fi.Context) (*IAMRolePolicy, error) { cloud := c.Cloud.(*awsup.AWSCloud) request := &iam.GetRolePolicyInput{ RoleName: e.Role.Name, PolicyName: e.Name, } response, err := cloud.IAM.GetRolePolicy(request) if awsErr, ok := err.(awserr.Error); ok { if awsErr.Code() == "NoSuchEntity" { return nil, nil } } if err != nil { return nil, fmt.Errorf("error getting role: %v", err) } p := response actual := &IAMRolePolicy{} actual.Role = &IAMRole{Name: p.RoleName} if aws.StringValue(e.Role.Name) == aws.StringValue(p.RoleName) { actual.Role.ID = e.Role.ID } if p.PolicyDocument != nil { // The PolicyDocument is URI encoded (?) policy := *p.PolicyDocument policy, err = url.QueryUnescape(policy) if err != nil { return nil, fmt.Errorf("error parsing PolicyDocument for IAMRolePolicy %q: %v", e.Name, err) } actual.PolicyDocument = fi.WrapResource(fi.NewStringResource(policy)) } actual.Name = p.PolicyName e.ID = actual.ID return actual, nil }
func (e *LaunchConfiguration) Find(c *fi.Context) (*LaunchConfiguration, error) { cloud := c.Cloud.(*awsup.AWSCloud) request := &autoscaling.DescribeLaunchConfigurationsInput{} prefix := *e.Name + "-" configurations := map[string]*autoscaling.LaunchConfiguration{} err := cloud.Autoscaling.DescribeLaunchConfigurationsPages(request, func(page *autoscaling.DescribeLaunchConfigurationsOutput, lastPage bool) bool { for _, l := range page.LaunchConfigurations { name := aws.StringValue(l.LaunchConfigurationName) if strings.HasPrefix(name, prefix) { suffix := name[len(prefix):] configurations[suffix] = l } } return true }) if len(configurations) == 0 { return nil, nil } var newest *autoscaling.LaunchConfiguration var newestTime int64 for _, lc := range configurations { t := lc.CreatedTime.UnixNano() if t > newestTime { newestTime = t newest = lc } } lc := newest glog.V(2).Infof("found existing AutoscalingLaunchConfiguration: %q", *lc.LaunchConfigurationName) actual := &LaunchConfiguration{ Name: e.Name, ID: lc.LaunchConfigurationName, ImageID: lc.ImageId, InstanceType: lc.InstanceType, SSHKey: &SSHKey{Name: lc.KeyName}, AssociatePublicIP: lc.AssociatePublicIpAddress, IAMInstanceProfile: &IAMInstanceProfile{Name: lc.IamInstanceProfile}, } securityGroups := []*SecurityGroup{} for _, sgID := range lc.SecurityGroups { securityGroups = append(securityGroups, &SecurityGroup{ID: sgID}) } actual.SecurityGroups = securityGroups actual.BlockDeviceMappings = make(map[string]*BlockDeviceMapping) for _, b := range lc.BlockDeviceMappings { deviceName, bdm := BlockDeviceMappingFromAutoscaling(b) actual.BlockDeviceMappings[deviceName] = bdm } userData, err := base64.StdEncoding.DecodeString(*lc.UserData) if err != nil { return nil, fmt.Errorf("error decoding UserData: %v", err) } actual.UserData = fi.WrapResource(fi.NewStringResource(string(userData))) // Avoid spurious changes on ImageId if e.ImageID != nil && actual.ImageID != nil && *actual.ImageID != *e.ImageID { image, err := cloud.ResolveImage(*e.ImageID) if err != nil { glog.Warningf("unable to resolve image: %q: %v", *e.ImageID, err) } else if image == nil { glog.Warningf("unable to resolve image: %q: not found", *e.ImageID) } else if aws.StringValue(image.ImageId) == *actual.ImageID { glog.V(4).Infof("Returning matching ImageId as expected name: %q -> %q", *actual.ImageID, *e.ImageID) actual.ImageID = e.ImageID } } if e.ID == nil { e.ID = actual.ID } return actual, nil }