Class: JackAndTheElasticBeanstalk::Service

Inherits:
Object
  • Object
show all
Defined in:
lib/jack_and_the_elastic_beanstalk/service.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config:, source_dir:, eb:, runner:, logger:) ⇒ Service



9
10
11
12
13
14
15
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 9

def initialize(config:, source_dir:, eb:, runner:, logger:)
  @config = config
  @source_dir = source_dir
  @eb = eb
  @runner = runner
  @logger = logger
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



3
4
5
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 3

def config
  @config
end

#ebObject (readonly)

Returns the value of attribute eb.



5
6
7
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 5

def eb
  @eb
end

#loggerObject (readonly)

Returns the value of attribute logger.



7
8
9
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 7

def logger
  @logger
end

#runnerObject (readonly)

Returns the value of attribute runner.



6
7
8
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 6

def runner
  @runner
end

#source_dirObject (readonly)

Returns the value of attribute source_dir.



4
5
6
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 4

def source_dir
  @source_dir
end

Instance Method Details

#archive(input_dir:, output_path:) ⇒ Object



103
104
105
106
107
108
109
110
111
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 103

def archive(input_dir:, output_path:)
  paths = Pathname.glob(input_dir + "**/*", File::FNM_DOTMATCH).select(&:file?)

  Zip::File.open(output_path.to_s, Zip::File::CREATE) do |zip|
    paths.each do |path|
      zip.add(path.relative_path_from(input_dir).to_s, path.to_s)
    end
  end
end

#deploy(group:, process:, archive_path:, s3_key:, label:) ⇒ Object



146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 146

def deploy(group:, process:, archive_path:, s3_key:, label:)
  upload(archive_path: archive_path, name: s3_key)
  eb.create_version(s3_bucket: config.s3_bucket, s3_key: s3_key, label: label)

  eb.environments.find {|env| env.environment_name == env_name(group: group, process: process) }.try do |env|
    env.synchronize_update do
      env.deploy(label: label)
    end

    env.ensure_version!(expected_label: label)
  end

  eb.cleanup_versions
end

#destroy(group:) ⇒ Object



161
162
163
164
165
166
167
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 161

def destroy(group:)
  logger.info("jeb::service") { "Destroying #{group} ..." }

  each_environment(group: group) do |env, _|
    env.destroy
  end
end

#each_environment(group:) ⇒ Object



169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 169

def each_environment(group:)
  if block_given?
    regexp = /\Ajeb-#{config.app_name}-#{group}-([^\-]+)\Z/

    eb.environments.each do |env|
      if env.environment_name =~ regexp
        yield env, $1
      end
    end
  else
    enum_for :each_environment, group: group
  end
end

#each_groupObject



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 183

def each_group
  if block_given?
    regexp = /\Ajeb-#{config.app_name}-(.+)-([^\-]+)\Z/

    eb.environments.group_by {|env|
      if env.environment_name =~ regexp
        $1
      end
    }.each do |group, envs|
      if group
        yield group, envs
      end
    end
  else
    enum_for :each_group
  end
end

#eb_create(target_dir:, configuration:, group:, process:, env_vars:) ⇒ Object



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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 32

def eb_create(target_dir:, configuration:, group:, process:, env_vars:)
  if eb.environments.none? {|env| env.environment_name == env_name(group: group, process: process) }
    logger.info("jeb::service") { "Creating eb environment for #{process} from #{target_dir}..." }

    commandline = ["eb", "create", env_name(group: group, process: process), "--nohang", "--scale", "1"]

    hash = config.processes(configuration)[process]

    commandline.concat(["-t", "worker"]) if config.process_type(configuration, process) == "worker"
    commandline.concat(["--region", hash["region"] || config.region])
    commandline.concat(["--platform", hash["platform"] || config.platform])
    commandline.concat(["--instance_profile", hash["instance_profile"]]) if hash["instance_profile"]
    commandline.concat(["--keyname", hash["keyname"]]) if hash["keyname"]
    commandline.concat(["--instance_type", hash["instance_type"]]) if hash["instance_type"]
    commandline.concat(["--service-role", hash["service_role"]]) if hash["service_role"]

    if hash["tags"]&.any?
      commandline.concat(["--tags", hash["tags"].each.with_object([]) do |(key, value), acc|
        acc << "#{key}=#{value}"
      end.concat(",")])
    end

    if hash["vpc"]
      vpc = hash["vpc"]

      commandline.concat(["--vpc", "--vpc.id", vpc["id"]])
      commandline.concat(["--vpc.ec2subnets", vpc["ec2subnets"].join(",")]) if vpc["ec2subnets"]&.any?
      commandline.concat(["--vpc.elbpublic"]) if vpc["elbpublic"]
      commandline.concat(["--vpc.elbsubnets", vpc["elbsubnets"].join(",")]) if vpc["elbsubnets"]&.any?
      commandline.concat(["--vpc.publicip"]) if vpc["publicip"]
      commandline.concat(["--vpc.securitygroups", vpc["securitygroups"].join(",")]) if vpc["securitygroups"]&.any?
    end

    unless env_vars.empty?
      vars = env_vars.to_a.map {|(k, v)| "#{k}=#{v}" }.join(",")
      commandline.concat(["--envvars", vars])
    end

    runner.chdir target_dir do
      runner.capture3!(*commandline)
    end

    eb.refresh
    env = eb.environments.find {|e| e.environment_name == env_name(group: group, process: process) }
    env.synchronize_update
  else
    logger.info("jeb::service") { "Environment #{env_name(group:group, process: process)} already exists..." }
  end
end

#eb_deploy(target_dir:, group:, process:) ⇒ Object



23
24
25
26
27
28
29
30
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 23

def eb_deploy(target_dir:, group:, process:)
  runner.chdir target_dir do
    runner.capture3!("eb", "deploy", env_name(group: group, process: process), "--nohang")
  end

  env = eb.environments.find {|e| e.environment_name == env_name(group: group, process: process) }
  env.synchronize_update
end

#eb_init(target_dir:) ⇒ Object



17
18
19
20
21
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 17

def eb_init(target_dir:)
  runner.chdir target_dir do
    runner.capture3!("eb", "init", config.app_name, "-r", config.region, "-p", config.platform)
  end
end

#env_name(group:, process:) ⇒ Object



82
83
84
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 82

def env_name(group:, process:)
  "jeb-#{config.app_name}-#{group}-#{process}"
end

#export_files(dest:) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 113

def export_files(dest:)
  files = if (source_dir + '.git').exist?
            runner.chdir(source_dir) do
              runner.capture3!("git", "ls-files", "-z").first.split("\x0")
            end
          else
            Pathname.glob(source_dir + '**/*').select(&:file?).map do |path|
              path.to_s.sub(/\A#{source_dir}\//, '')
            end
          end

  files.each do |f|
    logger.debug("jeb::service") { "Copying #{f} ..."}

    source_path = source_dir + f
    target_path = dest + f

    unless target_path.parent.directory?
      target_path.parent.mkpath
    end

    FileUtils.copy(source_path.to_s, target_path.to_s)
  end
end

#stage(target_dir:, process:) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 86

def stage(target_dir:, process:)
  logger.info("jeb::service") { "Staging files in #{target_dir} for #{process}" }

  ENV["JEB_PROCESS"] = process

  export_files(dest: target_dir)

  eb_extensions = target_dir + ".ebextensions"
  eb_extensions.mkpath
  config.each_config do |path, content|
    logger.debug("jeb::service") { "Writing #{path} ..." }
    (eb_extensions + path).write content
  end
ensure
  ENV.delete("JEB_PROCESS")
end

#upload(archive_path:, name:) ⇒ Object



138
139
140
141
142
143
144
# File 'lib/jack_and_the_elastic_beanstalk/service.rb', line 138

def upload(archive_path:, name:)
  logger.debug("jeb::service") { "Uploading #{archive_path} to #{config.s3_bucket}/#{name}..." }
  s3 = Aws::S3::Client.new(region: config.region)
  archive_path.open do |io|
    s3.put_object(bucket: config.s3_bucket, key: name, body: io)
  end
end