/// <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));
        }
Exemple #2
0
        /// <summary>
        /// Determines whether argument at current path should be omitted due to its value.
        /// </summary>
        /// <param name="self"><see cref="IResourceTraits"/> derivative</param>
        /// <param name="currentPath">The current path.</param>
        /// <param name="value">The value.</param>
        /// <returns>
        ///   <c>true</c> if argument at current path should be omitted due to its value, else <c>false</c>.
        /// </returns>
        public static bool IsOmittedConditionalAttrbute(this IResourceTraits self, string currentPath, string value)
        {
            if (self == null)
            {
                throw new ArgumentNullException(nameof(self));
            }

            var conditionalAttribute = self.ConditionalAttributes.FirstOrDefault(ca => ca.Name.IsLike(currentPath));

            if (conditionalAttribute == null)
            {
                return(false);
            }

            return(value == conditionalAttribute.Value);
        }
Exemple #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ConsolidatedResourceTraits"/> class.
        /// </summary>
        /// <param name="sharedTraits">The shared traits.</param>
        /// <param name="specificResourceTraits">The specific resource traits.</param>
        public ConsolidatedResourceTraits(IResourceTraits sharedTraits, IResourceTraits specificResourceTraits)
        {
            // No conflicting arguments defined for all resources
            this.ConflictingArguments = specificResourceTraits.ConflictingArguments;

            // No default values defined for all resources
            this.DefaultValues = specificResourceTraits.DefaultValues;

            // No conditional attributes defined for all resources
            this.ConditionalAttributes = specificResourceTraits.ConditionalAttributes;

            // No attribute map defined for all resources
            this.AttributeMap = specificResourceTraits.AttributeMap;

            this.ResourceType = specificResourceTraits.ResourceType;

            this.MissingFromSchema = specificResourceTraits.MissingFromSchema;

            this.ComputedAttributes =
                sharedTraits.ComputedAttributes.Concat(specificResourceTraits.ComputedAttributes).ToList();
        }
Exemple #4
0
 /// <summary>
 /// Initializes a new instance of the <see cref="ResourceSchema"/> class.
 /// </summary>
 /// <param name="resourceType">The resource type.</param>
 /// <param name="schema">The schema.</param>
 /// <param name="traits">The traits.</param>
 public ResourceSchema(string resourceType, ProviderResourceSchema schema, IResourceTraits traits)
 {
     this.Schema       = schema;
     this.ResourceType = resourceType;
     this.Traits       = traits;
 }
