Class: Sfn::Command::Destroy

Inherits:
Sfn::Command
  • Object
show all
Includes:
Sfn::CommandModule::Base
Defined in:
lib/sfn/command/destroy.rb

Constant Summary

Constants inherited from Sfn::Command

CONFIG_BASE_NAME, VALID_CONFIG_EXTENSIONS

Instance Method Summary collapse

Methods included from Sfn::CommandModule::Base

included

Methods inherited from Sfn::Command

#config, #initialize

Methods included from Sfn::CommandModule::Callbacks

#api_action!, #callbacks_for, #run_callbacks_for

Constructor Details

This class inherits a constructor from Sfn::Command

Instance Method Details

#execute!Object

Run the stack destruction action



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
# File 'lib/sfn/command/destroy.rb', line 9

def execute!
  name_required!
  stacks = name_args.sort
  plural = "s" if stacks.size > 1
  globs = stacks.find_all do |s|
    s !~ /^[a-zA-Z0-9-]+$/
  end
  unless globs.empty?
    glob_stacks = provider.connection.stacks.all.find_all do |remote_stack|
      globs.detect do |glob|
        File.fnmatch(glob, remote_stack.name)
      end
    end
    stacks += glob_stacks.map(&:name)
    stacks -= globs
    stacks.sort!
  end
  ui.warn "Destroying Stack#{plural}: #{ui.color(stacks.join(", "), :bold)}"
  ui.confirm "Destroy listed stack#{plural}?"
  stacks.each do |stack_name|
    stack = provider.connection.stacks.get(stack_name)
    if stack
      nested_stack_cleanup!(stack)
      begin
        api_action!(:api_stack => stack) do
          stack.destroy
        end
      rescue Miasma::Error::ApiError::RequestError => error
        raise unless error.response.code == 404
        # if stack is already gone, disable polling
        config[:poll] = false
      end
      ui.info "Destroy request complete for stack: #{ui.color(stack_name, :red)}"
    else
      ui.warn "Failed to locate requested stack: #{ui.color(stack_name, :bold)}"
    end
  end
  if config[:poll]
    if stacks.size == 1
      pstack = stacks.first
      begin
        poll_stack(pstack)
        stack = provider.connection.stacks.get(pstack)
        stack.reload
        if stack.state.to_s.end_with?("failed")
          ui.error("Stack #{ui.color(pstack, :bold)} still exists after polling complete.")
          raise "Failed to successfully destroy stack!"
        end
      rescue Miasma::Error::ApiError::RequestError => error
        # Ignore if stack cannot be reloaded
      end
    else
      ui.error "Stack polling is not available when multiple stack deletion is requested!"
    end
  end
  ui.info "  -> Destroyed SparkleFormation#{plural}: #{ui.color(stacks.join(", "), :bold, :red)}"
end

#nested_stack_cleanup!(stack) ⇒ Object

Cleanup persisted templates if nested stack resources are included



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
# File 'lib/sfn/command/destroy.rb', line 68

def nested_stack_cleanup!(stack)
  stack.nested_stacks.each do |n_stack|
    nested_stack_cleanup!(n_stack)
  end
  nest_stacks = stack.template.fetch("Resources", {}).values.find_all do |resource|
    provider.connection.data[:stack_types].include?(resource["Type"])
  end.each do |resource|
    url = resource["Properties"]["TemplateURL"]
    if url && url.is_a?(String)
      _, bucket_name, path = URI.parse(url).path.split("/", 3)
      bucket = provider.connection.api_for(:storage).buckets.get(bucket_name)
      if bucket
        file = bucket.files.get(path)
        if file
          file.destroy
          ui.info "Deleted nested stack template! (Bucket: #{bucket_name} Template: #{path})"
        else
          ui.warn "Failed to locate template file within bucket for deletion! (#{path})"
        end
      else
        ui.warn "Failed to locate bucket containing template file for deletion! (#{bucket_name})"
      end
    end
  end
end