cyclid 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +174 -0
  3. data/README.md +54 -0
  4. data/app/cyclid.rb +61 -0
  5. data/app/cyclid/config.rb +38 -0
  6. data/app/cyclid/controllers.rb +123 -0
  7. data/app/cyclid/controllers/auth.rb +34 -0
  8. data/app/cyclid/controllers/auth/token.rb +78 -0
  9. data/app/cyclid/controllers/health.rb +96 -0
  10. data/app/cyclid/controllers/organizations.rb +104 -0
  11. data/app/cyclid/controllers/organizations/collection.rb +134 -0
  12. data/app/cyclid/controllers/organizations/config.rb +128 -0
  13. data/app/cyclid/controllers/organizations/document.rb +135 -0
  14. data/app/cyclid/controllers/organizations/job.rb +266 -0
  15. data/app/cyclid/controllers/organizations/members.rb +145 -0
  16. data/app/cyclid/controllers/organizations/stages.rb +251 -0
  17. data/app/cyclid/controllers/users.rb +47 -0
  18. data/app/cyclid/controllers/users/collection.rb +131 -0
  19. data/app/cyclid/controllers/users/document.rb +133 -0
  20. data/app/cyclid/health_helpers.rb +40 -0
  21. data/app/cyclid/job.rb +3 -0
  22. data/app/cyclid/job/helpers.rb +67 -0
  23. data/app/cyclid/job/job.rb +164 -0
  24. data/app/cyclid/job/runner.rb +275 -0
  25. data/app/cyclid/job/stage.rb +67 -0
  26. data/app/cyclid/log_buffer.rb +104 -0
  27. data/app/cyclid/models.rb +3 -0
  28. data/app/cyclid/models/job_record.rb +25 -0
  29. data/app/cyclid/models/organization.rb +64 -0
  30. data/app/cyclid/models/plugin_config.rb +25 -0
  31. data/app/cyclid/models/stage.rb +42 -0
  32. data/app/cyclid/models/step.rb +29 -0
  33. data/app/cyclid/models/user.rb +60 -0
  34. data/app/cyclid/models/user_permissions.rb +28 -0
  35. data/app/cyclid/monkey_patches.rb +37 -0
  36. data/app/cyclid/plugin_registry.rb +75 -0
  37. data/app/cyclid/plugins.rb +125 -0
  38. data/app/cyclid/plugins/action.rb +48 -0
  39. data/app/cyclid/plugins/action/command.rb +89 -0
  40. data/app/cyclid/plugins/action/email.rb +207 -0
  41. data/app/cyclid/plugins/action/email/html.erb +58 -0
  42. data/app/cyclid/plugins/action/email/text.erb +13 -0
  43. data/app/cyclid/plugins/action/script.rb +90 -0
  44. data/app/cyclid/plugins/action/slack.rb +129 -0
  45. data/app/cyclid/plugins/action/slack/note.erb +5 -0
  46. data/app/cyclid/plugins/api.rb +195 -0
  47. data/app/cyclid/plugins/api/github.rb +111 -0
  48. data/app/cyclid/plugins/api/github/callback.rb +66 -0
  49. data/app/cyclid/plugins/api/github/methods.rb +201 -0
  50. data/app/cyclid/plugins/api/github/status.rb +67 -0
  51. data/app/cyclid/plugins/builder.rb +80 -0
  52. data/app/cyclid/plugins/builder/mist.rb +107 -0
  53. data/app/cyclid/plugins/dispatcher.rb +89 -0
  54. data/app/cyclid/plugins/dispatcher/local.rb +167 -0
  55. data/app/cyclid/plugins/provisioner.rb +40 -0
  56. data/app/cyclid/plugins/provisioner/debian.rb +90 -0
  57. data/app/cyclid/plugins/provisioner/ubuntu.rb +98 -0
  58. data/app/cyclid/plugins/source.rb +39 -0
  59. data/app/cyclid/plugins/source/git.rb +64 -0
  60. data/app/cyclid/plugins/transport.rb +63 -0
  61. data/app/cyclid/plugins/transport/ssh.rb +155 -0
  62. data/app/cyclid/sinatra/api_helpers.rb +66 -0
  63. data/app/cyclid/sinatra/auth_helpers.rb +127 -0
  64. data/app/cyclid/sinatra/warden/strategies/api_token.rb +62 -0
  65. data/app/cyclid/sinatra/warden/strategies/basic.rb +58 -0
  66. data/app/cyclid/sinatra/warden/strategies/hmac.rb +76 -0
  67. data/app/db.rb +51 -0
  68. data/bin/cyclid-db-init +107 -0
  69. data/db/schema.rb +92 -0
  70. data/lib/cyclid/app.rb +4 -0
  71. metadata +407 -0
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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 Job related classes
21
+ module Job
22
+ # Non-AR model for Stages. Using a wrapper allows us to create an ad-hoc
23
+ # stage (I.e. one that is not stored in the database) or load a stage
24
+ # from the database and merge in over-rides without risking modifying
25
+ # the database object.
26
+ class StageView
27
+ attr_reader :name, :version, :steps
28
+ attr_accessor :on_success, :on_failure
29
+
30
+ def initialize(arg)
31
+ if arg.is_a? Cyclid::API::Stage
32
+ @name = arg.name
33
+ @version = arg.version
34
+ @steps = arg.steps.map(&:serializable_hash)
35
+ elsif arg.is_a? Hash
36
+ arg.symbolize_keys!
37
+
38
+ raise ArgumentError, 'name is required' unless arg.key? :name
39
+
40
+ @name = arg[:name]
41
+ @version = arg.fetch(:version, '1.0.0')
42
+
43
+ # Create & serialize Actions for each step
44
+ sequence = 1
45
+ @steps = arg[:steps].map do |step|
46
+ Cyclid.logger.debug "ad-hoc step=#{step}"
47
+
48
+ action_name = step['action']
49
+ plugin = Cyclid.plugins.find(action_name, Cyclid::API::Plugins::Action)
50
+
51
+ step_action = plugin.new(step)
52
+ raise ArgumentError if step_action.nil?
53
+
54
+ # Serialize the object into the Step and store it in the database.
55
+ action = Oj.dump(step_action)
56
+
57
+ step_definition = { sequence: sequence, action: action }
58
+ sequence += 1
59
+
60
+ step_definition
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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
+ # Simple in-memory FIFO; inspired by StringIO but reads & writes maintain
21
+ # their own position. It's unlike a file enough to not be derived from IO.
22
+ class StringFIFO
23
+ def initialize
24
+ @buffer = String.new
25
+ @write_pos = 0
26
+ @read_pos = 0
27
+ end
28
+
29
+ # Append data to the buffer & update the write position
30
+ def write(data)
31
+ @buffer += data
32
+ @write_pos += data.length
33
+ end
34
+
35
+ # Read data from the buffer. If length is given, read at most length
36
+ # characters from the buffer or whatever is available, whichever is
37
+ # smaller.
38
+ #
39
+ # Completely non-blocking; if no data is available, returns an empty
40
+ # string.
41
+ def read(length = nil)
42
+ len = if length
43
+ [length, @write_pos].min
44
+ else
45
+ @write_pos
46
+ end
47
+ start = @read_pos
48
+ @read_pos += len
49
+
50
+ @buffer[start, len]
51
+ end
52
+
53
+ # Return the entire contents of the buffer
54
+ def string
55
+ @buffer
56
+ end
57
+
58
+ alias to_s string
59
+
60
+ # Reset the buffer, read & write positions
61
+ def clear
62
+ @buffer = ''
63
+ @write_pos = 0
64
+ @read_pos = 0
65
+ end
66
+ end
67
+
68
+ # Intelligent buffer which can be passed to plugins which need to collate
69
+ # output data from different commands during a job
70
+ class LogBuffer
71
+ def initialize(job_record = nil, websocket = nil)
72
+ @job_record = job_record
73
+ @websocket = websocket
74
+ @buffer = StringFIFO.new
75
+ end
76
+
77
+ # Append data to the log and send it on to any configured consumers
78
+ def write(data)
79
+ # Append the new data to log
80
+ @buffer.write data
81
+
82
+ # Update the Job Record, if there is one
83
+ if @job_record
84
+ # XXX: This will destroy the database. Find a better method.
85
+ @job_record.log = @buffer.string
86
+ @job_record.save!
87
+ end
88
+
89
+ # Write to web socket
90
+ @websocket.write data if @websocket
91
+ end
92
+
93
+ # Non-destructively read any new data from the buffer
94
+ def read(length = nil)
95
+ @buffer.read(length)
96
+ end
97
+
98
+ # Return a complete copy of the data from the buffer
99
+ def log
100
+ @buffer.string
101
+ end
102
+ end
103
+ end
104
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+ # Load the models
3
+ require_rel 'models/*.rb'
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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
+ # Model for Users
21
+ class JobRecord < ActiveRecord::Base
22
+ Cyclid.logger.debug('In the JobRecod model')
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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
+ # Model for Organizations
21
+ class Organization < ActiveRecord::Base
22
+ Cyclid.logger.debug('In the Organization model')
23
+
24
+ class << self
25
+ # Return the collection of Organizations as an array of Hashes (instead
26
+ # of Organization objects)
27
+ def all_as_hash
28
+ all.to_a.map(&:serializable_hash)
29
+ end
30
+ end
31
+
32
+ validates :name, presence: true
33
+ validates :owner_email, presence: true
34
+
35
+ validates :rsa_private_key, presence: true
36
+ validates :rsa_public_key, presence: true
37
+ validates :salt, presence: true
38
+
39
+ validates_uniqueness_of :name
40
+
41
+ has_and_belongs_to_many :users,
42
+ after_add: :add_user_org_perm,
43
+ after_remove: :remove_user_org_perm
44
+
45
+ has_many :userpermissions
46
+ has_many :stages
47
+ has_many :job_records
48
+ has_many :plugin_configs
49
+
50
+ # Ensure that a set of Userpermissions exist when a User is added to
51
+ # this Organization
52
+ def add_user_org_perm(user)
53
+ Cyclid.logger.debug "Creating org. perm. for #{user.username}"
54
+ user.userpermissions << Userpermission.new(organization: self)
55
+ end
56
+
57
+ # Remove Userpermissions when a User is removed from this Organization
58
+ def remove_user_org_perm(user)
59
+ Cyclid.logger.debug "Destroying org. perm. for #{user.username}"
60
+ user.userpermissions.delete(Userpermission.find_by(organization: self))
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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
+ # Model for PluginConfigs
21
+ class PluginConfig < ActiveRecord::Base
22
+ belongs_to :organization
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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
+ # Model for Stages
21
+ class Stage < ActiveRecord::Base
22
+ Cyclid.logger.debug('In the Stage model')
23
+
24
+ class << self
25
+ # Return the collection of Stages as an array of Hashes (instead
26
+ # of Stage objects)
27
+ def all_as_hash
28
+ all.to_a.map(&:serializable_hash)
29
+ end
30
+ end
31
+
32
+ validates :name, presence: true
33
+ validates :version, presence: true
34
+
35
+ validates_uniqueness_of :name, scope: :version
36
+ validates_format_of :version, with: /\A\d+.\d+.\d+.?\d*\z/
37
+
38
+ belongs_to :organization
39
+ has_many :steps
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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
+ # Model for Steps
21
+ class Step < ActiveRecord::Base
22
+ Cyclid.logger.debug('In the Step model')
23
+
24
+ validates :sequence, presence: true
25
+
26
+ belongs_to :stage
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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 'bcrypt'
17
+
18
+ # Top level module for the core Cyclid code.
19
+ module Cyclid
20
+ # Module for the Cyclid API
21
+ module API
22
+ # Model for Users
23
+ class User < ActiveRecord::Base
24
+ Cyclid.logger.debug('In the User model')
25
+
26
+ class << self
27
+ # Return the collection of Users as an array of Hashes (instead
28
+ # of User objects)
29
+ def all_as_hash
30
+ all.to_a.map(&:serializable_hash)
31
+ end
32
+ end
33
+
34
+ validates :username, presence: true
35
+ validates :email, presence: true
36
+
37
+ validates_uniqueness_of :username
38
+
39
+ has_and_belongs_to_many :organizations
40
+ has_many :userpermissions
41
+ has_many :job_records
42
+
43
+ # Allow an unencryped password to be passed in via. new_password and
44
+ # ensure it is encrypted into password when the record is saved
45
+ attr_accessor :new_password
46
+
47
+ before_save :hash_new_password, if: :password_changed?
48
+
49
+ # Check if the new_password attribute has changed
50
+ def password_changed?
51
+ !@new_password.blank?
52
+ end
53
+
54
+ # Generate a BCrypt2 password from the plaintext
55
+ def hash_new_password
56
+ self.password = BCrypt::Password.create(@new_password)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ # Copyright 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
+ # Model for UserPermissions
21
+ class Userpermission < ActiveRecord::Base
22
+ Cyclid.logger.debug('In the Userpermission model')
23
+
24
+ belongs_to :user
25
+ belongs_to :organization
26
+ end
27
+ end
28
+ end