dg 0.4

Sign up to get free protection for your applications and to get access to all the features.
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: