cyclid 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/app/cyclid.rb +6 -0
  3. data/app/cyclid/controllers/organizations/job.rb +5 -4
  4. data/app/cyclid/controllers/plugins.rb +41 -0
  5. data/app/cyclid/job/helpers.rb +20 -2
  6. data/app/cyclid/job/job.rb +1 -4
  7. data/app/cyclid/job/stage.rb +2 -0
  8. data/app/cyclid/plugins.rb +30 -0
  9. data/app/cyclid/plugins/action/cobertura.rb +8 -0
  10. data/app/cyclid/plugins/action/command.rb +12 -3
  11. data/app/cyclid/plugins/action/email.rb +8 -0
  12. data/app/cyclid/plugins/action/log.rb +8 -0
  13. data/app/cyclid/plugins/action/script.rb +11 -4
  14. data/app/cyclid/plugins/action/simplecov.rb +8 -0
  15. data/app/cyclid/plugins/action/slack.rb +8 -0
  16. data/app/cyclid/plugins/api/github.rb +8 -0
  17. data/app/cyclid/plugins/api/github/pull_request.rb +17 -0
  18. data/app/cyclid/plugins/api/github/push.rb +17 -0
  19. data/app/cyclid/plugins/builder/docker.rb +8 -0
  20. data/app/cyclid/plugins/builder/google.rb +9 -1
  21. data/app/cyclid/plugins/dispatcher/local.rb +13 -2
  22. data/app/cyclid/plugins/provisioner/centos.rb +8 -0
  23. data/app/cyclid/plugins/provisioner/debian.rb +26 -10
  24. data/app/cyclid/plugins/provisioner/fedora.rb +8 -0
  25. data/app/cyclid/plugins/provisioner/redhat/helpers.rb +14 -13
  26. data/app/cyclid/plugins/provisioner/rhel.rb +8 -0
  27. data/app/cyclid/plugins/provisioner/ubuntu.rb +28 -12
  28. data/app/cyclid/plugins/source/git.rb +11 -3
  29. data/app/cyclid/plugins/transport.rb +1 -1
  30. data/app/cyclid/plugins/transport/dockerapi.rb +17 -4
  31. data/app/cyclid/plugins/transport/ssh.rb +17 -4
  32. data/lib/cyclid/version.rb +1 -1
  33. metadata +3 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a6d5c64f60ead996640a63f571a67236cbcc6185
4
- data.tar.gz: 478f7805d7e8153aa1d98a55da62f52d8543f504
3
+ metadata.gz: 94bc08b9bc09f947dc23c30549b14fd7a8ab3c36
4
+ data.tar.gz: 1f26f26ee185b9fcc8e1fd62231cc21fdb9a4e7d
5
5
  SHA512:
6
- metadata.gz: d9aaeaa77e2f3d9c2c8f0cac5220e4c6a52b95411d8d7123a28b08255d4aa290276da0682c8e12cc6f93bd2c3682be398bb7ef8f5ac7654d5986a18a36bb4bb2
7
- data.tar.gz: 31b39a88162dfb9998c65410dae99984bd68b0213484648b5bf2ec699648e5d8f2b17f7cf22dcd0fedb1098fef8444658771d70928732f3ac7b66332f4187fe8
6
+ metadata.gz: 4d26a3198eca4c25a099274aa518b388594005e18ad8702e652803976f22a3f8b316e2cd60e1d98e1f1096b0948538e30281060ca693b0318ea4d72fe9ec97a8
7
+ data.tar.gz: fa4f4e04485036074c143baad158684840c7ff58edac9b0d7ec2e3b490133b6803e0c09c57e019113039731c9f1664b38c5035d21acacc05f31bb41531b7f7ec
@@ -36,6 +36,12 @@ module Cyclid
36
36
  else
37
37
  Logger.new(Cyclid.config.log)
38
38
  end
39
+
40
+ original_formatter = Logger::Formatter.new
41
+ Cyclid.logger.formatter = proc { |severity, datetime, progname, msg|
42
+ original_formatter.call(severity, datetime, progname, "#{Thread.current.object_id}: #{msg}")
43
+ }
44
+
39
45
  rescue StandardError => ex
40
46
  abort "Failed to initialize: #{ex}"
41
47
  end
@@ -104,6 +104,7 @@ module Cyclid
104
104
  # @private
105
105
  def self.registered(app)
106
106
  include Errors::HTTPErrors
107
+ include Exceptions
107
108
  include Constants::JobStatus
108
109
 
109
110
  # Return a list of jobs
@@ -180,12 +181,12 @@ module Cyclid
180
181
  payload = parse_request_body
181
182
  Cyclid.logger.debug payload
182
183
 
183
- halt_with_json_response(400, INVALID_JOB, 'invalid job definition') \
184
- unless payload.key? 'sequence' and \
185
- payload.key? 'environment'
186
-
187
184
  begin
188
185
  job_id = job_from_definition(payload)
186
+ rescue NotFoundError => ex
187
+ halt_with_json_response(404, INVALID_ORG, ex.to_s)
188
+ rescue InvalidObjectError => ex
189
+ halt_with_json_response(400, INVALID_JOB, ex.to_s)
189
190
  rescue StandardError => ex
