cyclid 0.3.0 → 0.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e7112455a4780d7e09049b9a7e248d41e70e4558
4
- data.tar.gz: 5e7423b5c082b494a05d98ce46d87f1a72540111
3
+ metadata.gz: ea995b9c7270ae9d3e38e97ad81397ceb4b73e13
4
+ data.tar.gz: 7642bb2b0a8703a0199e092858091de720d9bb19
5
5
  SHA512:
6
- metadata.gz: 48fedf1d7150d25fa45787d1e47dc07568488f92151d3237440ecc69d6f71586edc4687eaad16d706758295905d4bda58b860e72422821e0df6462a994f40f92
7
- data.tar.gz: a95452bf58313dec14d44e8c9c277c9e42c7d0222dd7ed453bd0f730121b2ee5fdf994c827811a4e2c731dc5e05aae84594466b029b523613e4012bf289e2d49
6
+ metadata.gz: b4e2f3529858bdba00c9be839fff1c6a0a7091355abdf7ec002781c44d0acad9764f37b39f1eb322ea0fe63f5c9141a536cd34dea6126252f0bd8fdcf1464717
7
+ data.tar.gz: f3e00484f2d3491f56424612bc317b178b936109403ccbca9f802899b62fc5d69f9ceeff8f8720d02771209345c6883af60536749aa0f38d021f38de2feff2b1
data/README.md CHANGED
@@ -4,7 +4,7 @@ Cyclid
4
4
 
5
5
  See http://docs.cyclid.io/en/latest/ for full documentation, including [installation instructions](http://docs.cyclid.io/en/latest/server.html#installation).
6
6
 
7
- # Developement
7
+ # Development
8
8
 
9
9
  Cyclid is an Open Source project and we welcome contributions. These instructions will help you get your development environment set up to develop & test Cyclid.
