Class: Amigrind::Repo

Inherits:
Object
  • Object
show all
Includes:
Core::Logging::Mixin
Defined in:
lib/amigrind/repo.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path) ⇒ Repo

Returns a new instance of Repo.



7
8
9
10
11
12
13
14
15
# File 'lib/amigrind/repo.rb', line 7

def initialize(path)
  @path = File.expand_path path

  raise "'path' (#{path}) is not a directory." unless Dir.exist?(path)
  raise "'path' is not an Amigrind root (lacks .amigrind_root file)." \
    unless File.exist?(File.join(path, '.amigrind_root'))

  info_log "using Amigrind path: #{path}"
end

Instance Attribute Details

#pathObject (readonly)

Returns the value of attribute path.



5
6
7
# File 'lib/amigrind/repo.rb', line 5

def path
  @path
end

Class Method Details

.init(path:) ⇒ Object



176
177
178
# File 'lib/amigrind/repo.rb', line 176

def init(path:)
  raise "TODO: implement"
end

.with_repo(path: nil, &block) ⇒ Object



180
181
182
183
184
185
186
187
188
# File 'lib/amigrind/repo.rb', line 180

def with_repo(path: nil, &block)
  path = path || ENV['AMIGRIND_PATH'] || Dir.pwd

  repo = Repo.new(path)

  Dir.chdir path do
    block.call(repo)
  end
end

Instance Method Details

#add_to_channel(env, blueprint_name, id, channel) ⇒ Object

TODO: refactor these client-y things.



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
# File 'lib/amigrind/repo.rb', line 83

def add_to_channel(env, blueprint_name, id, channel)
  raise "'env' must be a String or an Environment." \
    unless env.is_a?(String) || env.is_a?(Environments::Environment)
  raise "'blueprint_name' must be a String." unless blueprint_name.is_a?(String)
  raise "'id' must be a Fixnum." unless id.is_a?(Fixnum)
  raise "'channel' must be a String or Symbol." \
    unless channel.is_a?(String) || channel.is_a?(Symbol)

  if env.is_a?(String)
    env = environment(env)
  end

  raise "channel '#{channel}' does not exist in environment '#{env.name}'." \
    unless env.channels.key?(channel.to_s) || channel.to_sym == :latest

  credentials = Amigrind::Config.aws_credentials(env)

  amigrind_client = Amigrind::Core::Client.new(env.aws.region, credentials)
  ec2 = Aws::EC2::Client.new(region: env.aws.region, credentials: credentials)

  image = amigrind_client.get_image_by_id(name: blueprint_name, id: id)

  tag_key = Amigrind::Core::AMIGRIND_CHANNEL_TAG % { channel_name: channel }

  info_log "setting '#{tag_key}' on image #{image.id}..."
  ec2.create_tags(
    resources: [ image.id ],
    tags: [
      {
        key: tag_key,
        value: '1'
      }
    ]
  )
end

#blueprint_namesObject



62
63
64
# File 'lib/amigrind/repo.rb', line 62

def blueprint_names
  Dir[File.join(blueprints_path, "*.rb")].map { |f| File.basename(f, ".rb") }
end

#blueprints_pathObject



21
22
23
# File 'lib/amigrind/repo.rb', line 21

def blueprints_path
  File.join(path, 'blueprints')
end

#environment(name) ⇒ Object

TODO: cache environments (but make configurable)



43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/amigrind/repo.rb', line 43

def environment(name)
  yaml_path = yaml_path_if_exists(name)
  rb_path = rb_path_if_exists(name)

  raise "found multiple env files for same env #{name}." if !yaml_path.nil? && !rb_path.nil?
  raise "TODO: implement Ruby environments." unless rb_path.nil?

  env = Environments::Environment.load_yaml_file(yaml_path) unless yaml_path.nil?

  raise "no env found for '#{name}'." if env.nil?

  IceNine.deep_freeze(env)
  env
end

#environment_namesObject

TODO: Ruby DSL environments



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/amigrind/repo.rb', line 26