190
191
  halt_with_json_response(500, INVALID_JOB, "job failed: #{ex}")
191
192
  end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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 all of the core Cyclid code.
17
+ module Cyclid
18
+ # Module for the Cyclid API
19
+ module API
20
+ # API endpoints for plugins information
21
+ # @api REST
22
+ class PluginController < ControllerBase
23
+ include Errors::HTTPErrors
24
+
25
+ # Return plugin metadata
26
+ get '/plugins' do
27
+ authorized_for!(params[:name], Operations::READ)
28
+
29
+ metadata = []
30
+ Cyclid.plugins.all.each do |plugin|
31
+ metadata << plugin.metadata
32
+ end
33
+
34
+ return metadata.to_json
35
+ end
36
+ end
37
+
38
+ # Register this controller
39
+ Cyclid.controllers << PluginController
40
+ end
41
+ end
@@ -13,6 +13,8 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ require 'cyclid/linter'
17
+
16
18
  # Top level module for the core Cyclid code.
17
19
  module Cyclid
18
20
  # Module for the Cyclid API
@@ -21,15 +23,29 @@ module Cyclid
21
23
  module Job
22
24
  # Useful methods for dealing with Jobs
23
25
  module Helpers
26
+ include Cyclid::API::Exceptions
27
+
24
28
  # Create & dispatch a Job from the job definition
25
29
  def job_from_definition(definition, callback = nil, context = {})
30
+ # Job definition is a hash (converted from JSON or YAML)
31
+ definition.symbolize_keys!
32
+
26
33
  # This function will only ever be called from a Sinatra context
27
34
  org = Organization.find_by(name: params[:name])
28
- halt_with_json_response(404, INVALID_ORG, 'organization does not exist') \
35
+ raise NotFoundError, 'organization does not exist' \
29
36
  if org.nil?
30
37
 
38
+ # Lint the job and reject if there are errors
39
+ verifier = Cyclid::Linter::Verifier.new
40
+ verifier.verify(definition)
41
+
42
+ raise InvalidObjectError, 'job definition has errors' \
43
+ unless verifier.status.errors.zero?
44
+
31
45
  # Create a new JobRecord
32
46
  job_record = JobRecord.new
47
+ job_record.job_name = definition[:name]
48
+ job_record.job_version = definition[:version] || '1.0.0'
33
49
  job_record.started = Time.now.to_s
34
50
  job_record.status = Constants::JobStatus::NEW
35
51
  job_record.save!
@@ -50,13 +66,15 @@ module Cyclid
50
66
  job_id = Cyclid.dispatcher.dispatch(job, job_record, callback)
51
67
  rescue StandardError => ex
52
68
  Cyclid.logger.error "job dispatch failed: #{ex}"
69
+ Cyclid.logger.debug ex.backtrace.join "\n"
53
70
 
54
71
  # We couldn't dispatch the job; record the failure
55
72
  job_record.status = Constants::JobStatus::FAILED
56
73
  job_record.ended = Time.now.to_s
57
74
  job_record.save!
58
75
 
59
- raise
76
+ # Re-raise something useful
77
+ raise InternalError, "job dispatch failed: #{ex}"
60
78
  end
61
79
 
62
80
  return job_id
@@ -25,15 +25,12 @@ module Cyclid
25
25
  attr_reader :name, :version
26
26
 
27
27
  def initialize(job, context, org)
28
- # Job is a hash (converted from JSON or YAML)
29
- job.symbolize_keys!
30
-
31
28
  @name = job[:name]
32
29
  @version = job[:version] || '1.0.0'
33
30
 
34
31
  @context = context
35
32
  @organization = org.name
36
- @environment = job[:environment]
33
+ @environment = job[:environment] || {}
37
34
  @sources = job[:sources] || []
38
35
  @secrets = setec_astronomy(org, (job[:secrets] || {}))
39
36
 
@@ -48,6 +48,8 @@ module Cyclid
48
48
  action_name = step['action']
49
49
  plugin = Cyclid.plugins.find(action_name, Cyclid::API::Plugins::Action)
50
50
 
51
+ raise NameError, "unknown action #{action_name}" if plugin.nil?
52
+
51
53
  step_action = plugin.new(step)
52
54
  raise ArgumentError if step_action.nil?
53
55
 
@@ -40,6 +40,36 @@ module Cyclid
40
40
  Cyclid.plugins.register(self)
41
41
  end
42
42
 
43
+ # Return the plugin version
44
+ def version
45
+ @version || '1.0.0'
46
+ end
47
+
48
+ # Return the plugin author
49
+ def author
50
+ @author || 'Unknown'
51
+ end
52
+
53
+ # Return the plugin license
54
+ def license
55
+ @license || 'Unknown'
56
+ end
57
+
58
+ # Return a URL to the plugin homepage
59
+ def homepage
60
+ @homepage || 'https://cyclid.io'
61
+ end
62
+
63
+ # Return plugin metadata
64
+ def metadata
65
+ { name: @name,
66
+ type: human_name,
67
+ version: version,
68
+ author: author,
69
+ license: license,
70
+ homepage: homepage }
71
+ end
72
+
43
73
  # Does this plugin support configuration data?
