dg 0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (8) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +14 -0
  4. data/README.md +10 -0
  5. data/bin/dg +23 -0
  6. data/dg.gemspec +16 -0
  7. data/lib/docker.rb +198 -0
  8. metadata +62 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bfa6c8117f605ab7db2805f81e17216c92987489
4
+ data.tar.gz: eaafc7f4ffb0ee78493790040d9bb5eec079b49b
5
+ SHA512:
6
+ metadata.gz: b5830cb101398c6699904cd09bb3d8f87711561e6efd05a3422c2cc8c3a8de803a6ca4a999868444a1954bf9fe734bb11f761c410fa879bcf1eb49e17e840460
7
+ data.tar.gz: 6acfe0496cba3c12eec562fbbcc2fe59efc9dfe9f82229838ee2a539f4405c92a24028f043ab17d0b7c4526c67b8fb56530550d6772e12b5fc92a6cb9f8fedc6
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in docker_go_tasks.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use debugger
14
+ # gem 'debugger'
data/README.md ADDED
@@ -0,0 +1,10 @@
1
+ DockerGo (DG)
2
+ =============
3
+
4
+ Provides tasks for quickly building docker and running (via fig) docker images.
5
+
6
+ Prerequisites:
7
+
8
+ - Git for version control.
9
+ - Mac or GNU/Linux environment.
10
+ - docker and fig are installed
data/bin/dg ADDED
@@ -0,0 +1,23 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.expand_path('../../lib/docker', __FILE__)
4
+
5
+ COMMANDS = %w(
6
+ -h
7
+ build
8
+ debug
9
+ deploy
10
+ help
11
+ purge
12
+ push
13
+ run
14
+ test
15
+ )
16
+
17
+ if COMMANDS.include?(ARGV.first)
18
+ Docker.send(ARGV.first.tr('-','').to_sym)
19
+ exit 0
20
+ else
21
+ STDERR.puts "You must supply a command (#{COMMANDS.join(', ')})"
22
+ exit 1
23
+ end
data/dg.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Describe your gem and declare its dependencies:
4
+ Gem::Specification.new do |s|
5
+ s.name = "dg"
6
+ s.version = '0.4'
7
+ s.authors = ["Michael Malet"]
8
+ s.email = ["michael@nervd.com"]
9
+ s.homepage = "https://github.com/shinyscorpion/dg"
10
+ s.license = "MIT"
11
+ s.summary = "Provides integration between Docker and GoCD."
12
+ s.description = File.read('README.md')
13
+
14
+ s.files = `git ls-files -z`.split("\x0")
15
+ s.executables = `git ls-files -z -- bin/*`.split("\x0").map{ |f| File.basename(f) }
16
+ end
data/lib/docker.rb ADDED
@@ -0,0 +1,198 @@
1
+ require 'pty'
2
+ require 'uri'
3
+ require 'net/http'
4
+
5
+ class Docker
6
+ MATERIAL_NAME = ENV['MATERIAL_NAME'] || 'BITBUCKET'
7
+ SUDO = !!ENV["GO_REVISION_#{MATERIAL_NAME}"]
8
+ BASEPATH = Dir.pwd
9
+ GIT_COMMIT = ENV['GO_REVISION_BITBUCKET'] || `git rev-parse HEAD`.strip
10
+
11
+ FIG_YML_PATH = "#{BASEPATH}/fig.yml"
12
+ FIG_GEN_PATH = "#{BASEPATH}/fig_gen.yml"
13
+
14
+ class << self
15
+
16
+ def build
17
+ build_docker_image_with_tag
18
+ end
19
+
20
+ def debug
21
+ generate_fig_yaml
22
+ debug_app
23
+ end
24
+
25
+ def purge
26
+ run_with_output("docker rm $(docker ps -a -q) && docker rmi $(docker images -q)")
27
+ end
28
+
29
+ def push
30
+ run_with_output("docker push #{git_image_name.tr(':',' ')}")
31
+ end
32
+
33
+ def deploy
34
+ required_envs = %w(GO_HOST GO_USER GO_PWD)
35
+ unless required_envs.reduce{ |acc, e| acc && ENV[e] }
36
+ error!(
37
+ RuntimeError.new("Environment variables {#{required_envs.join(', ')}} must be set"),
38
+ 'triggering pipeline'
39
+ )
40
+ end
41
+ deploy_stages.each do |deploy_stage|
42
+ schedule_pipeline(project_name, deploy_stage, git_image_name)
43
+ end
44
+ end
45
+
46
+ def deploy_stages
47
+ candidates = Dir['deploy-to*']
48
+ if candidates.size == 1
49
+ script = candidates.first
50
+ if File.executable?(script)
51
+ branch = ENV['GIT_BRANCH'] ||
52
+ `git symbolic-ref --short -q HEAD`.strip
53
+ return `./#{script} #{branch}`.strip.split(',')
54
+ else
55
+ error!(
56
+ RuntimeError.new(
57
+ %(Deploy-to script: "#{script}" must be executable! (e.g. chmod +x #{script}))
58
+ ),
59
+ "determining stage to deploy to"
60
+ )
61
+ end
62
+ else
63
+ error!(
64
+ RuntimeError.new(
65
+ "There must be a deploy-to* script " +
66
+ "(e.g. deploy-to.{rb|sh|js}): #{candidates.size} found"
67
+ ),
68
+ "determining stage to deploy to"
69
+ )
70
+ end
71
+ end
72
+
73
+ def run
74
+ generate_fig_yaml
75
+ run_app
76
+ end
77
+
78
+ def test
79
+ generate_fig_yaml
80
+ run_tests
81
+ end
82
+
83
+ private
84
+
85
+ def error!(e, step = "executing")
86
+ STDERR.puts "An error occurred while #{step}: #{e.message}"
87
+ exit 1
88
+ end
89
+
90
+ def run_with_output(command)
91
+ sudo_command = SUDO ? "sudo -E bash -c '#{command}'" : command
92
+ puts "Running `#{sudo_command}` in #{Dir.pwd}"
93
+ PTY.spawn(sudo_command) do |stdin, stdout, pid|
94
+ stdin.each { |line| print line } rescue Errno::EIO
95
+ Process.wait(pid)
96
+ end
97
+ status_code = $?.exitstatus
98
+
99
+ error!(RuntimeError.new("exit code was #{status_code}"), "executing #{command}") if status_code != 0
100
+ rescue PTY::ChildExited
101
+ puts "The child process exited!"
102
+ end
103
+
104
+ def fig_yml
105
+ @@fig_yml ||= File.read(FIG_YML_PATH)
106
+ rescue => e
107
+ error!(e, "reading fig.yml from #{FIG_YML_PATH}")
108
+ end
109
+
110
+ def project_name
111
+ @@project_name ||= ENV['GO_PIPELINE_NAME'] || image_name.split('/').last
112
+ end
113
+
114
+ # Infer the project name from the image specified in the fig.yml
115
+ def image_name
116
+ @@image_name ||= fig_yml.match(/\s+image: (.*)/)[1]
117
+ end
118
+
119
+ # Add the git commit hash to the image name
120
+ def git_image_name
121
+ @@git_image_name ||= "#{image_name}:#{GIT_COMMIT}"
122
+ end
123
+
124
+ def generate_fig_yaml
125
+ File.write(
126
+ FIG_GEN_PATH,
127
+ fig_yml.sub(image_name, git_image_name)
128
+ )
129
+ rescue => e
130
+ error!(e, "generating new fig.yml")
131
+ end
132
+
133
+ def build_docker_image_with_tag
134
+ run_with_output("docker build -t #{git_image_name} #{BASEPATH}")
135
+ rescue => e
136
+ error!(e, "building docker image")
137
+ end
138
+
139
+ def run_tests
140
+ run_with_output("fig -f #{FIG_GEN_PATH} run test")
141
+ rescue => e
142
+ error!(e, "running tests")
143
+ end
144
+
145
+ def run_app
146
+ run_with_output("fig -f #{FIG_GEN_PATH} up -d web")
147
+ end
148
+
149
+ def debug_app
150
+ puts "docker run -it --entrypoint=/bin/bash #{git_image_name}"
151
+ end
152
+
153
+ def schedule_pipeline(project_name, deploy_stage, image_id)
154
+ pipeline_name = "docker-#{project_name}-#{deploy_stage}"
155
+
156
+ uri = URI("https://#{ENV['GO_HOST']}/go/api/pipelines/#{pipeline_name}/schedule")
157
+ request = Net::HTTP::Post.new(uri.path)
158
+ request.basic_auth ENV['GO_USER'], ENV['GO_PWD']
159
+ request.set_form_data({ 'variables[IMAGE_ID]' => git_image_name.gsub('/','\/') })
160
+
161
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
162
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
163
+ http.ssl_version = :SSLv3
164
+ http.request(request)
165
+ end
166
+
167
+ if response.code.to_i == 202
168
+ puts response.body.strip
169
+ else
170
+ error!(
171
+ RuntimeError.new(
172
+ "response code was #{response.code}: #{response.body.strip}"
173
+ ),
174
+ "scheduling pipeline"
175
+ )
176
+ end
177
+ end
178
+
179
+ def help
180
+ puts "Usage: dg COMMAND
181
+
182
+ A helper for building, testing, and running docker images via docker & fig.
183
+
184
+ Commands:
185
+ build Build an image based on your fig.yml (tags with the project's Git commit hash)
186
+ debug Debug a previously built image (!) THIS MUST BE RUN IN A SUBSHELL: `$(dim debug)`
187
+ deploy Trigger the GoCD pipeline for this project
188
+ help Display this help text
189
+ purge Remove ALL docker containers and images (not just for this project!)
190
+ push Push the image to your docker registry
191
+ run Run the image using your fig.yml's `web` config
192
+ test Run the image using your fig.yml's `test` config
193
+ ".gsub(/^ {6}/,'')
194
+ end
195
+ alias_method :h, :help
196
+ end
197
+
198
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dg
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.4'
5
+ platform: ruby
6
+ authors:
7
+ - Michael Malet
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-12-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: |
14
+ DockerGo (DG)
15
+ =============
16
+
17
+ Provides tasks for quickly building docker and running (via fig) docker images.
18
+
19
+ Prerequisites:
20
+
21
+ - Git for version control.
22
+ - Mac or GNU/Linux environment.
23
+ - docker and fig are installed
24
+ email:
25
+ - michael@nervd.com
26
+ executables:
27
+ - dg
28
+ extensions: []
29
+ extra_rdoc_files: []
30
+ files:
31
+ - ".gitignore"
32
+ - Gemfile
33
+ - README.md
34
+ - bin/dg
35
+ - dg.gemspec
36
+ - lib/docker.rb
37
+ homepage: https://github.com/shinyscorpion/dg
38
+ licenses:
39
+ - MIT
40
+ metadata: {}
41
+ post_install_message:
42
+ rdoc_options: []
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ required_rubygems_version: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ requirements: []
56
+ rubyforge_project:
57
+ rubygems_version: 2.4.3
58
+ signing_key:
59
+ specification_version: 4
60
+ summary: Provides integration between Docker and GoCD.
61
+ test_files: []
62
+ has_rdoc: