Class: RefArchSetup::DownloadHelper

Inherits:
Object
  • Object
show all
Defined in:
lib/ref_arch_setup/download_helper.rb

Overview

Download helper methods

Constant Summary collapse

PE_VERSIONS_URL =

the ‘Puppet Enterprise Version History’ url

"https://puppet.com/misc/version-history".freeze
BASE_PROD_URL =

the base of the URL where prod PE tarballs are hosted

"https://s3.amazonaws.com/pe-builds/released".freeze
MIN_PROD_VERSION =

the minimum prod version supported by RAS

"2018.1.0".freeze
PE_PLATFORMS =

the supported platforms for PE installation using RAS

%w[el-6-x86_64
el-7-x86_64
sles-12-x86_64
ubuntu-16.04-amd64
ubuntu-18.04-amd64].freeze

Class Method Summary collapse

Class Method Details

.build_prod_tarball_url(version = "latest", host = "localhost", platform = "default") ⇒ string

Builds the prod tarball URL for the specified or default version of PE

*** Specifying the host will determine and validate the platform for the host *** Specifying the platform will ignore the host value and only perform the validation

@example: url = build_prod_tarball_url() url = build_prod_tarball_url(“2018.1.4”, “master.mydomain.net”, “”) url = build_prod_tarball_url(“2018.1.4”, “value_is_ignored”, “sles-12-x86_64”)

Parameters:

  • version (string) (defaults to: "latest")

    The desired version of PE (default = “latest”)

  • host (string) (defaults to: "localhost")

    The target host for this PE tarball (default = “localhost”)

  • platform (string) (defaults to: "default")

    The target platform for this PE tarball

Returns:

  • (string)

    the prod tarball URL

Author:

  • Bill Claytor



59
60
61
62
63
64
65
66
# File 'lib/ref_arch_setup/download_helper.rb', line 59

def self.build_prod_tarball_url(version = "latest", host = "localhost", platform = "default")
  init
  pe_version = handle_prod_version(version)
  pe_platform = handle_platform(host, platform)
  url = "#{@base_prod_url}/#{pe_version}/puppet-enterprise-#{pe_version}-#{pe_platform}.tar.gz"
  puts "URL: #{url}"
  return url
end

.ensure_supported_prod_version(version) ⇒ true, false

Determines whether the specified version is supported by RAS

@example:

result = ensure_supported_prod_version("2018.1.4")

Parameters:

  • version (string)

    The specified version of PE

Returns:

  • (true, false)

    Whether the specified version is supported

Raises:

  • (RuntimeError)

    If the specified version is not supported

Author:

  • Bill Claytor



152
153
154
155
156
157
158
159
160
161
162
163
# File 'lib/ref_arch_setup/download_helper.rb', line 152

def self.ensure_supported_prod_version(version)
  major_version = version.split(".")[0]
  supported_version = @min_prod_version.split(".")[0]

  supported = major_version >= supported_version ? true : false
  puts "Specified version #{version} is supported by RAS" if supported
  puts "The minimum supported version is #{@min_prod_version}" unless supported

  raise "Specified version #{version} is not supported by RAS" unless supported

  return supported
end

.ensure_valid_prod_version(version) ⇒ true, false

Determines whether the specified version is an actual production version of PE

@example:

result = ensure_valid_prod_version("2018.1.4")

Parameters:

  • version (string)

    The specified version of PE

Returns:

  • (true, false)

    Whether the specified version was found

Raises:

  • (RuntimeError)

    If the specified version is not found

Author:

  • Bill Claytor



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/ref_arch_setup/download_helper.rb', line 127

def self.ensure_valid_prod_version(version)
  puts "Verifying specified PE version: #{version}"

  result = parse_prod_versions_url("//table/tbody/tr/td[contains(., '#{version}')]")
  found = result.text == version ? true : false

  puts "Specified version #{version} was found" if found
  raise "Specified version not found: #{version}" unless found

  return found
end

.fetch_prod_versionsOga::XML::NodeSet

Fetches the list of production PE versions from the ‘Puppet Enterprise Version History’ *note: this is no longer used but has been left as an example @example:

versions = fetch_prod_versions

Returns:

  • (Oga::XML::NodeSet)

    The versions list

Author:

  • Bill Claytor



174
175
176
177
178
179
180
181
182
183
184
185
# File 'lib/ref_arch_setup/download_helper.rb', line 174

def self.fetch_prod_versions
  versions = parse_prod_versions_url
  puts "Versions:"

  versions.each do |version|
    version_text = version.text
    puts version_text
  end
  puts

  return versions
end

.get_host_platform(host) ⇒ string