44
74
  def config?
45
75
  false
@@ -63,6 +63,14 @@ module Cyclid
63
63
  return [false, 0]
64
64
  end
65
65
 
66
+ # Plugin metadata
67
+ def self.metadata
68
+ super.merge!(version: Cyclid::Api::VERSION,
69
+ license: 'Apache-2.0',
70
+ author: 'Liqwyd Ltd.',
71
+ homepage: 'http://docs.cyclid.io')
72
+ end
73
+
66
74
  # Register this plugin
67
75
  register_plugin 'cobertura'
68
76
  end
@@ -43,8 +43,9 @@ module Cyclid
43
43
 
44
44
  Cyclid.logger.debug "cmd: '#{@cmd}' args: #{@args}"
45
45
 
46
- @env = args[:env] if args.include? :env
47
- @path = args[:path] if args.include? :path
46
+ @env = args[:env]
47
+ @path = args[:path]
48
+ @sudo = args[:sudo]
48
49
  end
49
50
 
50
51
  # Note that we don't need to explicitly use the log for transport
@@ -71,7 +72,7 @@ module Cyclid
71
72
  path = path ** @ctx unless path.nil?
72
73
 
73
74
  # Run the command
74
- success = @transport.exec(cmd_args, path)
75
+ success = @transport.exec(cmd_args, path: path, sudo: @sudo)
75
76
  rescue KeyError => ex
76
77
  # Interpolation failed
77
78
  log.write "#{ex.message}\n"
@@ -81,6 +82,14 @@ module Cyclid
81
82
  [success, @transport.exit_code]
82
83
  end
83
84
 
85
+ # Plugin metadata
86
+ def self.metadata
87
+ super.merge!(version: Cyclid::Api::VERSION,
88
+ license: 'Apache-2.0',
89
+ author: 'Liqwyd Ltd.',
90
+ homepage: 'http://docs.cyclid.io')
91
+ end
92
+
84
93
  # Register this plugin
85
94
  register_plugin 'command'
86
95
  end
@@ -113,6 +113,14 @@ module Cyclid
113
113
  [success, 0]
114
114
  end
115
115
 
116
+ # Plugin metadata
117
+ def self.metadata
118
+ super.merge!(version: Cyclid::Api::VERSION,
119
+ license: 'Apache-2.0',
120
+ author: 'Liqwyd Ltd.',
121
+ homepage: 'http://docs.cyclid.io')
122
+ end
123
+
116
124
  # Register this plugin
117
125
  register_plugin 'email'
118
126
 
@@ -36,6 +36,14 @@ module Cyclid
36
36
  true
37
37
  end
38
38
 
39
+ # Plugin metadata
40
+ def self.metadata
41
+ super.merge!(version: Cyclid::Api::VERSION,
42
+ license: 'Apache-2.0',
43
+ author: 'Liqwyd Ltd.',
44
+ homepage: 'http://docs.cyclid.io')
45
+ end
46
+
39
47
  # Register this plugin
40
48
  register_plugin 'log'
41
49
  end
@@ -47,9 +47,8 @@ module Cyclid
47
47
  File.join('/', 'tmp', file)
48
48
  end
49
49
 
50
- @env = args[:env] if args.include? :env
51
-
52
- Cyclid.logger.debug "script: '#{@script}' path: #{@path}"
50
+ @env = args[:env]
51
+ @sudo = args[:sudo]
53
52
  end
54
53
 
55
54
  # Run the script action
@@ -72,7 +71,7 @@ module Cyclid
72
71
 
73
72
  # Execute the script
74
73
  log.write("Running script from #{path}...\n")
75
- success = @transport.exec("chmod +x #{path} && #{path}")
74
+ success = @transport.exec("chmod +x #{path} && #{path}", sudo: @sudo)
76
75
  rescue KeyError => ex
77
76
  # Interpolation failed
78
77
  log.write "#{ex.message}\n"
@@ -82,6 +81,14 @@ module Cyclid
82
81
  [success, @transport.exit_code]
83
82
  end
84
83
 
84
+ # Plugin metadata
85
+ def self.metadata
86
+ super.merge!(version: Cyclid::Api::VERSION,
87
+ license: 'Apache-2.0',
88
+ author: 'Liqwyd Ltd.',
89
+ homepage: 'http://docs.cyclid.io')
90
+ end
91
+
85
92
  # Register this plugin
86
93
  register_plugin 'script'
87
94
  end
@@ -51,6 +51,14 @@ module Cyclid
51
51
  return [false, 0]
52
52
  end
53
53
 
54
+ # Plugin metadata
55
+ def self.metadata
56
+ super.merge!(version: Cyclid::Api::VERSION,
57
+ license: 'Apache-2.0',
58
+ author: 'Liqwyd Ltd.',
59
+ homepage: 'http://docs.cyclid.io')
60
+ end
61
+
54
62
  # Register this plugin
55
63
  register_plugin 'simplecov'
56
64
  end
