/// <summary>
 /// Initializes a new instance of the <see cref="EmitterContext"/> class.
 /// </summary>
 /// <param name="emitter">The emitter.</param>
 /// <param name="currentResourceType">Type of the current resource.</param>
 /// <param name="currentResourceName">Name of the current resource.</param>
 public EmitterContext(IHclEmitter emitter, string currentResourceType, string currentResourceName)
 {
     this.Emitter             = emitter;
     this.CurrentResourceName = currentResourceName;
     this.CurrentResourceType = currentResourceType;
     this.ResourceSchema      = AwsSchema.GetResourceSchema(this.CurrentResourceType);
 }
        public void AssertAttributeAsBlocksWillBeRenderedAsBlocks(string resourceType, string attributeName)
        {
            var resource  = AwsSchema.GetResourceSchema(resourceType);
            var attribute = resource.GetAttributeByPath(attributeName);

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

            var resolver = new EventQueuePreprocessor(q);

            resolver.ResolveConflicts();
        }
        public void GetResourceByNameShouldThrowForUnknownTerraformResource()
        {
            const string TerraformName   = "aws_foo_bar";
            var          expectedMessage = $"Resource \"{TerraformName}\" not found.";

            Action action = () => AwsSchema.GetResourceSchema(TerraformName);

            action.Should().Throw <KeyNotFoundException>().WithMessage(expectedMessage);
        }
        public void AssertGetResourceSchemaWithUnknownAwsTypeThrows()
        {
            const string UnknownAwsType = "AWS::EC2::FooBar";

            var expectedMessage =
                $"Resource \"{UnknownAwsType}\": No corresponding Terraform resource found. If this is incorrect, please raise an issue.";
            Action action = () => AwsSchema.GetResourceSchema(UnknownAwsType);

            action.Should().Throw <KeyNotFoundException>().WithMessage(expectedMessage);
        }
        public void InvalidPathToAttributeWithValueSchemaShouldThrow()
        {
            const string InvalidAttribute = "managed_policy_arns.max_session_duration";
            var          expectedMessage  = $"Resource does not contain an attribute at\"{InvalidAttribute}\".";

            var    resource = AwsSchema.GetResourceSchema("aws_iam_role");
            Action action   = () => resource.GetAttributeByPath(InvalidAttribute);

            action.Should().Throw <KeyNotFoundException>().WithMessage(expectedMessage);
        }
        public void GetResourceByNameShouldThrowForUnknownAwsResource()
        {
            const string AwsName         = "AWS::Foo::Bar";
            var          expectedMessage =
                $"Resource \"{AwsName}\": No corresponding Terraform resource found. If this is incorrect, please raise an issue.";

            Action action = () => AwsSchema.GetResourceSchema(AwsName);

            action.Should().Throw <KeyNotFoundException>().WithMessage(expectedMessage);
        }
示例#8
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));
        }
示例#10
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TerraformAttributeSetterContext"/> class.
 /// </summary>
 /// <param name="intrinsicInfo">The intrinsic information.</param>
 /// <param name="template">Reference to parsed CloudFormation template.</param>
 /// <param name="resource">Reference to resource being updated.</param>
 /// <param name="inputs">The list of input variables and data sources.</param>
 public TerraformAttributeSetterContext(
     IReadOnlyCollection <IntrinsicInfo> intrinsicInfo,
     ITemplate template,
     StateFileResourceDeclaration resource,
     IList <InputVariable> inputs)
 {
     this.Template       = template;
     this.IntrinsicInfos = intrinsicInfo;
     this.Resource       = resource;
     this.Inputs         = inputs;
     this.Schema         = AwsSchema.GetResourceSchema(resource.Type);
 }
        public void Test()
        {
            var stack = new Stack("test");

            var lc = new LaunchConfiguration(stack, "lc")
                     .ImageId("123")
                     .InstanceType("123");

            string json = JsonConvert.SerializeObject(lc);

            AwsSchema schema = LoadSchema();

            validateAgainstSchema(json, schema);
        }
        private void validateAgainstSchema(string json, AwsSchema schema)
        {
            JObject parsed = JObject.Parse(json);

            string type = parsed.Property("Type").Value.ToString();

            Resource resource = schema.ResourceType[type];

            Assert.True(resource != null, $"Schema does not contain resource : {type}");

            JToken properties = parsed.GetValue("Properties");

            foreach (var prop in resource.Properties)
            {
                JToken jsonProp = properties[prop.Key];

                switch (jsonProp.Type)
                {
                case JTokenType.Object:
                    // TODO : possible ref or param
                    break;

                case JTokenType.None:
                case JTokenType.Null:
                    Assert.False(prop.Value.Required, $"Property {prop.Key} is required on {type}");
                    continue;

                default:

                    break;
                }

                if (prop.Value.PrimitiveType != null)
                {
                    Assert.Equal(prop.Value.PrimitiveType, jsonProp.Type.ToString());
                }
                else if (prop.Value.ItemType != null)
                {
                    // TODO : recursive check of the type on the property
                }
                else
                {
                }
            }
        }
示例#13
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);
                }
            }
        public void AssertGetResourceSchemaWithValidAwsTypeDoesNotThrow()
        {
            Action action = () => AwsSchema.GetResourceSchema("AWS::EC2::Instance");

            action.Should().NotThrow();
        }
示例#15
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());
 }