Handles the platform for the specified host using the host’s facts

@example:

platform = get_host_platform("localhost")

rubocop:disable Metrics/MethodLength rubocop:disable Metrics/AbcSize rubocop:disable Metrics/CyclomaticComplexity

Parameters:

  • host (string)

    The target host

Returns:

  • (string)

    The corresponding platform for the specified host

Raises:

  • (RuntimeError)

    If the facts status is ‘failure’

  • (RuntimeError)

    If the platform can’t be determined

Author:

  • Bill Claytor



310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
# File 'lib/ref_arch_setup/download_helper.rb', line 310

def self.get_host_platform(host)
  facts = retrieve_facts(host)

  status = facts[0]["status"]
  raise "Facts indicate that status for host #{host} is failure" if status == "failure"

  os = facts[0]["result"]["os"]
  os_name = os["name"]
  os_family = os["family"]
  platform_type = nil

  case os_family
  when "RedHat"
    platform_type = "el"
    platform_arch = "x86_64"
    release = os["release"]["major"]
  when "SLES"
    platform_type = "sles"
    platform_arch = "x86_64"
    release = os["release"]["major"]
  when "Debian"
    if os_name == "Ubuntu"
      platform_type = "ubuntu"
      platform_arch = "amd64"
      release = os["release"]["full"]
    end
  end

  raise "Unable to determine platform for host: #{host}" unless platform_type
  platform = "#{platform_type}-#{release}-#{platform_arch}"
  puts "Host platform: #{platform}"

  return platform
end

.handle_platform(host, platform) ⇒ string

Handles the host and platform and determines the appropriate PE platform

*** Specifying the host will determine and validate the platform for the host *** Specifying the platform will ignore the host value and only perform the validation

@example:

handle_platform("my_host", "default")
handle_platform("value_is_ignored", "sles-12-x86_64")

Parameters:

  • host (string)

    The target host for this PE tarball (default = “localhost”)

  • platform (string)

    The target platform for this PE tarball

Returns:

  • (string)

    The PE platform

Raises:

  • (RuntimeError)

    If the platform is not valid

Author:

  • Bill Claytor



281
282
283
284
285
286
287
288
289
290
291
# File 'lib/ref_arch_setup/download_helper.rb', line 281

def self.handle_platform(host, platform)
  if platform == "default"
    puts "Default platform specified; determining platform for host: #{host}"
    pe_platform = get_host_platform(host)
  else
    puts "Specified platform: #{platform}"
    pe_platform = platform
  end
  raise "Invalid PE platform: #{pe_platform}" unless valid_platform?(pe_platform)
  return pe_platform
end

.handle_prod_version(version) ⇒ string

Retrieves the latest production PE version or verifies a user-specified version

@example:

version = handle_prod_version("latest")
version = handle_prod_version("2018.1.4")

Parameters:

  • version (string)

    The desired version of PE

Returns:

  • (string)

    The corresponding PE version

Raises:

  • (RuntimeError)

    If the specified version is not valid

Author:

  • Bill Claytor



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

def self.handle_prod_version(version)
  if version == "latest"
    pe_version = latest_prod_version
    puts "The latest version is #{pe_version}"
  else
    success = ensure_valid_prod_version(version) && ensure_supported_prod_version(version)
    raise "Invalid version: #{version}" unless success

    pe_version = version
    puts "Proceeding with specified version: #{pe_version}"
  end

  puts

  return pe_version
end

.initObject

Initializes the instance variables to the defaults or values specified by environment variables

@example: init

Author:

  • Bill Claytor



34
35
36
37
38
39
# File 'lib/ref_arch_setup/download_helper.rb', line 34

def self.init
  @pe_versions_url = ENV["PE_VERSIONS_URL"] ? ENV["PE_VERSIONS_URL"] : PE_VERSIONS_URL
  @base_prod_url = ENV["BASE_PROD_URL"] ? ENV["BASE_PROD_URL"] : BASE_PROD_URL
  @min_prod_version = ENV["MIN_PROD_VERSION"] ? ENV["MIN_PROD_VERSION"] : MIN_PROD_VERSION
  @pe_platforms = PE_PLATFORMS
end

.latest_prod_versionstring

Retrieves the latest production version of PE from the ‘Puppet Enterprise Version History’

@example:

latest_version = latest_prod_version

Returns:

  • (string)

    The latest production version of PE

Author:

  • Bill Claytor



108
109
110
111
112
# File 'lib/ref_arch_setup/download_helper.rb', line 108

def self.latest_prod_version
  result = parse_prod_versions_url("//table/tbody/tr[1]/td[1]")
  latest_version = result.text
  return latest_version