@@ -94,6 +94,14 @@ module Cyclid
94
94
  [success, rc]
95
95
  end
96
96
 
97
+ # Plugin metadata
98
+ def self.metadata
99
+ super.merge!(version: Cyclid::Api::VERSION,
100
+ license: 'Apache-2.0',
101
+ author: 'Liqwyd Ltd.',
102
+ homepage: 'http://docs.cyclid.io')
103
+ end
104
+
97
105
  # Register this plugin
98
106
  register_plugin 'slack'
99
107
 
@@ -33,6 +33,14 @@ module Cyclid
33
33
  return ApiExtension::Controller.new(ApiExtension::GithubMethods, routes)
34
34
  end
35
35
 
36
+ # Plugin metadata
37
+ def metadata
38
+ super.merge!(version: Cyclid::Api::VERSION,
39
+ license: 'Apache-2.0',
40
+ author: 'Liqwyd Ltd.',
41
+ homepage: 'http://docs.cyclid.io')
42
+ end
43
+
36
44
  # This plugin has configuration data
37
45
  def config?
38
46
  true
@@ -124,6 +124,23 @@ module Cyclid
124
124
 
125
125
  callback = GithubCallback.new(auth_token, pr_repository, pr_sha, linkback_url)
126
126
  job_from_definition(job_definition, callback, ctx)
127
+ rescue NotFoundError
128
+ @client.create_status(pr_repository, pr_sha, 'error',
129
+ context: 'Cyclid',
130
+ description: 'The Organization does not exist')
131
+
132
+ return_failure(404, 'organization does not exist')
133
+ rescue InvalidObjectError
134
+ @client.create_status(pr_repository, pr_sha, 'error',
135
+ context: 'Cyclid',
136
+ description: 'The Job definition contains errors')
137
+
138
+ return_failure(400, 'job definition contains errors')
139
+ rescue InternalError
140
+ @client.create_status(pr_repository, pr_sha, 'error',
141
+ context: 'Cyclid', description: 'An Internal Error occurred')
142
+
143
+ return_failure(4500, "internal error: #{ex}")
127
144
  rescue StandardError
128
145
  @client.create_status(pr_repository, pr_sha, 'error',
129
146
  context: 'Cyclid', description: 'An unknown error occurred')
@@ -104,6 +104,23 @@ module Cyclid
104
104
 
105
105
  callback = GithubCallback.new(auth_token, push_repository, push_sha, linkback_url)
106
106
  job_from_definition(job_definition, callback, ctx)
107
+ rescue NotFoundError
108
+ @client.create_status(pr_repository, pr_sha, 'error',
109
+ context: 'Cyclid',
110
+ description: 'The Organization does not exist')
111
+
112
+ return_failure(404, 'organization does not exist')
113
+ rescue InvalidObjectError
114
+ @client.create_status(pr_repository, pr_sha, 'error',
115
+ context: 'Cyclid',
116
+ description: 'The Job definition contains errors')
117
+
118
+ return_failure(400, 'job definition contains errors')
119
+ rescue InternalError
120
+ @client.create_status(pr_repository, pr_sha, 'error',
121
+ context: 'Cyclid', description: 'An Internal Error occurred')
122
+
123
+ return_failure(4500, "internal error: #{ex}")
107
124
  rescue StandardError
108
125
  @client.create_status(push_repository, push_sha, 'error',
109
126
  context: 'Cyclid', description: 'An unknown error occurred')
@@ -84,6 +84,14 @@ module Cyclid
84
84
  container.delete(force: true)
85
85
  end
86
86
 
87
+ # Plugin metadata
88
+ def self.metadata
89
+ super.merge!(version: Cyclid::Api::VERSION,
90
+ license: 'Apache-2.0',
91
+ author: 'Liqwyd Ltd.',
92
+ homepage: 'http://docs.cyclid.io')
93
+ end
94
+
87
95
  # Register this plugin
88
96
  register_plugin 'docker'
89
97
 
@@ -83,7 +83,7 @@ module Cyclid
83
83
 
84
84
  # Destroy the build host
85
85
  def release(_transport, buildhost)
86
- name = buildhost['name']
86
+ name = buildhost[:name]
87
87
 
88
88
  instance = @api.servers.get(name)
89
89
  raise "instance #{name} does not exist" unless instance
@@ -92,6 +92,14 @@ module Cyclid
92
92
  raise 'failed to destroy instance' unless instance.destroy
93
93
  end
94
94
 
95
+ # Plugin metadata
96
+ def self.metadata
97
+ super.merge!(version: Cyclid::Api::VERSION,
98
+ license: 'Apache-2.0',
99
+ author: 'Liqwyd Ltd.',
100
+ homepage: 'http://docs.cyclid.io')
101
+ end
102
+
95
103
  # Register this plugin
96
104
  register_plugin 'google'
97
105
 
@@ -70,6 +70,14 @@ module Cyclid
70
70
  end
71
71
  end
72
72
 
73
+ # Plugin metadata
74
+ def self.metadata
75
+ super.merge!(version: Cyclid::Api::VERSION,
76
+ license: 'Apache-2.0',
77
+ author: 'Liqwyd Ltd.',
78
+ homepage: 'http://docs.cyclid.io')
79
+ end
80
+
73
81
  # Register this plugin
