cide 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,110 @@
1
+ require 'json'
2
+
3
+ require 'cide/docker'
4
+
5
+ module CIDE
6
+ class Runner
7
+ include CIDE::Docker
8
+
9
+ def initialize(
10
+ command: [],
11
+ env: {},
12
+ links: [],
13
+ tag: nil,
14
+ user: nil
15
+ )
16
+ fail ArgumentError, 'tag missing' unless tag
17
+
18
+ @containers = []
19
+ @id = SecureRandom.hex
20
+
21
+ @tag = tag
22
+ @env = env
23
+ @links = links
24
+ @command = command
25
+ @user = user
26
+ end
27
+
28
+ # !!!! Don't call run twice !!!!
29
+ def run!(interactive: false)
30
+ start_links!
31
+
32
+ run_options = ['--detach']
33
+
34
+ @env.each_pair do |key, value|
35
+ run_options.push '--env', [key, value].join('=')
36
+ end
37
+
38
+ @links.each do |link|
39
+ run_options.push '--link', [link.id, link.name].join(':')
40
+ end
41
+
42
+ run_options.push '--name', @id
43
+
44
+ run_options.push '--user', @user if @user
45
+
46
+ run_options.push('--interactive', '--tty') if interactive
47
+
48
+ run_options.push @tag
49
+ run_options.push(*@command)
50
+
51
+ id = docker(:run, *run_options, capture: true).strip
52
+ @containers << id
53
+ docker(:attach, id)
54
+ end
55
+
56
+ def export!(guest_dir: nil, host_dir: nil)
57
+ fail ArgumentError, 'guest export_dir missing' unless guest_dir
58
+ fail ArgumentError, 'host export_dir missing' unless host_dir
59
+
60
+ # FIXME: strip trailing slashes ?
61
+ guest_dir = File.expand_path(guest_dir, CIDE_SRC_DIR)
62
+ host_dir = File.expand_path(host_dir, Dir.pwd)
63
+
64
+ FileUtils.mkdir_p(File.dirname(host_dir))
65
+
66
+ docker :cp, [@id, guest_dir].join(':'), host_dir
67
+ end
68
+
69
+ def cleanup!(output: $stderr)
70
+ return if @containers.empty?
71
+ begin
72
+ report_containers!(output)
73
+ ensure
74
+ # Shutdown old containers
75
+ docker :rm, '--force', '--volumes', *@containers.reverse, capture: true
76
+ end
77
+ end
78
+
79
+ protected
80
+
81
+ def start_links!
82
+ @links.each do |link|
83
+ args = ['--detach']
84
+ link.env.each_pair do |key, value|
85
+ args.push('--env', [key, value].join('='))
86
+ end
87
+ args << link.image
88
+ args << link.run if link.run
89
+ link.id = docker(:run, *args, capture: true).strip
90
+ @containers << link.id
91
+ end
92
+ end
93
+
94
+ def report_containers!(output)
95
+ infos = docker(:inspect, *@containers, capture: true)
96
+
97
+ JSON.parse(infos).each do |info|
98
+ config = info['Config']
99
+ state = info['State']
100
+
101
+ next unless state['Dead'] || state['ExitCode'] > 0
102
+
103
+ output.puts "=== Failed container #{info['Id']} ==="
104
+ output.puts "Image: #{config['Image']}"
105
+ output.puts "State: #{state.inspect}"
106
+ docker(:logs, '--tail', 20, info['Id'])
107
+ end
108
+ end
109
+ end
110
+ end
@@ -1,16 +1,16 @@
1
- CIDE-BUILD 1 "JUNE 2015" cide-build "Cide Manual"
2
- =================================================
1
+ CIDE-EXEC 1 "FEBRUARY 2016" cide-exec "Cide Manual"
2
+ ===================================================
3
3
 
4
4
  NAME
5
5
  ----
6
6
 
7
- cide-build - Builds an image and executes the run script
7
+ cide-exec - Builds an image and executes the run script
8
8
 
9
9
  SYNOPSIS
10
10
  --------
11
11
 
12
- *cide build* [`-n`|`--name`=<*name*>] [`--export`|`--no-export`]
13
- [`-o`|`--export-dir`=<*path*>] [`-r`|`--run`=<*command*>]
12
+ *cide exec* [`--export`|`--no-export`] [`-o`|`--export-dir`=<*path*>]
13
+ [`--guest_export_dir`=<*path*>] [`-r`|`--run`=<*command*>]
14
14
  [`--pull`|`--no-pull`] [`-s`|`--ssh-key`=<*path*>]
