src/installation.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
function Install-Terraform {
    <#
    .SYNOPSIS

    Installs the Terraform CLI tool.

    .DESCRIPTION

    Downloads and installs either a specific version of Terraform, or the latest one available.

    .PARAMETER Version
    Version of Terraform to install.

    .PARAMETER DisableLogo
    Disables the logo.

    .PARAMETER SetAsActive
    Automatically set the downloaded version as the active one.

    .INPUTS

    None. You cannot pipe objects to Install-Terraform.

    .OUTPUTS

    System string.

    .EXAMPLE

    Install-Terraform

    .EXAMPLE

    Install-Terraform -Version 0.13.1

    .EXAMPLE

    Install-Terraform 0.13.1 -SetAsActive

    .LINK

    https://github.com/roberthstrand/tftools/docs/Install-TerraformVersion.md

    #>

    [CmdletBinding()]
    param (
        [Parameter(Position = 0)]
        [string]
        $Version,
        [Parameter()]
        [switch]
        $DisableLogo,
        [Parameter()]
        [switch]
        $SetAsActive
    )
    <#----------------------------------------------+
    |The secret to getting ahead is getting started |
    | - Mark Twain |
    +----------------------------------------------#>

    begin {
        # Write the logo, +1 to sexiness - if not disabled
        if (!$DisableLogo) { Write-tftoolsLogo }
        # Set platform specific variables, by determining what version of PowerShell is running and on what platform
        Set-PlatformVariables
        # Check if the working directory exists, create it if it doesn't
        try { 
            New-Item -Path $tfPath -ItemType Directory -ErrorAction Stop | Out-Null
        }
        catch { 
            Write-Host "Working directory found..." -ForegroundColor Green
        }
        # If the version parameter wasn't used, ask the user what version they want installed
        # Can also be set to latest, or TODO:beta-latest
        if (!$Version) {
            Write-Host "What version do you want?"
            do {
                $userResponse = Read-Host "Version number or (l)atest`n"
                $Version = $userResponse
            } while ($userResponse.ToLower() -notmatch "(latest)|(l\b)|(beta-latest)|(b\b)|([0-9]+\.[0-9]+\.[0-9]+)?(-[\S]+)?()")
        }
        elseif ($Version -eq "latest") {
            Write-Host "Fetching the latest version of Terraform" -ForegroundColor Yellow
        }
        elseif ($Version -eq "beta-latest") {
            Write-Host "Fetching the latest beta version of Terraform" -ForegroundColor Yellow
        }
        elseif ($Version -like "*.*.*") {
            Write-Host "Fetching Terraform v$Version" -ForegroundColor Yellow
        }
        # To avoid existential crisis, we want to check that the version asked for is available.
        # Also, if latest or beta-latest is requested, we need to figure out what that is.

        # Fetch the HashiCorp Terraform release page and stick it into an object
        $releasePageURL = "https://releases.hashicorp.com/terraform/"
        [string]$tfReleases = Invoke-WebRequest $releasePageURL -UseBasicParsing | Select-Object -ExpandProperty Content
        # We then want to pick out all the releases available
        [System.Collections.ArrayList]$tfReleases = $tfReleases -split "`n" | Select-String -Pattern '(?<=\/)([\d]+.[\d]+.[\d]+-[\w]+[\d]+|[\d]+.[\d]+.[\d]+)' |
        ForEach-Object { $_.Matches | ForEach-Object { $_.Groups[1].Value } }
        # If version is set to latest, we download the latest release if it doesn't already exist in our working path
        if (($Version -eq "latest") -or ($Version -eq "l")) {
            # We want the latest stable version, so if the latest version is beta, release candidate or simular, we'll try and find the last numbered release.
            switch ($tfReleases[0] -match '-') {
                $true { 
                    $i = 0
                    do {
                        $i += 1
                        $Version = $tfReleases[$i]
                    } while ($Version -match '-')
                }
                Default { $Version = $tfReleases[0] }
            }
        }
        elseif ($tfReleases -notcontains $Version) {
            # Stops everything if the version requested doesn't exist
            Write-Error "Invalid version"
            break
        }
    }
    process {
        # If the release exist, check wether or not it has already been downloaded
        switch (Test-Path -Path "$tfPath/$Version") {
            $false {
                Write-Progress "Downloading Terraform v$Version"
                Write-Host "Downloading Terraform v$Version" -ForegroundColor Yellow
            
                # Creating a temporary file to be used while downloading the release
                $tempFile = [System.IO.Path]::GetTempFileName()
                
                # Downloading the release
                $downloadSplat = @{
                    uri             = "https://releases.hashicorp.com/terraform/" + $version + "/terraform_" + $Version + "_" + $machineOS + ".zip"
                    OutFile         = $tempFile
                    UseBasicParsing = $true
                }
                $ProgressPreference = 'SilentlyContinue'
                Invoke-WebRequest @downloadSplat
                
                # Unzip that sucker!
                Export-ZipFile -ZipFile $tempFile -OutputFolder "$tfPath/$Version"
                
                # If the switch SetAsActive is present, automatically set the active version
                if ($SetAsActive) {
                    Set-TerraformVersion -Version $Version
                }
                else {
                    # Ask the user if they want to set the downloaded Terraform as the active version
                    $userResponse = Read-Host "You want to set v$Version as the active version? `n(Y)es or (n)o?"
                    # If they answer yes...
                    switch ($userResponse.ToLower()) {
                        y {
                            Set-TerraformVersion -Version $Version
                        }
                        Default { continue }
                    }
                }
                Write-Host "v$Version downloaded" -ForegroundColor Green
                if ($userResponse -eq "y") { Write-Host "And activated!" -ForegroundColor Magenta }
                # Cleanup on isle five
                Remove-Item -Path $tempFile
            }
            Default {
                Write-Error "v$Version already exist"
                continue
            }
        }
    }
    # Don’t adventures ever have an end?
    # I suppose not. Someone else always has to carry on the story.
}
function Remove-Terraform {
    <#
    .SYNOPSIS

    Removes a version of the Terraform CLI tool.

    .DESCRIPTION

    Removes a version of Terraform from the local version library.

    .PARAMETER Version
    Version of Terraform to remove.

    .INPUTS

    None. You cannot pipe objects to Install-Terraform.

    .OUTPUTS

    System string.

    .EXAMPLE

    Remove-Terraform

    .EXAMPLE

    Remove-Terraform -Version 0.13.1

    .LINK

    https://github.com/roberthstrand/tftools/docs/Remove-Terraform.md

    #>

    param (
        # Terraform version
        [Parameter(Mandatory, Position = 0)]
        [ValidateNotNullOrEmpty()]
        [string]
        $Version,
        [bool]
        $Confirm
    )
    Set-PlatformVariables
    $removeSplat = @{
        Path        = "$tfPath/$Version"
        Force       = $true
        recurse     = $true
        confirm     = $Confirm
    }
    try {
        Remove-Item @removeSplat -ErrorAction Stop
    }
    catch {
        Write-Error "Version not found"
    }
}