74
82
  register_plugin 'local'
75
83
  end
@@ -133,7 +141,8 @@ module Cyclid
133
141
  class Local
134
142
  include Sidekiq::Worker
135
143
 
136
- sidekiq_options retry: false
144
+ sidekiq_options retry: false,
145
+ queue: 'cyclid_jobs'
137
146
 
138
147
  # Run a job Runner asynchronously
139
148
  def perform(job, job_id, callback_object)
@@ -151,7 +160,9 @@ module Cyclid
151
160
  runner = Cyclid::API::Job::Runner.new(job_id, job, notifier)
152
161
  success = runner.run
153
162
  rescue StandardError => ex
154
- Cyclid.logger.error "job runner failed: #{ex}"
163
+ Cyclid.logger.error "local Sidekiq Worker failed: #{ex}"
164
+ Cyclid.logger.debug ex.backtrace.join("\n")
165
+
155
166
  success = false
156
167
  end
157
168
 
@@ -41,6 +41,14 @@ module Cyclid
41
41
  end
42
42
  end
43
43
 
44
+ # Plugin metadata
45
+ def self.metadata
46
+ super.merge!(version: Cyclid::Api::VERSION,
47
+ license: 'Apache-2.0',
48
+ author: 'Liqwyd Ltd.',
49
+ homepage: 'http://docs.cyclid.io')
50
+ end
51
+
44
52
  # Register this plugin
45
53
  register_plugin 'centos'
46
54
 
@@ -26,7 +26,7 @@ module Cyclid
26
26
  transport.export_env('DEBIAN_FRONTEND' => 'noninteractive')
27
27
 
28
28
  # Build hosts may require an update before anything can be installed
29
- success = transport.exec 'apt-get update -qq'
29
+ success = transport.exec('apt-get update -qq', sudo: true)
30
30
  raise 'failed to update repositories' unless success
31
31
 
32
32
  if env.key? :repos
@@ -44,13 +44,15 @@ module Cyclid
44
44
  end
45
45
 
46
46
  # We must update again to cache the new repositories
47
- success = transport.exec 'apt-get update -q'
47
+ success = transport.exec('apt-get update -q', sudo: true)
48
48
  raise 'failed to update repositories' unless success
49
49
  end
50
50
 
51
51
  if env.key? :packages
52
- success = transport.exec \
53
- "apt-get install -q -y #{env[:packages].join(' ')}" \
52
+ success = transport.exec( \
53
+ "apt-get install -q -y #{env[:packages].join(' ')}", \
54
+ sudo: true
55
+ )
54
56
 
55
57
  raise "failed to install packages #{env[:packages].join(' ')}" unless success
56
58
  end
@@ -59,6 +61,14 @@ module Cyclid
59
61
  raise
60
62
  end
61
63
 
64
+ # Plugin metadata
65
+ def self.metadata
66
+ super.merge!(version: Cyclid::Api::VERSION,
67
+ license: 'Apache-2.0',
68
+ author: 'Liqwyd Ltd.',
69
+ homepage: 'http://docs.cyclid.io')
70
+ end
71
+
62
72
  private
63
73
 
64
74
  def add_http_repository(transport, url, repo, buildhost)
@@ -70,8 +80,10 @@ module Cyclid
70
80
  components = repo[:components]
71
81
  fragment = "deb #{url} #{release} #{components}"
72
82
 
73
- success = transport.exec \
74
- "sh -c \"echo '#{fragment}' | tee -a /etc/apt/sources.list.d/cyclid.list\""
83
+ success = transport.exec( \
84
+ "sh -c \"echo '#{fragment}' | tee -a /etc/apt/sources.list.d/cyclid.list\"", \
85
+ sudo: true
86
+ )
75
87
  raise "failed to add repository #{url}" unless success
76
88
 
77
89
  return unless repo.key? :key_id
@@ -79,12 +91,16 @@ module Cyclid
79
91
  # Import the signing key
80
92
  key_id = repo[:key_id]
81
93
 
82
- success = transport.exec \
83
- "gpg --keyserver keyserver.ubuntu.com --recv-keys #{key_id}"
94
+ success = transport.exec( \
95
+ "gpg --keyserver keyserver.ubuntu.com --recv-keys #{key_id}", \
96
+ sudo: true
97
+ )
84
98
  raise "failed to import key #{key_id}" unless success
85
99
 
86
- success = transport.exec \
87
- "sh -c 'gpg -a --export #{key_id} | apt-key add -'"
100
+ success = transport.exec( \
101
+ "sh -c 'gpg -a --export #{key_id} | apt-key add -'", \
102
+ sudo: true
103
+ )
88
104
  raise "failed to add repository key #{key_id}" unless success
89
105
  end
90
106
 
@@ -41,6 +41,14 @@ module Cyclid
41
41
  end
42
42
  end
43
43
 
