public void ShouldResolveASGConflicts()
        {
            var q      = new EventQueue(EventQueues.AutoScalingGroupEvents);
            var traits = AwsSchema.GetResourceTraits("aws_autoscaling_group");

            var resolver = new EventQueuePreprocessor(q);

            resolver.ResolveConflicts();
        }
Beispiel #2
0
        /// <summary>
        /// Renders the specified GetAtt intrinsic.
        /// </summary>
        /// <param name="getAttIntrinsic">The GetAtt intrinsic.</param>
        /// <param name="template">The template.</param>
        /// <param name="resource">The resource.</param>
        /// <returns>An <see cref="IndirectReference"/> to an attribute on another resource.</returns>
        private static Reference Render(GetAttIntrinsic getAttIntrinsic, ITemplate template, ResourceMapping resource)
        {
            string attributeName;

            if (getAttIntrinsic.AttributeName is IIntrinsic)
            {
                if (!(getAttIntrinsic.AttributeName is RefIntrinsic refIntrinsic))
                {
                    // Only !Ref allowed here
                    return(null);
                }

                attributeName = refIntrinsic.Evaluate(template).ToString();
            }
            else
            {
                attributeName = getAttIntrinsic.AttributeName.ToString();
            }

            // This GetAtt refers to a nested stack which may or may not have been imported as a terraform module.
            if (attributeName.StartsWith(TerraformExporterConstants.StackOutputQualifier))
            {
                var referencedOutput =
                    attributeName.Substring(TerraformExporterConstants.StackOutputQualifier.Length);

                if (resource.Module?.LogicalId == getAttIntrinsic.LogicalId && resource.Module.Outputs.Any(o => o.OutputKey == referencedOutput))
                {
                    // This reference is to a module output
                    return(new ModuleReference($"{resource.Module.Name}.{referencedOutput}"));
                }

                // The reference is to an aws_cloudformation_stack as the use did not elect to import nested stacks.
                // Just lowercase "Outputs." which will then resolve to the terraform resource.
                attributeName = attributeName.Replace(
                    TerraformExporterConstants.StackOutputQualifier,
                    TerraformExporterConstants.StackOutputQualifier.ToLowerInvariant());
            }
            else
            {
                var traits = AwsSchema.GetResourceTraits(resource.TerraformType);

                attributeName = traits.AttributeMap.ContainsKey(attributeName)
                                    ? traits.AttributeMap[attributeName]
                                    : attributeName.CamelCaseToSnakeCase();
            }

            if (getAttIntrinsic.ExtraData is IntrinsicInfo intrinsicInfo)
            {
                resource = intrinsicInfo.TargetResource;
            }

            return(template.Resources.Any(r => r.Name == resource.LogicalId)
                       ? new IndirectReference($"{resource.Address}.{attributeName}")
                       : null);
        }
        /// <summary>
        /// Emits the resource start.
        /// </summary>
        /// <param name="event">A <see cref="ResourceStart"/> event.</param>
        private void EmitResourceStart(HclEvent @event)
        {
            var rs = GetTypedEvent <ResourceStart>(@event);

            this.Write("resource");
            this.isWhitespace        = false;
            this.resourceTraits      = AwsSchema.GetResourceTraits(rs.ResourceType);
            this.currentResourceName = rs.ResourceName;
            this.currentResourceType = rs.ResourceType;
            this.EmitScalar(new Scalar(rs.ResourceType, true));
            this.EmitScalar(new Scalar(rs.ResourceName, true));
        }