10
10
 
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 2016, 2017 Liqwyd Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'nokogiri'
17
+
18
+ # Top level module for the core Cyclid code.
19
+ module Cyclid
20
+ # Module for the Cyclid API
21
+ module API
22
+ # Module for Cyclid Plugins
23
+ module Plugins
24
+ # Cobertura (& compatible) coverage reader plugin
25
+ class Cobertura < Action
26
+ def initialize(args = {})
27
+ args.symbolize_keys!
28
+
29
+ # There must be the path to the coverage report..
30
+ raise 'a Cobertura action requires a path' unless args.include? :path
31
+
32
+ @path = args[:path]
33
+ end
34
+
35
+ def perform(log)
36
+ # Retrieve the Cobertura XML report
37
+ report = StringIO.new
38
+ @transport.download(report, @path ** @ctx)
39
+
40
+ # Parse the report and extract the line & branch coverage.
41
+ xml = Nokogiri.parse(report.string)
42
+ coverage = xml.xpath('//coverage')
43
+ line_rate = coverage.attr('line-rate').value.to_f
44
+ branch_rate = coverage.attr('branch-rate').value.to_f
45
+
46
+ # Coverage is given as a fraction, so convert it to a percentage.
47
+ #
48
+ # Cobertura can produce oddly specific coverage metrics, so round it
49
+ # to only 2 decimal points...
50
+ line_rate_pct = (line_rate * 100).round(2)
51
+ branch_rate_pct = (branch_rate * 100).round(2)
52
+
53
+ log.write "Cobertura coverage line rate is #{line_rate_pct}%, " \
54
+ "branch rate is #{branch_rate_pct}%\n"
55
+
56
+ @ctx[:cobertura_line_rate] = "#{line_rate_pct}%"
57
+ @ctx[:cobertura_branch_rate] = "#{branch_rate_pct}%"
58
+
59
+ return [true, 0]
60
+ rescue StandardError => ex
61
+ log.write "Failed to read Cobertura coverage report: #{ex}"
62
+
63
+ return [false, 0]
64
+ end
65
+
66
+ # Register this plugin
67
+ register_plugin 'cobertura'
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 2016, 2017 Liqwyd Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ # Top level module for the core Cyclid code.
17
+ module Cyclid
18
+ # Module for the Cyclid API
19
+ module API
20
+ # Module for Cyclid Plugins
21
+ module Plugins
22
+ # Simplecov coverage reader plugin
23
+ class Simplecov < Action
24
+ def initialize(args = {})
25
+ args.symbolize_keys!
26
+
27
+ # There must be the path to the coverage report..
28
+ raise 'a simplecov action requires a path' unless args.include? :path
29
+
30
+ @path = args[:path]
31
+ end
32
+
33
+ def perform(log)
34
+ # Retrieve the Simplecov JSON report
35
+ report = StringIO.new
36
+ @transport.download(report, @path ** @ctx)
37
+
38
+ # Parse the report and extract the total coverage percentage;
39
+ # Simplecov can produce oddly specific coverage metrics, so round it
40
+ # to only 2 decimal points...
41
+ coverage = JSON.parse(report.string)
42
+ covered_percent = coverage['metrics']['covered_percent'].round(2)
43
+
44
+ log.write "Simplecov coverage is #{covered_percent}%\n"
45
+ @ctx[:simplecov_coverage] = "#{covered_percent}%"
46
+
47
+ return [true, 0]
48
+ rescue StandardError => ex
49
+ log.write "Failed to read Simplecov coverage report: #{ex}"
50
+
51
+ return [false, 0]
52
+ end
53
+
54
+ # Register this plugin
55
+ register_plugin 'simplecov'
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+ # Licensed under the Apache License, Version 2.0 (the "License");
3
+ # you may not use this file except in compliance with the License.
4
+ # You may obtain a copy of the License at
5
+ #
6
+ # http://www.apache.org/licenses/LICENSE-2.0
7
+ #
8
+ # Unless required by applicable law or agreed to in writing, software
9
+ # distributed under the License is distributed on an "AS IS" BASIS,
10
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ # See the License for the specific language governing permissions and
12
+ # limitations under the License.
13
+
14
+ require 'docker'
15
+ require_rel '../helpers/docker'
16
+
17
+ # Top level module for the core Cyclid code
18
+ module Cyclid
19
+ # Module for the Cyclid API
20
+ module API
21
+ # Module for Cyclid plugins
22
+ module Plugins
23
+ # Docker build host
24
+ class DockerHost < BuildHost
25
+ # Docker is the only acceptable transport
26
+ def transports
27
+ ['dockerapi']
28
+ end
29
+ end
30
+
31
+ # Docker builder, uses the Docker API to create a build host container
32
+ class Docker < Builder
33
+ include Cyclid::API::Plugins::Helpers::Docker
34
+
35
+ def initialize
36
+ @config = load_docker_config(
37
+ Cyclid.config.plugins
38
+ )
39
+ ::Docker.url = @config[:api]
40
+ end
41
+
42
+ # Create and return a build host
43
+ def get(args = {})
44
+ args.symbolize_keys!
45
+
46
+ Cyclid.logger.debug "docker: args=#{args}"
47
+
48
+ # If there is one, split the 'os' into a 'distro' and 'release'
49
+ if args.key? :os
50
+ match = args[:os].match(/\A(\w*)_(.*)\Z/)
51
+ distro = match[1] if match
52
+ release = match[2] if match
53
+ else
54
+ # No OS was specified; use the default
55
+ # XXX Defaults should be configurable
56
+ distro = 'ubuntu'
57
+ release = 'trusty'
58
+ end
59
+
60
+ # Find the image for the given distribution & release
61
+ image_alias = "#{distro}:#{release}"
62
+ Cyclid.logger.debug "image_alias=#{image_alias}"
63
+
64
+ # Create a new instance
65
+ name = create_name
66
+ container = create_container(name, image_alias)
67
+
68
+ Cyclid.logger.debug "container=#{container}"
69
+
70
+ # Create a buildhost from the container details
71
+ DockerHost.new(
72
+ host: container.id,
73
+ name: name,
74
+ username: 'root',
75
+ workspace: '/root',
76
+ distro: distro,
77
+ release: release
78
+ )
79
+ end
80
+
81
+ # Destroy the container when done
82
+ def release(_transport, buildhost)
83
+ container = get_container(buildhost[:host])
84
+ container.delete(force: true)
85
+ end
86
+
87
+ # Register this plugin
88
+ register_plugin 'docker'
89
+
90
+ private
91
+
92
+ # Get a unique name for the container
93
+ def create_name
94
+ base = @config[:instance_name]
95
+ "#{base}-#{SecureRandom.hex(16)}"
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -144,7 +144,9 @@ module Cyclid
144
144
 
