Class: Terraspace::Check

Inherits:
Object
  • Object
show all
Extended by:
Memoist
Defined in:
lib/terraspace/check.rb

Constant Summary collapse

BINS =
%w[tofu terraform]
@@terraform_bin =
nil

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ Check

Returns a new instance of Check.



6
7
8
9
10
11
# File 'lib/terraspace/check.rb', line 6

def initialize(options={})
  @options = options
  # Terraspace requires this terraform version or a fork
  @min_terraform_version = "0.12"
  @max_terraform_version = "1.5.7"
end

Instance Attribute Details

#max_terraform_versionObject (readonly)

Returns the value of attribute max_terraform_version.



5
6
7
# File 'lib/terraspace/check.rb', line 5

def max_terraform_version
  @max_terraform_version
end

#min_terraform_versionObject (readonly)

Returns the value of attribute min_terraform_version.



5
6
7
# File 'lib/terraspace/check.rb', line 5

def min_terraform_version
  @min_terraform_version
end

Class Method Details

.check!Object

Used as library call



148
149
150
151
152
153
# File 'lib/terraspace/check.rb', line 148

def check!
  setup = new
  return if setup.ok?
  # run meth designed for CLI and will puts out informative messages about installed version and exit 1 when version is not ok
  setup.run
end

Instance Method Details

#allowed_terraform_version?Boolean Also known as: ok?

aliased with ok?

Returns:

  • (Boolean)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/terraspace/check.rb', line 52

def allowed_terraform_version?
  return true if ENV['TS_VERSION_CHECK'] == '0' && !Terraspace.cloud?
  return false unless terraform_bin
  return true if !terraform_bin.include?("terraform") # IE: allow any version of terraform forks

  major, minor, patch = terraform_version.split('.').map(&:to_i)
  min_major, min_minor, _ = @min_terraform_version.split('.').map(&:to_i)
  max_major, max_minor, max_patch = @max_terraform_version.split('.').map(&:to_i)

  # must be between min and max
  min_ok = major > min_major ||
          (major == min_major && minor >= min_minor)
  max_ok = major < max_major ||
          (major == max_major && minor < max_minor) ||
          (major == max_major && minor == max_minor && patch <= max_patch)

  min_ok && max_ok
end

#error_message(cloud: false) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/terraspace/check.rb', line 33

def error_message(cloud: false)
  name = cloud ? "Terraspace Cloud" : "Terraspace"
  cloud_note =<<~EOL

    Note: If you're using Terraspace Cloud, you won't be able to bypass this check.
    See: https://terraspace.cloud/docs/terraform/license/
  EOL

  puts "ERROR: #{name} requires Terraform between #{@min_terraform_version}.x and #{@max_terraform_version}".color(:red)
  puts <<~EOL
    This is because newer versions of Terraform have a BSL license
    If your usage is allowed by the license, you can bypass this check with:

        export TS_VERSION_CHECK=0
    #{cloud_note}
  EOL
end

#pretty_home(path) ⇒ Object



142
143
144
# File 'lib/terraspace/check.rb', line 142

def pretty_home(path)
  path.sub(ENV['HOME'], '~')
end

#run(cloud: false) ⇒ Object Also known as: ok!

Used for the CLI



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/terraspace/check.rb', line 14

def run(cloud: false)
  puts "terraspace version: #{Terraspace::VERSION}"
  if terraform_bin
    puts "#{terraform_bin_name} bin: #{pretty_home(terraform_bin)}"
    puts "#{terraform_bin_name} version: #{terraform_version}"
    # check for allowed version of terraform
    if allowed_terraform_version?
      puts "You're all set!".color(:green)
    else
      error_message(cloud: cloud)
      exit 1
    end
  else
    puts terraform_is_not_installed
    exit 1
  end
end

#terraform_binObject



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/terraspace/check.rb', line 82

def terraform_bin
  return ENV['TS_TERRAFORM_BIN'] if ENV['TS_TERRAFORM_BIN']
  return @@terraform_bin if @@terraform_bin.present?
  BINS.each do |bin|
    if Gem.win_platform?
      out = "is #{bin}.exe".strip
    else
      out = `type #{bin} 2>&1`.strip
      next unless $?.success?
    end
    md = out.match(/is (.*)/)
    if md
      @@terraform_bin = md[1]
      break
    end
  end
  @@terraform_bin
end

#terraform_bin_nameObject



102
103
104
# File 'lib/terraspace/check.rb', line 102

def terraform_bin_name
  terraform_bin ? File.basename(terraform_bin) : "terraform"
end

#terraform_is_not_installedObject



72
73
74
75
76
77
78
# File 'lib/terraspace/check.rb', line 72

def terraform_is_not_installed
  <<~EOL
    Terraform not installed. Unable to detect a terraform command.
    Please double check that an allowed version of terraform is installed.
    See: https://terraspace.cloud/docs/install/terraform/
  EOL
end

#terraform_versionObject

Sometimes Terraform shows the version info on the first line and sometimes on the bottom line. Account for that by finding the line.

$ terraform --version
Terraform v0.12.24

Your version of Terraform is out of date! The latest version
is 0.12.26. You can update by downloading from https://www.terraform.io/downloads.html

Another example

$ tofu --version
OpenTofu v1.6.0

Note: The -json option is only available in v0.13+



121
122
123
124
125
126
127
# File 'lib/terraspace/check.rb', line 121

def terraform_version
  out = `#{terraform_bin} --version`
  # 1st regexp is more strict to avoid false positives
  # 2nd regexp is more lenient in include beta suffixes
  line = out.split("\n").find { |l| l =~ /(\d+\.\d+\.\d+)/ }
  version = line.match(/(\d+\.\d+\.\d+.*)/)[1] if line
end

#terraspace_versionObject



130
131
132
# File 'lib/terraspace/check.rb', line 130

def terraspace_version
  Terraspace::VERSION
end

#versionsObject



134
135
136
137
138
139
140
# File 'lib/terraspace/check.rb', line 134

def versions
  {
    terraspace_version: terraspace_version,
    terraform_version: terraform_version,
    terraform_command: terraform_bin_name,
  }
end