44
+ # Plugin metadata
45
+ def self.metadata
46
+ super.merge!(version: Cyclid::Api::VERSION,
47
+ license: 'Apache-2.0',
48
+ author: 'Liqwyd Ltd.',
49
+ homepage: 'http://docs.cyclid.io')
50
+ end
51
+
44
52
  # Register this plugin
45
53
  register_plugin 'fedora'
46
54
 
@@ -30,28 +30,28 @@ module Cyclid
30
30
 
31
31
  # Install the yum-utils package
32
32
  def install_yum_utils(transport)
33
- transport.exec 'yum install -q -y yum-utils'
33
+ transport.exec('yum install -q -y yum-utils', sudo: true)
34
34
  end
35
35
 
36
36
  # Import a signing key with RPM
37
37
  def import_signing_key(transport, key_url)
38
- transport.exec("rpm #{quiet} --import #{key_url}") \
38
+ transport.exec("rpm #{quiet} --import #{key_url}", sudo: true)
39
39
  end
40
40
 
41
41
  # Install a package group with yum
42
42
  def yum_groupinstall(transport, groups)
43
43
  grouplist = groups.map{ |g| "\"#{g}\"" }.join(' ')
44
- transport.exec "yum groupinstall #{quiet} -y #{grouplist}"
44
+ transport.exec("yum groupinstall #{quiet} -y #{grouplist}", sudo: true)
45
45
  end
46
46
 
47
47
  # Install a list of packages with yum
48
48
  def yum_install(transport, packages)
49
- transport.exec "yum install #{quiet} -y #{packages.join(' ')}"
49
+ transport.exec("yum install #{quiet} -y #{packages.join(' ')}", sudo: true)
50
50
  end
51
51
 
52
52
  # Add a repository with yum-config-manager
53
53
  def yum_add_repo(transport, url)
54
- transport.exec("yum-config-manager #{quiet} --add-repo #{url}")
54
+ transport.exec("yum-config-manager #{quiet} --add-repo #{url}", sudo: true)
55
55
  end
56
56
 
57
57
  # Use DNF to configure & install Fedora
@@ -60,7 +60,7 @@ module Cyclid
60
60
 
61
61
  if env.key? :repos
62
62
  # We need the config-manager plugin
63
- transport.exec("dnf install #{quiet} -y 'dnf-command(config-manager)'")
63
+ transport.exec("dnf install #{quiet} -y 'dnf-command(config-manager)'", sudo: true)
64
64
 
65
65
  env[:repos].each do |repo|
66
66
  next unless repo.key? :url
@@ -71,20 +71,20 @@ module Cyclid
71
71
 
72
72
  if repo[:url] =~ /\.rpm$/
73
73
  # If the URL is an RPM just install it
74
- transport.exec("dnf install #{quiet} -y #{repo[:url]}")
74
+ transport.exec("dnf install #{quiet} -y #{repo[:url]}", sudo: true)
75
75
  else
76
76
  # Not an RPM? Let's hope it's a repo file
77
- transport.exec("dnf config-manager #{quiet} --add-repo #{repo[:url]}")
77
+ transport.exec("dnf config-manager #{quiet} --add-repo #{repo[:url]}", sudo: true)
78
78
  end
79
79
  end
80
80
  end
81
81
 
82
82
  if env.key? :groups
83
83
  groups = env[:groups].map{ |g| "\"#{g}\"" }.join(' ')
84
- transport.exec "dnf groups install #{quiet} -y #{groups}"
84
+ transport.exec("dnf groups install #{quiet} -y #{groups}", sudo: true)
85
85
  end
86
86
 
87
- transport.exec "dnf install #{quiet} -y #{env[:packages].join(' ')}" \
87
+ transport.exec("dnf install #{quiet} -y #{env[:packages].join(' ')}", sudo: true) \
88
88
  if env.key? :packages
89
89
  end
90
90
 
@@ -105,7 +105,7 @@ module Cyclid
105
105
 
106
106
  if repo[:url] =~ /\.rpm$/
107
107
  # If the URL is an RPM just install it
108
- transport.exec("yum install #{quiet} -y --nogpgcheck #{repo[:url]}")
108
+ transport.exec("yum install #{quiet} -y --nogpgcheck #{repo[:url]}", sudo: true)
109
109
  else
110
110
  # Not an RPM? Let's hope it's a repo file
111
111
  yum_add_repo(transport, repo[:url])
@@ -137,7 +137,8 @@ module Cyclid
137
137
 
138
138
  if repo[:url] =~ /\.rpm$/
139
139
  # If the URL is an RPM just install it
140
- transport.exec("yum localinstall #{quiet} -y --nogpgcheck #{repo[:url]}")
140
+ transport.exec("yum localinstall #{quiet} -y --nogpgcheck #{repo[:url]}", \
141
+ sudo: true)
141
142
  else
142
143
  # Not an RPM? Let's hope it's a repo file
143
144
  yum_add_repo(transport, repo[:url])
@@ -163,7 +164,7 @@ module Cyclid
163
164
  if repo.key? :key_url
164
165
 
165
166
  # Assume the URL is an RPM
166
- transport.exec("rpm -U #{quiet} #{repo[:url]}")
167
+ transport.exec("rpm -U #{quiet} #{repo[:url]}", sudo: true)
167
168
  end
