module Terradactyl::Commands

rubocop:disable Metrics/ModuleLength

Public Class Methods

extend_by_revision(tf_version, object) click to toggle source
# File lib/terradactyl/commands.rb, line 59
def extend_by_revision(tf_version, object)
  anon_module = revision_module
  revision    = revision_constant(tf_version)

  anon_module.include(self)
  anon_module.prepend(revision)

  object.class.define_singleton_method(:revision) { revision }
  object.define_singleton_method(:revision) { revision }

  object.extend(anon_module)
end

Private Class Methods

decorate(base, method) click to toggle source
Calls superclass method
# File lib/terradactyl/commands.rb, line 81
def decorate(base, method)
  base.define_singleton_method(method) do |*args, &block|
    setup_terraform
    pushd(stack_path)
    super(*args, &block)
  ensure
    popd
  end
end
extended(base) click to toggle source
# File lib/terradactyl/commands.rb, line 77
def extended(base)
  terraform_methods.each { |method| decorate(base, method) }
end
revision_constant(tf_version) click to toggle source
# File lib/terradactyl/commands.rb, line 100
def revision_constant(tf_version)
  revision = Terradactyl::Terraform.calc_revision(tf_version)
  const_get(revision)
end
revision_module() click to toggle source
# File lib/terradactyl/commands.rb, line 74
def revision_module
  Module.new do
    class << self
      def extended(base)
        terraform_methods.each { |method| decorate(base, method) }
      end

      def decorate(base, method)
        base.define_singleton_method(method) do |*args, &block|
          setup_terraform
          pushd(stack_path)
          super(*args, &block)
        ensure
          popd
        end
      end

      private

      def terraform_methods
        public_instance_methods.reject { |m| m == :terraform_methods }
      end
    end
  end
end
terraform_methods() click to toggle source
# File lib/terradactyl/commands.rb, line 93
def terraform_methods
  public_instance_methods.reject { |m| m == :terraform_methods }
end

Public Instance Methods

apply() click to toggle source
# File lib/terradactyl/commands.rb, line 138
def apply
  Apply.execute(dir_or_plan: plan_file, options: command_options)
end
clean() click to toggle source

rubocop:disable Metrics/AbcSize

# File lib/terradactyl/commands.rb, line 166
def clean
  removals = config.cleanup.match.map { |p| Dir.glob("**/#{p}") }
  removals << `find . -type d -empty`.split if config.cleanup.empty
  removals = removals.flatten.sort.uniq.each do |trash|
    print_dot("Removing: #{trash}", :light_yellow)
    FileUtils.rm_rf(trash)
  end
  puts unless removals.empty?
end
destroy() click to toggle source
# File lib/terradactyl/commands.rb, line 147
def destroy
  options = command_options.tap { |dat| dat.state = state_file }
  Destroy.execute(dir_or_plan: nil, options: options)
end
fmt() click to toggle source
# File lib/terradactyl/commands.rb, line 157
def fmt
  Fmt.execute(dir_or_plan: nil, options: command_options)
end
init() click to toggle source
# File lib/terradactyl/commands.rb, line 108
def init
  Init.execute(dir_or_plan: nil, options: command_options)
end
lint() click to toggle source
# File lib/terradactyl/commands.rb, line 152
def lint
  options = command_options.tap { |dat| dat.check = true }
  Fmt.execute(dir_or_plan: nil, options: options)
end
plan() click to toggle source
# File lib/terradactyl/commands.rb, line 112
def plan
  options = command_options.tap do |dat|
    dat.state    = state_file
    dat.out      = plan_file
    dat.no_color = true
  end

  captured = Plan.execute(dir_or_plan: nil,
                          options: options,
                          capture: true)

  @plan_file_obj = load_plan_file

  case captured.exitstatus
  when 0
    'No changes. Infrastructure is up-to-date.'
  when 1
    @plan_file_obj.error_output = captured.stderr
  when 2
    @plan_file_obj.plan_output = captured.stdout
    @plan_file_obj.save
  end

  captured.exitstatus
end
refresh() click to toggle source
# File lib/terradactyl/commands.rb, line 142
def refresh
  options = command_options.tap { |dat| dat.state = state_file }
  Refresh.execute(dir_or_plan: nil, options: options)
end
upgrade() click to toggle source

rubocop:enable Metrics/AbcSize

# File lib/terradactyl/commands.rb, line 177
def upgrade
  perform_upgrade
end
validate() click to toggle source
# File lib/terradactyl/commands.rb, line 161
def validate
  Validate.execute(dir_or_plan: nil, options: command_options)
