cyclid 0.3.3 → 0.4.0

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 (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