145
145
  match = image.name.match(/^#{distro}-((\d*)-(.*)-v.*$|(\d*)-v.*$)/)
146
146
  next unless match
147
- next unless match[2] == release or match[3] == release
147
+ next unless match[2] == release or
148
+ match[3] == release or
149
+ match[4] == release
148
150
 
149
151
  # Found one
150
152
  Cyclid.logger.info "found image #{image.name} for #{distro}:#{release}"
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+ # Top level module for the core Cyclid code.
3
+ module Cyclid
4
+ # Module for the Cyclid API
5
+ module API
6
+ # Module for Cyclid Plugins
7
+ module Plugins
8
+ # Module for helper methods
9
+ module Helpers
10
+ # Module for Docker related bits within Cyclid
11
+ module Docker
12
+ # Load the config for the docker builder
13
+ def load_docker_config(config)
14
+ config.symbolize_keys!
15
+
16
+ docker_config = config[:docker] || {}
17
+ Cyclid.logger.debug "docker: config=#{docker_config}"
18
+
19
+ docker_config[:api] = 'unix:///var/run/docker.sock' \
20
+ unless docker_config.key? :api
21
+ docker_config[:instance_name] = 'cyclid-build' \
22
+ unless docker_config.key? :instance_name
23
+
24
+ docker_config
25
+ end
26
+
27
+ # Actually create the container
28
+ def create_container(name, image)
29
+ # Pull a suitable image
30
+ Cyclid.logger.debug "Creating image '#{image}'"
31
+ ::Docker::Image.create('fromImage' => image)
32
+
33
+ # Create the container
34
+ # XXX How do we (reliably) know what to run? /sbin/init is a good
35
+ # guess but not bullet proof
36
+ Cyclid.logger.debug "Creating container '#{name}'"
37
+ container = ::Docker::Container.create('Name' => name,
38
+ 'Image' => image,
39
+ 'Cmd' => ['/sbin/init'])
40
+ container.start
41
+
42
+ return container
43
+ end
44
+
45
+ # Get information about a container
46
+ def get_container(id)
47
+ ::Docker::Container.get(id)
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 2017, 2016 Liqwyd Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require_relative 'redhat/helpers'
17
+
18
+ # Top level module for the core Cyclid code.
19
+ module Cyclid
20
+ # Module for the Cyclid API
21
+ module API
22
+ # Module for Cyclid Plugins
23
+ module Plugins
24
+ # CentOS provisioner
25
+ class Centos < Provisioner
26
+ def initialize
27
+ @quiet = true
28
+ end
29
+
30
+ # Prepare a CentOS based build host
31
+ def prepare(transport, buildhost, env = {})
32
+ release = buildhost[:release].to_i
33
+
34
+ Cyclid.logger.debug 'is Centos'
35
+ if release >= 6
36
+ Cyclid.logger.debug 'is >= 6'
37
+ prepare_redhat(transport, env)
38
+ else
39
+ Cyclid.logger.debug 'is < 5'
40
+ prepare_redhat_5(transport, env)
41
+ end
42
+ end
43
+
44
+ # Register this plugin
45
+ register_plugin 'centos'
46
+
47
+ include Helpers::Redhat
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 2017, 2016 Liqwyd Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require_relative 'redhat/helpers'
17
+
18
+ # Top level module for the core Cyclid code.
19
+ module Cyclid
20
+ # Module for the Cyclid API
21
+ module API
22
+ # Module for Cyclid Plugins
23
+ module Plugins
24
+ # Fedora provisioner
25
+ class Fedora < Provisioner
26
+ def initialize
27
+ @quiet = true
28
+ end
29
+
30
+ # Prepare a Fedora based build host
31
+ def prepare(transport, buildhost, env = {})
32
+ release = buildhost[:release].to_i
33
+
34
+ Cyclid.logger.debug 'is Fedora'
35
+ if release >= 22
36
+ Cyclid.logger.debug 'is >= 22'
37
+ prepare_fedora_dnf(transport, env)
38
+ else
39
+ Cyclid.logger.debug 'is < 22'
40
+ prepare_fedora_yum(transport, env)
41
+ end
42
+ end
43
+
44
+ # Register this plugin
45
+ register_plugin 'fedora'
46
+
47
+ include Helpers::Redhat
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,180 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 2017, 2016 Liqwyd Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ # Top level module for the core Cyclid code.
17
+ module Cyclid
18
+ # Module for the Cyclid API
19
+ module API
20
+ # Module for Cyclid Plugins
21
+ module Plugins
22
+ # Module for helper methods
23
+ module Helpers
24
+ # Redhatish provisioner helper methods
25
+ module Redhat
26
+ # Insert the --quiet flag if required
27
+ def quiet
28
+ @quiet ? '-q' : ''
29
+ end
30
+
31
+ # Install the yum-utils package
32
+ def install_yum_utils(transport)
33
+ transport.exec 'yum install -q -y yum-utils'
34
+ end
35
+
36
+ # Import a signing key with RPM
37
+ def import_signing_key(transport, key_url)
38
+ transport.exec("rpm #{quiet} --import #{key_url}") \
39
+ end
40
+
41
+ # Install a package group with yum
42
+ def yum_groupinstall(transport, groups)
43
+ grouplist = groups.map{ |g| "\"#{g}\"" }.join(' ')
44
+ transport.exec "yum groupinstall #{quiet} -y #{grouplist}"
45
+ end
46
+
47
+ # Install a list of packages with yum
48
+ def yum_install(transport, packages)
49
+ transport.exec "yum install #{quiet} -y #{packages.join(' ')}"
50
+ end
51
+
52
+ # Add a repository with yum-config-manager
53
+ def yum_add_repo(transport, url)
54
+ transport.exec("yum-config-manager #{quiet} --add-repo #{url}")
55
+ end
56
+
57
+ # Use DNF to configure & install Fedora
58
+ def prepare_fedora_dnf(transport, env)
59
+ Cyclid.logger.debug 'using DNF'
60
+
61
+ if env.key? :repos
62
+ # We need the config-manager plugin
63
+ transport.exec("dnf install #{quiet} -y 'dnf-command(config-manager)'")
64
+
65
+ env[:repos].each do |repo|
66
+ next unless repo.key? :url
67
+
68
+ # If there's a key, install it
69
+ import_signing_key(transport, repo[:key_url]) \
70
+ if repo.key? :key_url
71
+
72
+ if repo[:url] =~ /\.rpm$/
73
+ # If the URL is an RPM just install it
74
+ transport.exec("dnf install #{quiet} -y #{repo[:url]}")
75
+ else
76
+ # Not an RPM? Let's hope it's a repo file
77
+ transport.exec("dnf config-manager #{quiet} --add-repo #{repo[:url]}")
78
+ end
79
+ end
80
+ end
81
+
82
+ if env.key? :groups
83
+ groups = env[:groups].map{ |g| "\"#{g}\"" }.join(' ')
84
+ transport.exec "dnf groups install #{quiet} -y #{groups}"
85
+ end
86
+
87
+ transport.exec "dnf install #{quiet} -y #{env[:packages].join(' ')}" \
88
+ if env.key? :packages
89
+ end
90
+
91
+ # Use YUM to configure & install Fedora
92
+ def prepare_fedora_yum(transport, env)
93
+ Cyclid.logger.debug 'using YUM'
94
+
95
+ if env.key? :repos
96
+ # We'll need yum-utils for yum-config-manager
97
+ install_yum_utils(transport)
98
+
99
+ env[:repos].each do |repo|
100
+ next unless repo.key? :url
101
+
102
+ # If there's a key, install it
103
+ import_signing_key(transport, repo[:key_url]) \
104
+ if repo.key? :key_url
105
+
106
+ if repo[:url] =~ /\.rpm$/
107
+ # If the URL is an RPM just install it
108
+ transport.exec("yum install #{quiet} -y --nogpgcheck #{repo[:url]}")
109
+ else
110
+ # Not an RPM? Let's hope it's a repo file
111
+ yum_add_repo(transport, repo[:url])
112
+ end
113
+ end
114
+ end
115
+
116
+ yum_groupinstall(transport, env[:groups]) \
117
+ if env.key? :groups
118
+
119
+ yum_install(transport, env[:packages]) \
120
+ if env.key? :packages
121
+ end
122
+
123
+ # Use YUM to configure & install a Redhat-like (RHEL, CentOS etc.)
124
+ def prepare_redhat(transport, env)
125
+ Cyclid.logger.debug 'using YUM'
126
+
127
+ if env.key? :repos
128
+ # We'll need yum-utils for yum-config-manager
129
+ install_yum_utils(transport)
130
+
131
+ env[:repos].each do |repo|
132
+ next unless repo.key? :url
133
+
134
+ # If there's a key, install it
135
+ import_signing_key(transport, repo[:key_url]) \
136
+ if repo.key? :key_url
137
+
138
+ if repo[:url] =~ /\.rpm$/
139
+ # If the URL is an RPM just install it
140
+ transport.exec("yum localinstall #{quiet} -y --nogpgcheck #{repo[:url]}")
141
+ else
142
+ # Not an RPM? Let's hope it's a repo file
143
+ yum_add_repo(transport, repo[:url])
144
+ end
145
+ end
146
+ end
147
+
148
+ yum_groupinstall(transport, env[:groups]) \
149
+ if env.key? :groups
150
+
151
+ yum_install(transport, env[:packages]) \
152
+ if env.key? :packages
153
+ end
154
+
155
+ # Use YUM & RPM to configure & install a Redhat-like (RHEL, CentOS etc.)
156
+ def prepare_redhat_5(transport, env)
157
+ if env.key? :repos
158
+ env[:repos].each do |repo|
159
+ next unless repo.key? :url
160
+
161
+ # If there's a key, install it
162
+ import_signing_key(transport, repo[:key_url]) \
163
+ if repo.key? :key_url
164
+
165
+ # Assume the URL is an RPM
166
+ transport.exec("rpm -U #{quiet} #{repo[:url]}")
167
+ end
168
+ end
169
+
170
+ yum_groupinstall(transport, env[:groups]) \
171
+ if env.key? :groups
172
+
173
+ yum_install(transport, env[:packages]) \
174
+ if env.key? :packages
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,51 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 2017, 2016 Liqwyd Ltd.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require_relative 'redhat/helpers'
17
+
18
+ # Top level module for the core Cyclid code.
19
+ module Cyclid
20
+ # Module for the Cyclid API
21
+ module API
22
+ # Module for Cyclid Plugins
23
+ module Plugins
24
+ # RHEL provisioner
25
+ class RHEL < Provisioner
26
+ def initialize
27
+ @quiet = true
28
+ end
29
+
30
+ # Prepare a RHEL based build host
31
+ def prepare(transport, buildhost, env = {})
32
+ release = buildhost[:release].to_i
33
+
34
+ Cyclid.logger.debug 'is RHEL'
35
+ if release >= 6
36
+ Cyclid.logger.debug 'is >= 6'
37
+ prepare_redhat(transport, env)
38
+ else
39
+ Cyclid.logger.debug 'is < 5'
40
+ prepare_redhat_5(transport, env)
41
+ end
42
+ end
43
+
44
+ # Register this plugin
45
+ register_plugin 'rhel'
46
+
47
+ include Helpers::Redhat
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require_rel '../helpers/docker'
16
+
17
+ # Top level module for the core Cyclid code.
18
+ module Cyclid
19
+ # Module for the Cyclid API
20
+ module API
21
+ # Module for Cyclid Plugins
22
+ module Plugins
23
+ # Docker based transport
24
+ class DockerApi < Transport
25
+ include Cyclid::API::Plugins::Helpers::Docker
26
+
27
+ attr_reader :exit_code
28
+
29
+ def initialize(args = {})
30
+ args.symbolize_keys!
31
+
32
+ Cyclid.logger.debug "Docker Transport: args=#{args}"
33
+
34
+ # Configure Docker
35
+ config = load_docker_config(
36
+ Cyclid.config.plugins
37
+ )
38
+ ::Docker.url = config[:api]
39
+
40
+ # Container name & a log target are required
41
+ return false unless args.include?(:host) && \
42
+ args.include?(:log)
43
+
44
+ @container = get_container(args[:host])
45
+ @log = args[:log]
46
+
47
+ ctx = args[:ctx]
48
+ @username = ctx[:username]
49
+ end
50
+
51
+ # Execute a command via the Docker API
52
+ def exec(cmd, path = nil)
53
+ command = build_command(cmd, path, @env)
54
+ Cyclid.logger.debug "command=#{command}"
55
+ result = @container.exec(command, wait: 300) do |_stream, chunk|
56
+ @log.write chunk
57
+ end
58
+ @exit_code = result[2]
59
+ @exit_code.zero? ? true : false
60
+ end
61
+
62
+ # Copy data from local IO object to a remote file
63
+ def upload(io, path)
64
+ @container.store_file(path, io.read)
65
+ end
66
+
67
+ # Copy data from remote file to local IO
68
+ def download(io, path)
69
+ result = @container.read_file(path)
70
+ io.write(result)
71
+ end
72
+
73
+ register_plugin('dockerapi')
74
+
75
+ private
76
+
77
+ def build_command(cmd, path = nil, env = {})
78
+ command = []
79
+ if env
80
+ vars = env.map do |k, value|
81
+ key = k.upcase
82
+ key.gsub!(/\s/, '_')
83
+ "export #{key}=\"#{value}\""
84
+ end
85
+ command << vars.join(';')
86
+ end
87
+
88
+ command << "cd #{path}" if path
89
+ command << if @username == 'root'
90
+ cmd
91
+ else
92
+ "sudo -E #{cmd}"
93
+ end
94
+ ['sh', '-l', '-c', command.join(';')]
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Cyclid
3
3
  module Api
4
- VERSION = '0.3.0'
4
+ VERSION = '0.3.1'
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cyclid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kristian Van Der Vliet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-02-28 00:00:00.000000000 Z
11
+ date: 2017-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -346,6 +346,20 @@ dependencies:
346
346
  - - "~>"
347
347
  - !ruby/object:Gem::Version
348
348
  version: 0.8.6
349
+ - !ruby/object:Gem::Dependency
350
+ name: docker-api
351
+ requirement: !ruby/object:Gem::Requirement
352
+ requirements:
353
+ - - "~>"
354
+ - !ruby/object:Gem::Version
355
+ version: '1.33'
356
+ type: :runtime
357
+ prerelease: false
358
+ version_requirements: !ruby/object:Gem::Requirement
359
+ requirements:
360
+ - - "~>"
361
+ - !ruby/object:Gem::Version
362
+ version: '1.33'
349
363
  description: The Cyclid CI system
350
364
  email: contact@cyclid.io
351
365
  executables:
@@ -392,12 +406,14 @@ files:
392
406
  - app/cyclid/plugin_registry.rb
393
407
  - app/cyclid/plugins.rb
394
408
  - app/cyclid/plugins/action.rb
409
+ - app/cyclid/plugins/action/cobertura.rb
395
410
  - app/cyclid/plugins/action/command.rb
396
411
  - app/cyclid/plugins/action/email.rb
397
412
  - app/cyclid/plugins/action/email/html.erb
398
413
  - app/cyclid/plugins/action/email/text.erb
399
414
  - app/cyclid/plugins/action/log.rb
400
415
  - app/cyclid/plugins/action/script.rb
416
+ - app/cyclid/plugins/action/simplecov.rb
401
417
  - app/cyclid/plugins/action/slack.rb
402
418
  - app/cyclid/plugins/action/slack/note.erb
403
419
  - app/cyclid/plugins/api.rb
@@ -411,15 +427,22 @@ files:
411
427
  - app/cyclid/plugins/api/github/pull_request.rb
412
428
  - app/cyclid/plugins/api/github/push.rb
413
429
  - app/cyclid/plugins/builder.rb
430
+ - app/cyclid/plugins/builder/docker.rb
414
431
  - app/cyclid/plugins/builder/google.rb
415
432
  - app/cyclid/plugins/dispatcher.rb
416
433
  - app/cyclid/plugins/dispatcher/local.rb
434
+ - app/cyclid/plugins/helpers/docker.rb
417
435
  - app/cyclid/plugins/provisioner.rb
436
+ - app/cyclid/plugins/provisioner/centos.rb
418
437
  - app/cyclid/plugins/provisioner/debian.rb
438
+ - app/cyclid/plugins/provisioner/fedora.rb
439
+ - app/cyclid/plugins/provisioner/redhat/helpers.rb
440
+ - app/cyclid/plugins/provisioner/rhel.rb
419
441
  - app/cyclid/plugins/provisioner/ubuntu.rb
420
442
  - app/cyclid/plugins/source.rb
421
443
  - app/cyclid/plugins/source/git.rb
422
444
  - app/cyclid/plugins/transport.rb
445
+ - app/cyclid/plugins/transport/dockerapi.rb
423
446
  - app/cyclid/plugins/transport/ssh.rb
424
447
  - app/cyclid/sinatra/api_helpers.rb
425
448
  - app/cyclid/sinatra/auth_helpers.rb