end

.parse_prod_versions_url(xpath = "//table/tbody/tr/td[1]") ⇒ Oga::XML::NodeSet

Parses the ‘Puppet Enterprise Version History’ using the specified xpath and returns the result

@example:

versions = parse_prod_versions_url
latest_version = parse_prod_versions_url("//table/tbody/tr[1]/td[1]")
result = parse_prod_versions_url("//table/tbody/tr/td[contains(., '#{version}')]")

Parameters:

  • xpath (string) (defaults to: "//table/tbody/tr/td[1]")

    The xpath to use when parsing the version history

Returns:

  • (Oga::XML::NodeSet)

    The resulting Oga NodeSet

Author:

  • Bill Claytor



201
202
203
204
205
206
207
208
209
210
211
# File 'lib/ref_arch_setup/download_helper.rb', line 201

def self.parse_prod_versions_url(xpath = "//table/tbody/tr/td[1]")
  puts "Checking Puppet Enterprise Version History: #{@pe_versions_url}"

  uri = URI.parse(@pe_versions_url)
  response = Net::HTTP.get_response(uri)
  validate_response(response)

  document = Oga.parse_html(response.body)
  result = document.xpath(xpath)
  return result
end

.retrieve_facts(hosts) ⇒ Array<Hash] The retrieved facts

Retrieves the facts for the specified host(s) using the facts::retrieve plan

@example:

facts = retrieve_facts("localhost")

Parameters:

  • hosts (string)

    The host(s) from which to retrieve facts

Returns:

  • (Array<Hash] The retrieved facts)

    Array<Hash] The retrieved facts

Raises:

  • (JSON::ParserError)

    If the output from the bolt plan can’t be parsed

  • (BoltCommandError)

    If the bolt command is not successful or the output is nil

Author:

  • Bill Claytor



362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'lib/ref_arch_setup/download_helper.rb', line 362

def self.retrieve_facts(hosts)
  plan = "facts::retrieve"
  puts "Retrieving facts for hosts: #{hosts}"

  output = BoltHelper.run_forge_plan_with_bolt(plan, nil, hosts)

  begin
    facts = JSON.parse(output)
  rescue
    puts "Unable to parse bolt output"
    raise
  end

  return facts
end

.valid_platform?(platform) ⇒ true, false

Determines whether the specified platform is a valid PE platform

@example:

is_valid = valid_platform?("sles-12-x86_64")

TODO: validate for a specified version?

Parameters:

  • platform (string)

    The platform

Returns:

  • (true, false)

    Based on validity of the specified platform

Author:

  • Bill Claytor



391
392
393
394
395
396
397
# File 'lib/ref_arch_setup/download_helper.rb', line 391

def self.valid_platform?(platform)
  valid = @pe_platforms.include?(platform) ? true : false
  puts "Platform #{platform} is valid" if valid
  puts "Platform #{platform} is not valid" unless valid
  puts "Valid platforms are: #{@pe_platforms}" unless valid
  return valid
end

.validate_response(res, valid_response_codes = ["200"], invalid_response_bodies = ["", nil]) ⇒ true, false

Determines whether the response is valid

rubocop:disable Metrics/AbcSize rubocop:disable Metrics/MethodLength rubocop:disable Metrics/CyclomaticComplexity rubocop:disable Metrics/PerceivedComplexity

Examples:

valid = validate_response(res)
valid = validate_response(res, ["200", "123"], ["", nil])

Parameters:

  • res (Net::HTTPResponse)

    The HTTP response to evaluate

  • valid_response_codes (Array) (defaults to: ["200"])

    The list of valid response codes

  • invalid_response_bodies (Array) (defaults to: ["", nil])

    The list of invalid response bodies

Returns:

  • (true, false)

    Based on whether the response is valid

Raises:

  • (RuntimeError)

    If the response is not valid

Author:

  • Bill Claytor



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
# File 'lib/ref_arch_setup/download_helper.rb', line 233

def self.validate_response(res, valid_response_codes = ["200"],
                           invalid_response_bodies = ["", nil])
  is_valid_response = false

  if res.nil?
    puts "Invalid response:"
    puts "nil"
    puts
  elsif !valid_response_codes.include?(res.code) ||
        invalid_response_bodies.include?(res.body)
    code = res.code.nil? ? "nil" : res.code
    body = res.body.nil? ? "nil" : res.body

    puts "Invalid response:"
    puts "code: #{code}"
    puts "body: #{body}"
    puts
  else
    is_valid_response = true
  end

  raise "Invalid response" unless is_valid_response

  return is_valid_response
end