Skip to content
This repository has been archived by the owner on Oct 21, 2023. It is now read-only.

VaporShell v3.0.0.20200618-alpha

Pre-release
Pre-release
Compare
Choose a tag to compare
@scrthq scrthq released this 18 Jun 18:00
4d6f29e

THIS IS A PRERELEASE

Changelog

3.0.0.20200618-alpha

Breaking Changes

  • All non-core functions have been broken out into service-specific modules, e.g. VaporShell.S3 or VaporShell.SAM.
  • All of VaporShell is now fully supported by PowerShell classes, so objects output by the functions will be different. If you are making changes to objects by updating properties on a variable, you may want to review your scripts and test with 3.0.0 to confirm that there are not changes needed to the script logic.
  • Add-CreationPolicy's parameters have been reduced to AutoScalingCreationPolicy and ResourceSignal with specific types expected.
  • Deprecated VaporShell.DSL nested module in favor of classes due to the overall benefits of classes, e.g. intellisense in editors, not using a hacky way to execute the scriptblock as a hashtable, etc.
  • Primary Class constructors and the core Add*() methods on the VSTemplate object accept a single parameter value. If you are passing multiple items to one of these methods, you'll need to wrap all of the items in parentheses to treat them as a single array of items instead, e.g...
$template = Initialize-Vaporshell

$template.AddCondition(
    (New-VaporCondition -LogicalId "CreateProdResources" -Condition (Add-ConEquals -FirstValue (Add-FnRef -Ref "EnvTypeString") -SecondValue "prod")),
    (Add-Include -Location "s3://MyAmazonS3BucketName/single_wait_condition.yaml")
)

# ERROR >> MethodException: Cannot find an overload for "AddCondition" and the argument count: "2".

$template.AddCondition(( # << note the extra (
    (New-VaporCondition -LogicalId "CreateProdResources" -Condition (Add-ConEquals -FirstValue (Add-FnRef -Ref "EnvTypeString") -SecondValue "prod")),
    (Add-Include -Location "s3://MyAmazonS3BucketName/single_wait_condition.yaml")
)) # << note the extra )

# Works!

New Features

  • Since all of VaporShell is now fully supported by PowerShell classes, you can work entirely with classes instead of functions by importing the service module(s) you will be using. Classes and functions will all be loaded into the session on module import, no need to include a using statement.
  • All Intrinsic and Condition functions have new aliases mimicking the YML shorthand syntax, e.g. !Ref is aliased to Add-FnRef, !Join is aliased to Add-FnJoin, !And is aliased to Add-ConAnd, etc.
    • Some additional convenience shorthand aliases have been included as well:
      • !Condition = Add-ConRef (new function when needing to Ref a Condition -- alt: [ConRef]'ConditionLogicalId')
      • !Include = Add-Include (usage: !Include 's3://mybucket/my-external-template.yml' -- alt: [Include]'s3://mybucket/my-external-template.yml')

Instructions

  • Each module is packaged in it's own ZIP.
  • There is one mega-zip containing all modules for ease of use named FULL_VaporShell.zip. If you are testing, I would recommend grabbing this one to prevent version diff oddities.
  1. Click here to download the FULL_VaporShell.zip file attached to the release.
  2. If on Windows: Right-click the downloaded zip, select Properties, then unblock the file.

    This is to prevent having to unblock each file individually after unzipping.

  3. Unzip the archive.
  4. (Optional) Place the contents somewhere in your PSModulePath.

    You can view the paths listed by running the environment variable $env:PSModulePath

  5. Import the module, using the full path to the PSD1 file in place of VaporShell if the unzipped module folder is not in your PSModulePath:
    # In $env:PSModulePath
    Import-Module VaporShell
    
    # Otherwise, provide the path to the manifest:
    Import-Module -Path C:\MyPSModules\VaporShell\3.0.0.20200618\VaporShell.psd1

Usage

Example using 100% classes:

Import-Module VaporShell,
            VaporShell.AutoScaling,
            VaporShell.EC2,
            VaporShell.ElasticLoadBalancing

[VSTemplate]@{
    Parameters = @(
        [VSParameter]@{
            LogicalId = 'MinSize'
            Type = 'Number'
        }
        [VSParameter]@{
            LogicalId = 'MaxSize'
            Type = 'Number'
        }
        [VSParameter]@{
            LogicalId = 'DesiredSize'
            Type = 'Number'
        }
        [VSParameter]@{
            LogicalId = 'ImageId'
            Type = 'AWS::EC2::Image::Id'
        }
        [VSParameter]@{
            LogicalId = 'InstanceType'
            Type = 'String'
        }
        [VSParameter]@{
            LogicalId = 'KeyName'
            Type = 'String'
        }
        [VSParameter]@{
            LogicalId = 'SSLCertificateArn'
            Type = 'String'
        }
        [VSParameter]@{
            LogicalId = 'PrivateSubnets'
            Type = 'List<AWS::EC2::Subnet::Id>'
        }
        [VSParameter]@{
            LogicalId = 'PublicSubnets'
            Type = 'List<AWS::EC2::Subnet::Id>'
        }
        [VSParameter]@{
            LogicalId = 'ASGSecurityGroups'
            Type = 'List<AWS::EC2::SecurityGroup::Id>'
        }
        [VSParameter]@{
            LogicalId = 'BastionSecurityGroups'
            Type = 'List<AWS::EC2::SecurityGroup::Id>'
        }
        [VSParameter]@{
            LogicalId = 'LoadBalancerSecurityGroups'
            Type = 'List<AWS::EC2::SecurityGroup::Id>'
        }
    )
    Conditions = @(
        [VSCondition]@{
            LogicalId = 'HasSSL'
            Condition = [ConNot]::new([ConEquals]::new(([FnRef]'SSLCertificateArn','')))
        }
        [VSCondition]@{
            LogicalId = 'HasSSHKey'
            Condition = [ConNot]::new([ConEquals]::new([FnRef]'KeyName',''))
        }
    )
    Resources = @(
        [ElasticLoadBalancingLoadBalancer]@{
            LogicalId = 'LoadBalancer'
            Subnets = [FnRef]'PublicSubnets'
            SecurityGroups = [FnRef]'LoadBalancerSecurityGroups'
            Listeners = @(
                [ElasticLoadBalancingLoadBalancerListeners]@{
                    LoadBalancerPort = '80'
                    InstancePort = '80'
                    Protocol = 'HTTP'
                }
                [ConIf]::new(
                    'HasSSL',
                    [ElasticLoadBalancingLoadBalancerListeners]@{
                        LoadBalancerPort = '443'
                        InstancePort = '443'
                        Protocol = 'HTTPS'
                        SSLCertificateId = [FnRef]'SSLCertificateArn'
                    },
                    [FnRef]::NoValue
                )
            )
            HealthCheck = [ElasticLoadBalancingLoadBalancerHealthCheck]@{
                Target = 'HTTP:80/'
                HealthyThreshold = '3'
                UnhealthyThreshold = '5'
                Interval = '30'
                Timeout = '5'
            }
        }
        [AutoScalingLaunchConfiguration]@{
            LogicalId = 'WebServerLaunchConfig'
            KeyName = [ConIf]::new(
                'HasSSHKey',
                [FnRef]'KeyName',
                [FnRef]::NoValue
            )
            ImageId = [FnRef]'ImageId'
            UserData = './Tests/Assets/UserData.sh'
            SecurityGroups = [FnRef]'ASGSecurityGroups'
            InstanceType = [FnRef]'InstanceType'
        }
        [AutoScalingAutoScalingGroup]@{
            LogicalId = 'WebServerGroup'
            UpdatePolicy = [UpdatePolicy]@{
                AutoScalingRollingUpdate = [AutoScalingRollingUpdate]@{
                    MinInstancesInService = 1
                    PauseTime = 'PT1M'
                }
            }
            LaunchConfigurationName = [FnRef]'WebServerLaunchConfig'
            MinSize = [FnRef]'MinSize'
            MaxSize = [FnRef]'MaxSize'
            DesiredCapacity = [FnRef]'DesiredSize'
            LoadBalancerNames = @([FnRef]'LoadBalancer')
            VPCZoneIdentifier = [FnRef]'PrivateSubnets'
        }
        [EC2Instance]@{
            LogicalId = 'Bastion'
            Condition = 'HasSSHKey'
            ImageId = [FnRef]'ImageId'
            InstanceType = 't2.micro'
            NetworkInterfaces = @(
                [EC2InstanceNetworkInterface]@{
                    AssociatePublicIpAddress = $true
                    DeviceIndex = '0'
                    GroupSet = [FnRef]'BastionSecurityGroups'
                    SubnetId = [FnSelect]::new(0, [FnRef]'PublicSubnets')
                }
            )
        }
    )
    Outputs = @(
        [VSOutput]@{
            LogicalId = 'ELB'
            Description = 'LoadBalancer DNS Name'
            Value = [FnGetAtt]::new('LoadBalancer','DNSName')
            Export = [Export]'elb-dns-name'
        }
        [VSOutput]@{
            LogicalId = 'Bastion'
            Description = 'Bastion instance IP'
            Value = [FnGetAtt]::new('Bastion','PublicIp')
            Condition = [ConRef]'HasSSHKey'
        }
    )
}