Beispiel #4
0
            /// <summary>
            /// Creates an <see cref="IntrinsicInfo"/> for a <c>!GetAtt</c> intrinsic.
            /// </summary>
            /// <param name="getAttIntrinsic">The <c>!GetAtt</c> intrinsic.</param>
            /// <param name="currentPath">The current path.</param>
            /// <returns>An <see cref="IntrinsicInfo"/></returns>
            private IntrinsicInfo ProcessGetAtt(GetAttIntrinsic getAttIntrinsic, PropertyPath currentPath)
            {
                object evaluation;

                // Logical name of the resource being referenced by this !GetAtt
                var(referencedResourceName, attribute) =
                    (Tuple <string, string>)getAttIntrinsic.Evaluate(this.template);

                // Is the reference to a nested stack module?
                var referencedModule =
                    this.module.NestedModules.FirstOrDefault(m => m.LogicalId == referencedResourceName);

                if (referencedModule != null)
                {
                    var targetModuleSummary = new ResourceMapping
                    {
                        AwsType    = TerraformExporterConstants.AwsCloudFormationStack,
                        LogicalId  = referencedModule.LogicalId,
                        PhysicalId = referencedModule.Name,
                        Module     = referencedModule
                    };

                    var parts = attribute.Split('.');
                    evaluation = referencedModule.Outputs.Where(o => o.OutputKey == parts[1])
                                 .Select(o => o.OutputValue).SingleOrDefault();

                    return(new IntrinsicInfo(currentPath, getAttIntrinsic, targetModuleSummary, evaluation));
                }

                // State file instance of the resource being referenced by this !GetAtt
                var referencedResource = this.TerraformResources.FirstOrDefault(r => r.Name == referencedResourceName)
                                         ?.Instances.First();

                if (referencedResource == null)
                {
                    // If not found, then reference is to a resource that couldn't be imported eg. a custom resource.
                    throw new UnsupportedResourceWarning(
                              getAttIntrinsic,
                              this.currentCloudFormationResource,
                              currentPath);
                }

                // CloudFormation instance of the resource being referenced by this !GetAtt
                var cloudFormationResource =
                    this.CloudFormationResources.First(r => r.LogicalResourceId == getAttIntrinsic.LogicalId);

                // Summary of the resource to which this !GetAtt refers to
                var targetResourceSummary = new ResourceMapping
                {
                    AwsType       = cloudFormationResource.ResourceType,
                    LogicalId     = cloudFormationResource.LogicalResourceId,
                    PhysicalId    = cloudFormationResource.PhysicalResourceId,
                    TerraformType = this.TerraformResources.First(
                        tr => tr.Name == cloudFormationResource.LogicalResourceId).Type
                };

                // Now attempt to match up the CloudFormation resource attribute name with the corresponding terraform one
                // and get the current value from state.
                // First, look up the attribute map
                var traits = AwsSchema.GetResourceTraits(referencedResource.Parent.Type);

                if (traits.AttributeMap.ContainsKey(attribute))
                {
                    var token = referencedResource.Attributes[traits.AttributeMap[attribute]];
                    evaluation = GetEvaluation(token);
                }
                else if (attribute.StartsWith(TerraformExporterConstants.StackOutputQualifier))
                {
                    // Nested stack output reference
                    var token = referencedResource.Attributes.SelectToken(
                        attribute.Replace(
                            TerraformExporterConstants.StackOutputQualifier,
                            TerraformExporterConstants.StackOutputQualifier.ToLowerInvariant()));
                    evaluation = GetEvaluation(token);
                }
                else
                {
                    var result = getAttIntrinsic.GetTargetValue(this.template, referencedResource);

                    if (result.Success)
                    {
                        evaluation = result.Value;
                    }
                    else
                    {
                        throw new UnreferenceableIntrinsicWarning(
                                  getAttIntrinsic,
                                  cloudFormationResource.TemplateResource,
                                  currentPath);
                    }
                }

                return(new IntrinsicInfo(currentPath, getAttIntrinsic, targetResourceSummary, evaluation));

                object GetEvaluation(JToken token)
                {
                    if (token is JValue jv)
                    {
                        // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
                        switch (jv.Type)
                        {
                        case JTokenType.String:

                            evaluation = jv.Value <string>();
                            break;

                        case JTokenType.Integer:
                        case JTokenType.Float:

                            evaluation = jv.Value <double>();
                            break;

                        case JTokenType.Boolean:

                            evaluation = jv.Value <bool>();
                            break;

                        default:

                            throw new InvalidOperationException(
                                      $"Unexpected JValue type: {jv.Type} while processing {getAttIntrinsic}");
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException(
                                  $"Unexpected JToken type: {token.Type} while processing {getAttIntrinsic}");
                    }

                    return(evaluation);
                }
            }
Beispiel #5
0
 /// <summary>
 /// Initializes a new instance of the <see cref="EventQueuePreprocessor"/> class.
 /// </summary>
 /// <param name="queue">The event queue.</param>
 public EventQueuePreprocessor(EventQueue queue)
 {
     this.queue  = queue;
     this.traits = AwsSchema.GetResourceTraits(this.GetResourceType());
 }