168
169
  end
169
170
 
@@ -41,6 +41,14 @@ module Cyclid
41
41
  end
42
42
  end
43
43
 
44
+ # Plugin metadata
45
+ def self.metadata
46
+ super.merge!(version: Cyclid::Api::VERSION,
47
+ license: 'Apache-2.0',
48
+ author: 'Liqwyd Ltd.',
49
+ homepage: 'http://docs.cyclid.io')
50
+ end
51
+
44
52
  # Register this plugin
45
53
  register_plugin 'rhel'
46
54
 
@@ -26,12 +26,12 @@ module Cyclid
26
26
  transport.export_env('DEBIAN_FRONTEND' => 'noninteractive')
27
27
 
28
28
  # Build hosts may require an update before anything can be installed
29
- success = transport.exec 'apt-get update -qq'
29
+ success = transport.exec('apt-get update -qq', sudo: true)
30
30
  raise 'failed to update repositories' unless success
31
31
 
32
32
  if env.key? :repos
33
33
  # Ensure apt-add-repository is available
34
- transport.exec 'apt-get install -qq -y software-properties-common'
34
+ transport.exec('apt-get install -qq -y software-properties-common', sudo: true)
35
35
 
36
36
  env[:repos].each do |repo|
37
37
  next unless repo.key? :url
@@ -50,13 +50,15 @@ module Cyclid
50
50
  end
51
51
 
52
52
  # We must update again to cache the new repositories
53
- success = transport.exec 'apt-get update -q'
53
+ success = transport.exec('apt-get update -q', sudo: true)
54
54
  raise 'failed to update repositories' unless success
55
55
  end
56
56
 
57
57
  if env.key? :packages
58
- success = transport.exec \
59
- "apt-get install -q -y #{env[:packages].join(' ')}" \
58
+ success = transport.exec( \
59
+ "apt-get install -q -y #{env[:packages].join(' ')}", \
60
+ sudo: true
61
+ )
60
62
 
61
63
  raise "failed to install packages #{env[:packages].join(' ')}" unless success
62
64
  end
@@ -65,10 +67,18 @@ module Cyclid
65
67
  raise
66
68
  end
67
69
 
70
+ # Plugin metadata
71
+ def self.metadata
72
+ super.merge!(version: Cyclid::Api::VERSION,
73
+ license: 'Apache-2.0',
74
+ author: 'Liqwyd Ltd.',
75
+ homepage: 'http://docs.cyclid.io')
76
+ end
77
+
68
78
  private
69
79
 
70
80
  def add_ppa_repository(transport, url)
71
- success = transport.exec "apt-add-repository -y #{url}"
81
+ success = transport.exec("apt-add-repository -y #{url}", sudo: true)
72
82
  raise "failed to add repository #{url}" unless success
73
83
  end
74
84
 
@@ -81,8 +91,10 @@ module Cyclid
81
91
  components = repo[:components]
82
92
  fragment = "deb #{url} #{release} #{components}"
83
93
 
84
- success = transport.exec \
85
- "sh -c \"echo '#{fragment}' | tee -a /etc/apt/sources.list.d/cyclid.list\""
94
+ success = transport.exec( \
95
+ "sh -c \"echo '#{fragment}' | tee -a /etc/apt/sources.list.d/cyclid.list\"", \
96
+ sudo: true
97
+ )
86
98
  raise "failed to add repository #{url}" unless success
87
99
 
88
100
  return unless repo.key? :key_id
@@ -90,12 +102,16 @@ module Cyclid
90
102
  # Import the signing key
91
103
  key_id = repo[:key_id]
92
104
 
93
- success = transport.exec \
94
- "gpg --keyserver keyserver.ubuntu.com --recv-keys #{key_id}"
105
+ success = transport.exec( \
106
+ "gpg --keyserver keyserver.ubuntu.com --recv-keys #{key_id}", \
107
+ sudo: true
108
+ )
95
109
  raise "failed to import key #{key_id}" unless success
96
110
 
97
- success = transport.exec \
98
- "sh -c 'gpg -a --export #{key_id} | apt-key add -'"
111
+ success = transport.exec( \
112
+ "sh -c 'gpg -a --export #{key_id} | apt-key add -'", \
113
+ sudo: true
114
+ )
99
115
  raise "failed to add repository key #{key_id}" unless success
100
116
  end
101
117
 
@@ -40,7 +40,7 @@ module Cyclid
40
40
  # username
41
41
  url.user = source[:token] if source.key? :token
42
42
 
43
- success = transport.exec("git clone #{url}", ctx[:workspace])
43
+ success = transport.exec("git clone #{url}", path: ctx[:workspace])
44
44
  return false unless success
45
45
 
46
46
  # If a branch was given, check it out
@@ -51,16 +51,24 @@ module Cyclid
51
51
  match = url.path.match(%r{^.*\/([^\.]*)})
52
52
  source_dir = "#{ctx[:workspace]}/#{match[1]}"
53
53
 
54
- success = transport.exec("git fetch origin #{branch}:#{branch}", source_dir)
54
+ success = transport.exec("git fetch origin #{branch}:#{branch}", path: source_dir)
55
55
  return false unless success