15
15
 
16
16
  DESCRIPTION
@@ -28,21 +28,29 @@ CI run with isolated dependencies.
28
28
  OPTIONS
29
29
  -------
30
30
 
31
- `-n`, `--name`=<*name*>
31
+ `-n`, `-t`, `--name`=<*name*>
32
32
  Name of the built image. This can be used to differentiate between branches
33
33
  or others in a CI environment. By default the name is the basename(1) of the
34
34
  current directory.
35
35
 
36
36
  `--export`, `--no-export`
37
- Whenever to export artifacts. If `--export` is passed and the `export:`
38
- directive is set in the `cide.yml` file, artifacts from that directory are
39
- transfered back outside of the container and into the current directory.
37
+ Whether to export artifacts. If `--export` is passed and the directory to
38
+ be exported is set (either with `export_dir:` in the `cide.yml` file, or by
39
+ specifying `--guest-export-dir` on the command line) artifacts from that
40
+ directory are transfered back outside of the container (see `--export-dir`
41
+ and `--guest-export-dir`)
40
42
 
41
43
  `-o`, `--export-dir`=<*path*>
42
- By default the export directory is the same as the one given in the
43
- `export:` directive in the `cide.yml` file. It is possible to change that
44
+ Where the directory extracted from the container should be placed on the
45
+ host. By default the export directory is the same as the one given in the
46
+ `export_dir:` directive in the `cide.yml` file. It is possible to change that
44
47
  target folder outside of the container.
45
48
 
49
+ `--guest-export-dir`=<*path*>
50
+ Which directory from the container should be extracted. By default the
51
+ export directory is the same as the one specified with `--export-dir` if any,
52
+ or in the `export_dir:` directive in the `cide.yml` file otherwise.
53
+
46
54
  `-r`, `--run`=<*command*>
47
55
  Override the script to run. Usually the `run:` directive in the `cide.yml`
48
56
  is defining what to run but this could be used for a quick one-off.
@@ -0,0 +1,56 @@
1
+ CIDE-PACKAGE "FEBRUARY 2016" cide-package "Cide Manual"
2
+ =======================================================
3
+
4
+ NAME
5
+ ----
6
+
7
+ cide-package - Builds a package from the run script
8
+
9
+ SYNOPSIS
10
+ --------
11
+
12
+ *cide package* [`-n`|`-t`|`--name`=<*name*>] [`-s`|`--ssh-key`=<*path*>]
13
+ [`--package`=<*package*>] [`--upload`]
14
+ [`--set-version`]
15
+
16
+ DESCRIPTION
17
+ -----------
18
+
19
+ This tells `cide` to package a built package for you, and possibly upload it to
20
+ s3.
21
+
22
+ When invoke, cide will retrieve a previously created container (see `--name`),
23
+ perform a `cide` run, and package a given directory. The behavior is the same
24
+ as `exec` but will always export a directory, which it will upload to Amazon
25
+ s3.
26
+
27
+ OPTIONS
28
+ -------
29
+
30
+ `-n`, `-t`, `--name`
31
+ The name (tag) of the container from which to retrieve the build.
32
+
33
+ `-s`, `--ssh-key`=<*path*>
34
+ When the `use_ssh:` directive is set to true, where to get the ssh key to
35
+ inject into the container. Defaults to `~/.ssh/id_rsa`.
36
+
37
+ `--package`=<*package*>
38
+ The name of the package. The final archive will have the name
39
+ `<package>.<timestamp>.<version>.tar.gz`, where timestamp is the time at
40
+ which the packaging occured (in format `YYYY-mm-dd_HHMMSS`) and `<version>`
41
+ is the package version (see `--set-version`).
42
+
43
+ `--upload`
44
+ Whether the archive should be uploaded to Amazon s3. If the archive should be
45
+ uploaded to s3 by the packager, the s3 credentials must be provided to
46
+ `cide`. The s3 credentials must be exported as environment variables.
47
+
48
+ `--set-version`
49
+ Sets a package version. Is is solely used when naming the archive (see
50
+ `--package`). If no version is provided on the command line, a default
51
+ version name will be extracted from git (short sha).
52
+
53
+ SEE ALSO
54
+ --------
55
+
56
+ cide(1)
@@ -25,6 +25,9 @@ of the current directory's structure, builds an image with it and then runs a
25
25
  container from it that executes the specified tests. See the cide.yml(1) man
26
26
  page for the structure of that file.
27
27
 