def environment_names
  yaml_environments =
    Dir[File.join(environments_path, '*.yaml')] \
      .map { |f| File.basename(f, '.yaml').to_s.strip.downcase }

  rb_environments =
    [].map { |f| File.basename(f, '.rb').to_s.strip.downcase }

  duplicate_environments = yaml_environments & rb_environments
  duplicate_environments.each do |dup_env_name|
    warn_log "environment '#{dup_env_name}' found in both YAML and Ruby; skipping."
  end

  (yaml_environments + rb_environments - duplicate_environments).sort
end

#environments_pathObject



17
18
19
# File 'lib/amigrind/repo.rb', line 17

def environments_path
  File.join(path, 'environments')
end

#evaluate_blueprint(blueprint_name, env) ⇒ Object

TODO: cache blueprint/environment tuples (but make configurable)



67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/amigrind/repo.rb', line 67

def evaluate_blueprint(blueprint_name, env)
  raise "'env' must be a String or an Environment." \
    unless env.is_a?(String) || env.is_a?(Environments::Environment)

  if env.is_a?(String)
    env = environment(env)
  end

  ev = Amigrind::Blueprints::Evaluator.new(File.join(blueprints_path,
                                                     "#{blueprint_name}.rb"),
                                           env)

  ev.blueprint
end

#get_image_by_channel(env, blueprint_name, channel, steps_back = 0) ⇒ Object



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/amigrind/repo.rb', line 155

def get_image_by_channel(env, blueprint_name, channel, steps_back = 0)
  raise "'env' must be a String or an Environment." \
    unless env.is_a?(String) || env.is_a?(Environments::Environment)
  raise "'blueprint_name' must be a String." unless blueprint_name.is_a?(String)
  raise "'channel' must be a String or Symbol." \
    unless channel.is_a?(String) || channel.is_a?(Symbol)

  if env.is_a?(String)
    env = environment(env)
  end

  raise "channel '#{channel}' does not exist in environment '#{env.name}'." \
    unless env.channels.key?(channel.to_s) || channel.to_sym == :latest

  credentials = Amigrind::Config.aws_credentials(env)
  amigrind_client = Amigrind::Core::Client.new(env.aws.region, credentials)

  amigrind_client.get_image_by_channel(name: blueprint_name, channel: channel, steps_back: steps_back)
end

#remove_from_channel(env, blueprint_name, id, channel) ⇒ Object



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
# File 'lib/amigrind/repo.rb', line 119

def remove_from_channel(env, blueprint_name, id, channel)
  raise "'env' must be a String or an Environment." \
    unless env.is_a?(String) || env.is_a?(Environments::Environment)
  raise "'blueprint_name' must be a String." unless blueprint_name.is_a?(String)
  raise "'id' must be a Fixnum." unless id.is_a?(Fixnum)
  raise "'channel' must be a String or Symbol." \
    unless channel.is_a?(String) || channel.is_a?(Symbol)

  if env.is_a?(String)
    env = environment(env)
  end

  raise "channel '#{channel}' does not exist in environment '#{env.name}'." \
    unless env.channels.key?(channel.to_s) || channel.to_sym == :latest

  credentials = Amigrind::Config.aws_credentials(env)

  amigrind_client = Amigrind::Core::Client.new(env.aws.region, credentials)
  ec2 = Aws::EC2::Client.new(region: env.aws.region, credentials: credentials)

  image = amigrind_client.get_image_by_id(name: blueprint_name, id: id)

  tag_key = Amigrind::Core::AMIGRIND_CHANNEL_TAG % { channel_name: channel }

  info_log "clearing '#{tag_key}' on image #{image.id}..."
  ec2.delete_tags(
    resources: [ image.id ],
    tags: [
      {
        key: tag_key,
        value: nil
      }
    ]
  )
end

#with_environment(environment_name, &block) ⇒ Object



58
59
60
# File 'lib/amigrind/repo.rb', line 58

def with_environment(environment_name, &block)
  block.call(environment(environment_name))
end