Functions/New-CmEC2Instance.ps1
Function New-CmEC2Instance { <# .Synopsis Creates a Windows EC2 On demand or spot Instance with minimal input. .DESCRIPTION Creates a Windows EC2 On demand or spot Instance and, if a Name and DomainName are specified, creates or updates the Route 53 DNS entry for the instance and applies a Name Tag. .NOTES Name: New-CMEC2Instance Author: Chad Miles DateUpdated: 2017-05-02 Version: 1.2.0 .EXAMPLE C:\> New-CMEC2Instance -InstanceType t2.micro -Region us-east-1 -DomainName mydomain.com -Name MyInstance InstanceID : i-1234567890abcdef Region : us-east-1 Name : MyInstance Hostname : MyInstance.Mydomain.com InstanceType : t2-micro BidPrice : OnDemandPrice : 0.017 Savings : 0 % ImageName : WINDOWS_2016_BASE ImageID : ami-58a1a73e KeyName : MyKeyPair .EXAMPLE C:\> New-CMEC2Instance -InstanceType t2.micro -Region us-east-1 -Name MyInstance InstanceID : i-1234567890abcdef Region : us-east-1 Name : MyInstance Hostname : ec2-34-248-2-178.eu-west-1.compute.amazonaws.com InstanceType : t2-micro BidPrice : OnDemandPrice : 0.017 Savings : 0 % ImageName : WINDOWS_2016_BASE ImageID : ami-58a1a73e KeyName : MyKeyPair .EXAMPLE C:\> New-CMEC2Instance -InstanceType t2.micro -Region us-east-1 -Name MyInstance -DomainName mydomain.com -OSVerion 2012R2 InstanceID : i-1234567890abcdef Region : us-east-1 Name : MyInstance Hostname : MyInstance.Mydomain.com InstanceType : t2-micro BidPrice : OnDemandPrice : 0.017 Savings : 0 % ImageName : WINDOWS_2012R2_BASE ImageID : ami-40003a26 KeyName : MyKeyPair .EXAMPLE C:\> New-CMEC2Instance -InstanceType t2.micro -Region us-east-1 -Name MyInstance -DomainName mydomain.com -SpotRequest WARNING: Spot Instances not available for T1 and T2 instance types, switching to on demand. InstanceID : i-1234567890abcdef Region : us-east-1 Name : MyInstance Hostname : MyInstance.Mydomain.com InstanceType : t2-micro BidPrice : OnDemandPrice : 0.017 Savings : 0 % ImageName : WINDOWS_2016_BASE ImageID : ami-40003a26 KeyName : MyKeyPair .EXAMPLE C:\> New-CMEC2Instance -InstanceType m3.medium -Region us-east-1 -Name MySpotInstance -DomainName mydomain.com -SpotRequest InstanceID : i-1234567890abcdef Region : us-east-1 Name : MySpotInstance Hostname : MySpotInstance.Mydomain.com InstanceType : m3.medium BidPrice : 0.0741 OnDemandPrice : 0.13 Savings : 55 % ImageName : WINDOWS_2016_BASE ImageID : ami-58a1a73e KeyName : MyKeyPair #> [CmdletBinding(SupportsShouldProcess=$true, DefaultParameterSetName='SearchBaseIds')] Param ( [Parameter(Mandatory=$true)] $Region, [Parameter(Mandatory=$true)] $InstanceType, # Applies this name tag to the instance after creation, if -DomainName is specified as well then registers a DNS CNAME for your instance using this name [string] $Name, # If -Name is also specified then a DNS CNAME is registered in this domain, provided the domain is hosted in R53 and you have rights to do so. [string] $DomainName, # Version of Windows e.g. 2012R2 or 2016. Default is 2012R2 [ValidateSet("1709","1803","2016", "2012R2", "2012", "2008R2","2008","2003")] [string] $OsVersion = 2016, [Parameter(ParameterSetName='SearchBaseIds')] [switch] $Base=$true, [Parameter(ParameterSetName='SearchSqlIds')] [ValidateSet("2014SP1","2014SP2","2016","2016SP1","2017","2012SP3","2012SP2","2008R2SP3","2008SP4","2005SP4")] [string] $SqlVersion, [Parameter(ParameterSetName='SearchSqlIds')] [ValidateSet("Express", "Web","Standard","Enterprise")] [string] $SqlEdition = "Standard", [switch] $Core, # Instance Profile (with IAM Role) to attach to new Instance [string] $InstanceProfile, # Path to User data file , using Your My Documents folder as a root [string] $UserData, # What Percrentage to add to the lowest Spot Price to ensure instance's longevity [int] $MarkUp = 1, #Specify an AMI id like ami-2b8c8452 [Parameter(ValueFromPipeline =$true, ValueFromPipelineByPropertyName=$true, ParameterSetName ='ImageId', Mandatory =$true)] [string] $ImageId, # The name of the Security Group, not the Security Group ID. The Function will get the ID. If none is specified the default Security Group is used. [string] $SecurityGroupName, # Switch to specify that a Spot instance should be created instead of On Demand. Bid price will be automatically calculated based on current bid price plus a markup percentage of which the default is 1. [switch] $SpotInstance, # The Name of the EC2 KeyPair to use when creating the instance [string] $KeyName, # The ID of the VPC you wish to use, if not specified, the default one is used. [string] $VpcId, # Last letter of the Availability Zone like a, b, c, d or e, if none specified, a is used [string] $AZSuffix = "a", [string] $SubNetId, [ValidateRange(1,15)] [Int] $NetworkInerfaces = 1 ) <#DynamicParam { $Names = Get-CmEc2InstanceTypes $ParameterName = 'InstanceType' $ParamDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $ParamAttrib = New-Object System.Management.Automation.ParameterAttribute $ParamAttrib.Mandatory= 1 $AttribColl = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $AttribColl.Add($ParamAttrib) $AttribColl.Add((New-Object System.Management.Automation.ValidateSetAttribute($Names))) $RuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter($ParameterName, [string], $AttribColl) $RuntimeParamDic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary $RuntimeParamDic.Add($ParameterName, $RuntimeParam) return $RuntimeParamDic }#> BEGIN { } Process { if ($SqlVersion) { Clear-Variable Base if ($InstanceType -like "t2.*" -and $SqlEdition -ne "Express") {Write-Error "Non Express editions of SQL Server are not permited to run on t2 instance types"} } [int]$Count = 1 $ErrorActionPreference = "Stop" $AvailabilityZone = $Region+$AZSuffix Write-Verbose "Geting On Demand Instance Pricing" $OndemandPrice = Get-EC2WindowsOndemandPrice -InstanceType $InstanceType -Region $Region if (!$ImageID) { Write-Verbose "Getting Current AMI for Selected OS" $ImageParam = @{OsVersion = $OsVersion} If ($Core) {$ImageParam.Add('Core',$true)} If ($Region) {$ImageParam.Add('Region',$Region)} If ($SqlVersion) {$ImageParam.Add('SqlVersion',$SqlVersion)} If ($SqlEdition) {$ImageParam.Add('SqlEdition',$SqlEdition)} try{$ImageID = Get-CMEC2ImageId @ImageParam}catch{} } if (!$ImageID) { Write-Error "Could not find an image with Search criteria in region $Region"} if (!$Keyname) { Write-Verbose "Getting first KeyPair for Region" $KeyName = (Get-EC2KeyPair -Region $Region)[0].KeyName } if (!$KeyName) {Write-Error "No EC2 Key Pairs found in region $Region, please create one"} If ($UserData) {$UserData64 = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($UserData))} If (!$SubNetId) { If (!$VpcId) { Write-Verbose "Getting default VPC" $VpcId = (Get-EC2Vpc -Region $Region| Where {$_.IsDefault -eq $true}).VpcId } If (!$VpcId) { Write-Error "Could not find default VPC in region $Region, Please specify one"} Write-Verbose "Getting Subnet for name $AvailabilityZone" $SubNetId = (Get-EC2Subnet -Region $Region | where {$_.AvailabilityZone -eq $AvailabilityZone -and $_.VpcId -eq $VPCid})[0].SubnetId } Else { $VpcId = (Get-EC2Subnet -Region $Region -SubnetId $SubNetId).VpcId } If (!$VpcId) {Write-Error "Could not determine VPC, check you have a default VPC in the region and if SubnetId is specified, make sure it is valid"} If ($SecurityGroupName) { Write-Verbose "Getting Security Group for name $SecurityGroupName" $SecurityGroupId = (Get-EC2SecurityGroup -Region $Region | where {$_.GroupName -eq $SecurityGroupName -and $_.VpcId -eq $VpcId})[0].GroupId If (!$SecurityGroupId) {Write-Error "Security Group with $SecurityGroupName cannot be found"} } else { Write-Verbose "Getting Security Group for VPC $VpcId" $SecurityGroupId = (Get-EC2SecurityGroup -Region $Region | where {$_.GroupName -eq "default" -and $_.VpcId -eq $VPCId})[0].GroupId } If (!$SecurityGroupId) { Write-Error "Could not find a Security Group with the name $SecurityGroupName in region $Region" } $Params = @{ Region = $Region MinCount = $Count MaxCount = $Count InstanceType = $InstanceType SecurityGroupId = $SecurityGroupId ImageId = $ImageId SubnetId = $SubNetId KeyName = $KeyName } if ($Name) { $tag1 = @{ Key="name"; Value=$Name } $Tags = @() $tagspec1 = New-Object -Type Amazon.EC2.Model.TagSpecification $tagspec1.ResourceType = "instance" $tagspec1.Tags.Add($tag1) $Tags+=$tagspec1 $tagspec2 = new-object -Type Amazon.EC2.Model.TagSpecification $tagspec2.ResourceType = "volume" $tagspec2.Tags.Add($tag1) $Tags+=$tagspec2 $Params.Add("TagSpecification",$Tags) } If ($SpotInstance) { $InstanceMarketOption = @{ MarketType ="Spot" <#SpotOptions = @{ InstanceInterruptionBehavior = "stop" SpotInstanceType = "persistent" }#> } $Params.Add("InstanceMarketOption",$InstanceMarketOption) } If ($UserData64) {$Params.Add("UserData",$UserData64)} If ($InstanceProfile) {$Params.Add("InstanceProfile_Name",$InstanceProfile)} $InstanceId = (New-EC2Instance @Params).Instances.InstanceId $global:testtest = $InstanceId if ($Name) { Write-Verbose "Applying Name Tag to instance" New-EC2Tag -Resource $InstanceId -Tag @{Key = "Name"; Value = $Name} -Region $Region If ($DomainName) { $DNSParams = @{InstanceId = $InstanceId} if($Region) {$DNSParams.Add('Region',$Region)} $SetDns = Set-CmEc2DnsName @DNSParams -DomainName $DomainName -InstanceName $Name $HostName = $SetDns.Hostname } } else { $HostName = $RunningInstance.PublicIPAddress } $OutputProperties = @{ InstanceId = $InstanceId Region = $Region Name = $Name Hostname = $HostName InstanceType = $InstanceType BidPrice = $BidPrice OnDemandPrice = $OnDemandPrice Savings = "$Savings %" ImageName = $ImageName ImageId = $ImageId KeyName = $KeyName InstanceProfile = $InstanceProfile } New-Object -TypeName PSObject -Property $OutputProperties } } |