28
+ Cide can also be used to package and upload projects after they have been
29
+ built. See cide-package(1) for more information.
30
+
28
31
  OPTIONS
29
32
  -------
30
33
 
@@ -45,11 +48,18 @@ These are global options that set the behavior of all commands.
45
48
  COMMANDS
46
49
  --------
47
50
 
48
- *cide build* [<*options*>]
51
+ *cide exec* [<*options*>]
49
52
  Builds an image and executes the run script. This is the default command
50
53
  when none is provided.
51
54
 
52
- See cide-build(1)
55
+ See cide-package(1)
56
+
57
+ *cide package* [<*options*>]
58
+ Packages a directory that resulting from a run script. Can also upload the
59
+ package to Amazon s3.
60
+
61
+ See cide-package(1)
62
+
53
63
 
54
64
  *cide clean* [<*options*>]
55
65
  Removes old containers.
@@ -91,6 +101,22 @@ https://docs.docker.com/docker/reference/commandline/cli/#environment-variables:
91
101
  *DOCKER_TLS_VERIFY*
92
102
  When set Docker uses TLS and verifies the remote.
93
103
 
104
+
105
+ The following environment variables are used by the Amazon `s3` SDK to
106
+ authenticate, and should be set by the user. See also
107
+ http://docs.aws.amazon.com/sdkforruby/api/index.html.
108
+
109
+ *AWS_ACCESS_KEY_ID*
110
+ *AWS_SECRET_ACCESS_KEY*
111
+ The Amazon key id and access key (see
112
+ http://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html)
113
+
114
+ *AWS_REGION*
115
+ The Amazon region (e.g. `us-east-1`)
116
+
117
+ *AWS_BUCKET*
118
+ Your bucket's name
119
+
94
120
  CONTRIBUTE
95
121
  ----------
96
122
 
@@ -4,7 +4,7 @@ CIDE.YML 1 "JUNE 2015" cide.yml "Cide Manual"
4
4
  NAME
5
5
  ----
6
6
 
7
- cide.yml - file format that directs the `cide build` execution
7
+ cide.yml - file format that directs the `cide exec` execution
8
8
 
9
9
  DESCRIPTION
10
10
  -----------
@@ -0,0 +1,29 @@
1
+ #!/bin/bash -e
2
+
3
+ if [[ -z $1 ]]; then
4
+ echo "Missing <TARGET>" >&2
5
+ exit 1
6
+ fi
7
+
8
+ packager_bin() {
9
+ local bin=$1
10
+ local name=$(basename "$1")
11
+ mkdir -p .packager/bin
12
+ cat <<BIN > ".packager/bin/${name}"
13
+ #!/bin/sh -e
14
+ here=\$(dirname "\$(readlink -f "\$0")")
15
+ target=\$(readlink -f "\$here/../../${bin}")
16
+ exec "\$target" "\$@"
17
+ BIN
18
+ chmod +x ".packager/bin/${name}"
19
+ }
20
+
21
+ TARGET=$1
22
+
23
+ cp -r "$PWD" "$TARGET"
24
+ cd "$TARGET"
25
+ bundle install --standalone --binstubs=binstubs --without=development test
26
+
27
+ rm -rf vendor/bundle/ruby/*/{bin,build_info,cache,doc,extensions,specifications}
28
+
29
+ packager_bin binstubs/cide
@@ -0,0 +1,2 @@
1
+ #!/bin/sh -e
2
+ bundle exec rake
@@ -1,12 +1,12 @@
1
- require "cide/build"
1
+ require "cide/config_file"
2
2
  require "stringio"
3
3
  require "ostruct"
4
4
  require "active_support/json"
5
5
 
6
- describe "CIDE::Build::Config::Loader" do
6
+ describe "CIDE::ConfigFile::Loader" do
7
7
  before do
8
- @config = CIDE::Build::Config.new
9
- @loader = CIDE::Build::ConfigLoader.new(@config)
8
+ @config = CIDE::ConfigFile.new
9
+ @loader = CIDE::ConfigFileLoader.new(@config)
10
10
  ENV['TEST1'] = 'test1'
11
11
  ENV['TEST2'] = 'test2'
12
12
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cide
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - zimbatm
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-10 00:00:00.000000000 Z
11
+ date: 2016-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -119,6 +119,7 @@ executables:
119
119
  extensions: []
120
120
  extra_rdoc_files: []
121
121
  files:
122
+ - ".dockerignore"
122
123
  - ".editorconfig"
123
124
  - ".gitignore"
124
125
  - ".nojekyll"
@@ -138,20 +139,24 @@ files:
138
139
  - docs/cide.yml.md
139
140
  - docs/sidebar.md
140
141
  - index.html
141
- - lib/cide/build.rb
142
- - lib/cide/build/config.rb
143
- - lib/cide/build/config_loader.rb
142
+ - lib/cide/builder.rb
144
143
  - lib/cide/cli.rb
144
+ - lib/cide/config_file.rb
145
+ - lib/cide/config_file_loader.rb
145
146
  - lib/cide/constants.rb
146
147
  - lib/cide/default_cide.yml
147
148
  - lib/cide/docker.rb
148
149
  - lib/cide/dockerfile_template.erb
149
- - man/cide-build.1.md
150
+ - lib/cide/runner.rb
150
151
  - man/cide-clean.1.md
151
152
  - man/cide-debug.1.md
153
+ - man/cide-exec.1.md
152
154
  - man/cide-init.1.md
155
+ - man/cide-package.1.md
153
156
  - man/cide.1.md
154
157
  - man/cide.yml.1.md
158
+ - script/build
159
+ - script/ci
155
160
  - spec/build_config_loader_spec.rb
156
161
  - spec/spec_helper.rb
157
162
  homepage: https://zimbatm.github.io/cide
@@ -1,2 +0,0 @@
1
- require 'cide/build/config'
2
- require 'cide/build/config_loader'
@@ -1,103 +0,0 @@
1
- require 'virtus'
2
-
3
- require 'erb'
4
- require 'yaml'
5
-
6
- require 'cide/build/config_loader'
7
-
8
- module CIDE
9
- module Build
10
- class Config
11
- DOCKERFILE_TEMPLATE =
12
- File.expand_path('../../dockerfile_template.erb', __FILE__)
13
-
14
- module NiceInspect
15
- def inspect
16
- out = []
17
- attributes.each_pair do |key, value|
18
- out << "#{key}=#{value.inspect}"
19
- end
20
- "<#{out.join(' ')}>"
21
- end
22
- end
23
-
24
- class FileAdd
25
- include Virtus.model(strict: true)
26
- include NiceInspect
27
- attribute :src, Array[String], default: []
28
- attribute :dest, String
29
- end
30
-
31
- class Step
32
- include Virtus.model(strict: true)
33
- include NiceInspect
34
- attribute :add, Array[FileAdd], default: []
35
- attribute :env, Hash[String, String], default: {}
36
- attribute :run, Array[String], default: []
37
- end
38
-
39
- class Link
40
- include Virtus.model
41
- include NiceInspect
42
- attribute :name, String
43
- attribute :image, String
44
- attribute :env, Hash[String, String], default: {}
45
- attribute :run, String
46
- # Container ID added after the fact
47
- attr_accessor :id
48
- end
49
-
50
- include Virtus.model(strict: true)
51
- include NiceInspect
52
- attribute :from, String, default: 'ubuntu'
53
- attribute :as_root, Step, required: false
54
- attribute :use_ssh, Boolean, default: false
55
- attribute :before, Step, required: false
56
- attribute :env, Hash[String, String], default: {}
57
- attribute :export_dir, String, required: false
58
- attribute :links, Array[Link], default: []
59
- attribute :run, Array[String], default: ['script/ci']
60
-
61
- attr_reader :warnings, :errors
62
-
63
- def initialize(*)
64
- super
65
- @warnings = []
66
- @errors = []
67
- end
68
-
69
- def to_dockerfile
70
- ERB.new(File.read(DOCKERFILE_TEMPLATE), nil, '<>-').result(binding)
71
- end
72
-
73
- def self.load(dir = Dir.pwd, output = $stderr)
74
- file_path = find_config(dir)
75
- load_file(file_path, output)
76
- end
77
-
78
- def self.load_file(file_path, output = $stderr)
79
- obj = new
80
- loader = ConfigLoader.new(obj)
81
- loader.load YAML.load_file(file_path)
82
-
83
- obj.warnings.each do |warn|
84
- output.puts "WARN: #{warn}"
85
- end
86
-
87
- obj.errors.each do |error|
88
- output.puts "ERROR: #{error}"
89
- end
90
-
91
- return obj if obj.errors.empty?
92
- nil
93
- end
94
-
95
- def self.find_config(dir)
96
- paths = CONFIG_FILES.map { |name| File.expand_path(name, dir) }
97
- paths
98
- .find { |path| File.exist?(path) } ||
99
- fail("Config not found among these paths: #{paths.inspect}")
100
- end
101
- end
102
- end
103
- end