Exemple #5
0
        /// <summary>
        /// Analyzes the value in this scalar based on it's key schema and any additional resource traits.
        /// </summary>
        /// <param name="key">The attribute key associated with this value.</param>
        /// <param name="resourceTraits">The resource traits.</param>
        /// <returns>Value analysis.</returns>
        /// <exception cref="System.InvalidOperationException">Invalid \"{key.Schema.Type}\" for scalar value at \"{key.Path}\"</exception>
        public AttributeContent Analyze(MappingKey key, IResourceTraits resourceTraits)
        {
            var value = this.Value;

            if (!key.Schema.Optional)
            {
                return(AttributeContent.Value);
            }

            if (resourceTraits.IsOmittedConditionalAttrbute(key.Path, value))
            {
                return(AttributeContent.Empty);
            }

            // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault
            switch (key.Schema.Type)
            {
            case SchemaValueType.TypeBool:

                if (bool.TryParse(value, out var boolValue) && boolValue)
                {
                    return(AttributeContent.Value);
                }

                break;

            case SchemaValueType.TypeInt:

                if (int.TryParse(value, out var intValue) && intValue != 0)
                {
                    return(AttributeContent.Value);
                }

                break;

            case SchemaValueType.TypeFloat:

                if (double.TryParse(value, out var doubleValue) && doubleValue != 0)
                {
                    return(AttributeContent.Value);
                }

                break;

            case SchemaValueType.TypeString:

                return(string.IsNullOrEmpty(value) ? AttributeContent.Empty : AttributeContent.Value);

            case SchemaValueType.TypeJsonData:

                // Always emit
                return(AttributeContent.Value);

            case SchemaValueType.TypeSet:
            case SchemaValueType.TypeList:
            case SchemaValueType.TypeObject:
            case SchemaValueType.TypeMap:

                // If these are empty, then they can be represented by a null scalar
                if (string.IsNullOrEmpty(value))
                {
                    return(AttributeContent.Empty);
                }

                throw new InvalidOperationException($"Unexpected scalar value for attribute of \"{key.Schema.Type}\" at \"{key.Path}\"");

            default:

                throw new InvalidOperationException($"Invalid SchemaValueType:\"{key.Schema.Type}\" for scalar value of attribute \"{key.Path}\".");
            }

            if (!string.IsNullOrEmpty(value) && char.IsLetter(value.First()) && value.Contains("."))
            {
                // A reference
                return(AttributeContent.Value);
            }

            return(AttributeContent.Empty);
        }
        /// <summary>
        /// Emits the next node.
        /// </summary>
        /// <param name="event">The event to write.</param>
        private void EmitNode(HclEvent @event)
        {
            // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
            switch (@event.Type)
            {
            case EventType.ResourceStart:

                this.EmitResourceStart(@event);
                break;

            case EventType.MappingKey:

                this.EmitMappingKey(@event);
                break;

            case EventType.ScalarValue:

                this.EmitScalarValue(@event);
                break;

            case EventType.SequenceStart:

                this.EmitSequenceStart(@event);
                break;

            case EventType.SequenceEnd:

                this.EmitSequenceEnd(@event);
                break;

            case EventType.MappingStart:

                this.EmitMappingStart(@event);
                break;

            case EventType.MappingEnd:

                this.EmitMappingEnd(@event);
                break;

            case EventType.JsonStart:

                this.EmitJsonStart(@event);
                break;

            case EventType.JsonEnd:

                this.EmitJsonEnd(@event);
                break;

            case EventType.ResourceEnd:

                this.indents.Clear();
                this.lifecycleKeys.Clear();
                this.blockKeys.Clear();
                this.column         = 0;
                this.indent         = 0;
                this.resourceTraits = AwsSchema.TraitsAll;
                this.WriteBreak();
                this.WriteBreak();
                break;
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="HclEmitter"/> class.
 /// </summary>
 /// <param name="output">The output stream.</param>
 public HclEmitter(TextWriter output)
 {
     this.output         = output;
     this.state          = EmitterState.Resource;
     this.resourceTraits = AwsSchema.TraitsAll;
 }
Exemple #8
0
        /// <summary>
        /// Gets an attribute schema given path to it.
        /// </summary>
        /// <param name="path">The path.</param>
        /// <param name="resourceTraits">Locally maintained traits that can influence the returned schema.</param>
        /// <returns>A <see cref="ValueSchema"/> for the attribute.</returns>
        /// <exception cref="System.ArgumentException">
        /// Value must be provided - path
        /// or
        /// Invalid attribute path \"{path}\" - path
        /// </exception>
        /// <exception cref="System.InvalidOperationException">
        /// Invalid path \"{path}\": Attribute at \"{GetCurrentPathFromPathStack(processedPath)}\" is not a set or a list.
        /// or
        /// Invalid path \"{path}\": Attribute at \"{GetCurrentPathFromPathStack(processedPath)}\" is not a set or a list.
        /// </exception>
        /// <exception cref="System.Collections.Generic.KeyNotFoundException">
        /// Resource does not contain an attribute \"{currentAttributeName}\".
        /// or
        /// Resource does not contain an attribute at\"{path}\".
        /// </exception>
        public ValueSchema GetAttributeByPath(string path, IResourceTraits resourceTraits)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentException("Value must be provided", nameof(path));
            }

            if (IsListIndexIndicator(path.First().ToString()) || IsListIndexIndicator(path.Last().ToString(), true))
            {
                throw new ArgumentException($"Invalid attribute path \"{path}\"", nameof(path));
            }

            if (path == "id")
            {
                // 'id' is not stored in the schema because _everything_ has it
                return(IdentitySchema);
            }

            if (resourceTraits.MissingFromSchema.Contains(path))
            {
                return(MissingFromSchemaValueSchema);
            }

            ValueSchema currentAttribute = null;
            var         currentResource  = this;
            var         pathComponents   = new Queue <string>(AttributePath.Split(path));
            var         processedPath    = new Stack <string>();

            while (true)
            {
                var currentAttributeName = pathComponents.Dequeue();

                if (IsListIndexIndicator(currentAttributeName))
                {
                    processedPath.Push(currentAttributeName);
                    continue;
                }

                var previousAttribute = currentAttribute;

                if (previousAttribute != null && previousAttribute.Type != SchemaValueType.TypeObject)
                {
                    // To get here, the previous attribute must be a set or list
                    if (!IsListIndexIndicator(processedPath.FirstOrDefault()))
                    {
                        throw new InvalidOperationException(
                                  $"Invalid path \"{path}\": Attribute at \"{GetCurrentPathFromPathStack()}\" is a set or a list. List indicator ('*', '#' or integer) was expected next in path.");
                    }
                }

                if (currentAttributeName == "timeouts")
                {
                    currentAttribute = TimeoutsSchema;
                }
                else
                {
                    if (!currentResource.Attributes.ContainsKey(currentAttributeName))
                    {
                        throw CreateKeyNotFoundException();
                    }

                    currentAttribute = currentResource.Attributes[currentAttributeName];
                }

                processedPath.Push(currentAttributeName);

                if (pathComponents.Count == 0)
                {
                    return(currentAttribute);
                }

                switch (currentAttribute.Elem)
                {
                case ProviderResourceSchema resourceSchema:

                    currentResource = resourceSchema;
                    break;

                case ValueSchema valueSchema
                    when pathComponents.Count == 1 && currentAttribute.Type == SchemaValueType.TypeMap:

                    return(valueSchema);

                default:

                    // If Elem is null or contains a value schema, then there are no further path components
                    // below this attribute.
                    throw CreateKeyNotFoundException();
                }
            }

            KeyNotFoundException CreateKeyNotFoundException()
            {
                return(new KeyNotFoundException($"Resource does not contain an attribute at\"{path}\"."));
            }

            string GetCurrentPathFromPathStack()
            {
                return(string.Join(".", processedPath.Reverse().ToList()));
            }
        }
Exemple #9
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());
 }