56
56
 
57
- success = transport.exec("git checkout #{branch}", source_dir)
57
+ success = transport.exec("git checkout #{branch}", path: source_dir)
58
58
  return false unless success
59
59
  end
60
60
 
61
61
  return true
62
62
  end
63
63
 
64
+ # Plugin metadata
65
+ def self.metadata
66
+ super.merge!(version: Cyclid::Api::VERSION,
67
+ license: 'Apache-2.0',
68
+ author: 'Liqwyd Ltd.',
69
+ homepage: 'http://docs.cyclid.io')
70
+ end
71
+
64
72
  # Register this plugin
65
73
  register_plugin 'git'
66
74
 
@@ -38,7 +38,7 @@ module Cyclid
38
38
  end
39
39
 
40
40
  # Run a command on the remote host.
41
- def exec(_cmd, _path = nil)
41
+ def exec(_cmd, _args = {})
42
42
  false
43
43
  end
44
44
 
@@ -49,8 +49,11 @@ module Cyclid
49
49
  end
50
50
 
51
51
  # Execute a command via the Docker API
52
- def exec(cmd, path = nil)
53
- command = build_command(cmd, path, @env)
52
+ def exec(cmd, args = {})
53
+ sudo = args[:sudo] || false
54
+ path = args[:path]
55
+
56
+ command = build_command(cmd, sudo, path, @env)
54
57
  Cyclid.logger.debug "command=#{command}"
55
58
  result = @container.exec(command, wait: 300) do |_stream, chunk|
56
59
  @log.write chunk
@@ -70,11 +73,19 @@ module Cyclid
70
73
  io.write(result)
71
74
  end
72
75
 
76
+ # Plugin metadata
77
+ def self.metadata
78
+ super.merge!(version: Cyclid::Api::VERSION,
79
+ license: 'Apache-2.0',
80
+ author: 'Liqwyd Ltd.',
81
+ homepage: 'http://docs.cyclid.io')
82
+ end
83
+
73
84
  register_plugin('dockerapi')
74
85
 
75
86
  private
76
87
 
77
- def build_command(cmd, path = nil, env = {})
88
+ def build_command(cmd, sudo, path = nil, env = {})
78
89
  command = []
79
90
  if env
80
91
  vars = env.map do |k, value|
@@ -88,8 +99,10 @@ module Cyclid
88
99
  command << "cd #{path}" if path
89
100
  command << if @username == 'root'
90
101
  cmd
102
+ elsif sudo
103
+ "sudo -E -n $SHELL -l -c '#{cmd}'"
91
104
  else
92
- "sudo -E #{cmd}"
105
+ cmd
93
106
  end
94
107
  ['sh', '-l', '-c', command.join(';')]
95
108
  end
@@ -66,8 +66,11 @@ module Cyclid
66
66
  end
67
67
 
68
68
  # Execute a command via. SSH
69
- def exec(cmd, path = nil)
70
- command = build_command(cmd, path, @env)
69
+ def exec(cmd, args = {})
70
+ sudo = args[:sudo] || false
71
+ path = args[:path]
72
+
73
+ command = build_command(cmd, sudo, path, @env)
71
74
  Cyclid.logger.debug "command=#{command}"
72
75
 
73
76
  @session.open_channel do |channel|
@@ -125,9 +128,17 @@ module Cyclid
125
128
  @session.close
126
129
  end
127
130
 
131
+ # Plugin metadata
132
+ def self.metadata
133
+ super.merge!(version: Cyclid::Api::VERSION,
134
+ license: 'Apache-2.0',
135
+ author: 'Liqwyd Ltd.',
136
+ homepage: 'http://docs.cyclid.io')
137
+ end
138
+
128
139
  private
129
140
 
130
- def build_command(cmd, path = nil, env = {})
141
+ def build_command(cmd, sudo, path = nil, env = {})
131
142
  command = []
132
143
  if env
133
144
  vars = env.map do |k, value|
@@ -141,8 +152,10 @@ module Cyclid
141
152
  command << "cd #{path}" if path
142
153
  command << if @username == 'root'
143
154
  cmd
155
+ elsif sudo
156
+ "sudo -E -n $SHELL -l -c '#{cmd}'"
144
157
  else
145
- "sudo -E #{cmd}"
158
+ cmd
146
159
  end
147
160
  command.join(';')
148
161
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Cyclid
3
3
  module Api
4
- VERSION = '0.3.3'
4
+ VERSION = '0.4.0'
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.3
4
+ version: 0.4.0
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-06-24 00:00:00.000000000 Z
11
+ date: 2017-07-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -383,6 +383,7 @@ files:
383
383
  - app/cyclid/controllers/organizations/job.rb
384
384
  - app/cyclid/controllers/organizations/members.rb
385
385
  - app/cyclid/controllers/organizations/stages.rb
386
+ - app/cyclid/controllers/plugins.rb
386
387
  - app/cyclid/controllers/users.rb
387
388
  - app/cyclid/controllers/users/collection.rb
388
389
  - app/cyclid/controllers/users/document.rb