end

Private Instance Methods

load_plan_file() click to toggle source

rubocop:enable Metrics/AbcSize

# File lib/terradactyl/commands.rb, line 307
def load_plan_file
  Terraform::PlanFile.new(plan_path: plan_file, parser: parser)
end
perform_upgrade() click to toggle source

rubocop:disable Metrics/AbcSize

# File lib/terradactyl/commands.rb, line 286
def perform_upgrade
  options = command_options.tap { |dat| dat.yes = true }
  upgrade = Upgrade.new(dir_or_plan: nil, options: options)

  sanitize_terraform_settings

  update_required_version(upgrade.next_version)

  if (result = upgrade.execute).zero?
    update_required_version(upgrade.next_version)
    FileUtils.rm_rf('terradactyl.yaml') if File.exist?('terradactyl.yaml')
  end

  print_content(upgrade_notice) if result.zero?

  print_crit(upgrade_notice_rev013) if upgrade.next_version =~ /0\.13/

  result
end
sanitize_terraform_settings() click to toggle source
# File lib/terradactyl/commands.rb, line 198
def sanitize_terraform_settings
  settings_files.each do |file|
    next if file == versions_file

    write_stream = Tempfile.new(Common.tag)
    File.open(file, 'r').each_line do |line|
      write_stream.puts line unless line.match(Common.required_versions_re)
    end
    write_stream.close
    FileUtils.mv(write_stream.path, file)
  end
end
settings_files() click to toggle source
# File lib/terradactyl/commands.rb, line 187
def settings_files
  Dir.glob('*.tf').each_with_object([]) do |file, memo|
    File.open(file, 'r').each_line do |line|
      if line.match(Common.required_versions_re)
        memo << file
        break
      end
    end
  end
end
update_required_version(upgrade_version) click to toggle source
# File lib/terradactyl/commands.rb, line 211
    def update_required_version(upgrade_version)
      if File.exist?(versions_file)
        settings = File.read(versions_file)
        if (req_version = settings.match(Common.required_versions_re))
          substitution = %(#{req_version[:assignment]}"~> #{upgrade_version}")
          settings.sub!(Common.required_versions_re, substitution)
        end
      else
        # This is ugly, so let's explain ...
        #
        # When the versions.tf is present, but the stack is ~> 0.11.0, the
        # `terraform 0.12upgrade` subcommand will FAIL because it uses the
        # presence of this file as the sole gauge as to whether or not
        # the stack can be upgraded. So, why not just use `-force`? Haha yes ...
        #
        # When the `versions.tf` file exists and the `-force` flag is passed,
        # it will create a `versions-1.tf` file ... FML :facepalm:
        #
        # So, make the creation of a de facto versions.tf contingent upon the
        # Terraform upgrade_version. Yay.
        unless upgrade_version =~ /0\.12/
          settings = <<~VERSIONS
            terraform {
              required_version = "~> #{upgrade_version}"
            }
          VERSIONS
        end
      end

      File.write(versions_file, settings) if settings
    end
upgrade_notice() click to toggle source
# File lib/terradactyl/commands.rb, line 243
    def upgrade_notice
      output = File.read('versions.tf')
      insert = output.strip.split("\n").map { |l| "    #{l}" }.join($INPUT_RECORD_SEPARATOR)

      <<~NOTICE
        This stack has been upgraded to version the described below and its
        Terradactly config file (if it existed) has been removed.

        #{insert}

        NOTES:

         • ALL Terraform version constraints are now specified in `versions.tf` using
          the `required_version` directive.

         • If your stack already contained one or more `required_version` directives,
          they have been consolidated into a single directive in `versions.tf`.

         • Terraform provider version contraints ARE NOT upgraded automatically. You
          will need to edit these MANUALLY.

         • Before proceeding. please perform a `terradactyl quickplan` on your stack
          to ensure the upgraded stack functions as intended.
      NOTICE
    end
upgrade_notice_rev013() click to toggle source
# File lib/terradactyl/commands.rb, line 269
    def upgrade_notice_rev013
      <<~NOTICE
        STOP UPGRADING!

              Upgrading from Terraform 0.12 to 0.13 requires an apply to be performed
              before continuing ...

              DO NOT attempt to upgrade any further without first committing the existing
              changes and seeing they are applied.

              See the documentation here if you require more infomation ...

              https://www.terraform.io/upgrade-guides/0-13.html
      NOTICE
    end
versions_file() click to toggle source
# File lib/terradactyl/commands.rb, line 183
def versions_file
  'versions.tf'
end