cyclid 0.2.3 → 0.2.4

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: 9d648344e006f1c13d7ee4c36f55328c66822708
4
- data.tar.gz: d6e69422363ff0deb638fa0e8a8bd03f71715890
3
+ metadata.gz: 051d2d610dc0eb351961625c4b7803648425b8e3
4
+ data.tar.gz: f318c016a0c6e3de32faea08f8cb4ac046c781ea
5
5
  SHA512:
6
- metadata.gz: 3c706eba8f83beb02b033a558f10af88c77dcd776be376fcc3cc4290457bb10736b60c4f56bfe53b5f41024706bf6799b28628ae86e03b0ff9ae1624b8d4f24c
7
- data.tar.gz: f77547d0efc97beb0599f0c2cc8bdcd34ab9e538dbde2b859a22b99053381b2e92e6cee4e2ff1ac2b848039c3962f337b72086bf2089ecf43a3f2a80a74f7b36
6
+ metadata.gz: 2b8cbf10d103bc69384c92eb32b9cb48944f6debe6bcbf2a1c37f0bcdd710c97f2077c82371373e6d57d30b15df487d0fbdd18ec9df60252335af21e0996a951
7
+ data.tar.gz: 3a518369356ca89ed5a5ab340779493ec7dd1862a4822735c596366063a9f70fd8e81934dd6a725d78e93d7c5c91e6e05d1171b792d7c7f2db715c2dd1a43228
data/README.md CHANGED
@@ -1,9 +1,16 @@
1
1
  Cyclid
2
2
  ======
3
+ # Documentation
4
+
5
+ See http://docs.cyclid.io/en/latest/ for full documentation, including [installation instructions](http://docs.cyclid.io/en/latest/server.html#installation).
6
+
7
+ # Developement
8
+
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.
3
10
 
4
- # Getting started
11
+ ## Getting started
5
12
  ```
6
- $ rbenv install 2.3.0
13
+ $ rbenv install 2.3.1
7
14
  $ bundle install --path vendor/bundle
8
15
  $ bundle exec rake db:migrate
9
16
  $ CYCLID_CONFIG=config/development bundle exec bin/cyclid-db-init
@@ -12,43 +19,18 @@ Cyclid requires a Redis server for Sidekiq; you can either run a Redis server on
12
19
 
13
20
  You can start Cyclid under Webrick with `bundle exec rake rackup`, and then start Sidekiq with `bundle exec rake sidekiq`, or you can run both under Guard with `bundle exec rake guard`.
14
21
 
15
- You can use curl or wget with HTTP Basic authentication, or the `test/hmac-test.rb` command for GET's using HMAC authentication.
22
+ The Cyclid development server will run on localhost port 8361, which is the standard Cyclid API port.
16
23
 
17
- # Testing
24
+ `cyclid-db-init` will create sqlite3 database and the initial `admin` user and `admins` group. You'll need to make a note of the HMAC secret that is automatically generated & printed so that you can configure the Cyclid client to connect to your development server.
25
+
26
+ ## Testing
18
27
 
19
28
  RSpec tests are included. Run `bundle exec rake spec` to run the tests and generate a coverage report into the `coverage` directory. The tests do not affect any databases and external API calls are mocked.
20
29
 
21
30
  The Cyclid source code is also expected to pass Rubocop; run `bundle exec rake rubocop` to lint the code.
22
31
 
23
- # Documentation
32
+ ## Documentation
24
33
 
25
34
  Cyclid uses YARD to generate documentation for both the Ruby API (internal Modules, Classes & Methods) and the REST API. Run `bundle exec rake doc` to generate both sets of documentation. The Ruby documentation is placed in the `doc/api` directory, and the REST API documentation is placed in the `doc/rest` directory.
26
35
 
27
- ## Test data
28
-
29
- The `test/db-loader.rb` script creates two users ('admin' and 'test'), and two organizations ('admins' and 'test).
30
-
31
- ### Users
32
-
33
- An admin (Super Admin) user is configured with the following attributes:
34
-
35
- * Username: admin
36
- * Email: admin@example.com
37
- * Password: password
38
- * Secret: aasecret55
39
-
40
- A test user is configured with the following attributes:
41
-
42
- * Username: test
43
- * Email: test@example.com
44
- * Password: aapassword55
45
- * Secret: aasecret55
46
-
47
- ### Organizations
48
-
49
- Two Organizations are created:
50
-
51
- * admins
52
- * test
53
-
54
- The admin user is a member of admins, and the test user is a member of test.
36
+ User documentation is hosted on [Read the Docs](https://readthedocs.org). The source can be found in the [Cyclid-docs](https://github.com/Cyclid/Cyclid-docs) repository.
@@ -68,7 +68,7 @@ module Cyclid
68
68
 
69
69
  # Connect a transport to the build host; the notifier is a proxy
70
70
  # to the log buffer
71
- @transport = create_transport(@build_host, @notifier)
71
+ @transport = create_transport(@build_host, @notifier, @ctx)
72
72
 
73
73
  # Prepare the host
74
74
  provisioner = create_provisioner(@build_host)
@@ -83,6 +83,7 @@ module Cyclid
83
83
  end
84
84
  rescue StandardError => ex
85
85
  Cyclid.logger.error "job runner failed: #{ex}"
86
+ Cyclid.logger.error ex.backtrace.join("\n")
86
87
 
87
88
  @notifier.status = FAILED
88
89
  @notifier.ended = Time.now.to_s
@@ -190,7 +191,7 @@ module Cyclid
190
191
 
191
192
  # Find a transport that can be used with the build host, create one and
192
193
  # connect them together
193
- def create_transport(build_host, log_buffer)
194
+ def create_transport(build_host, log_buffer, ctx)
194
195
  # Create a Transport & connect it to the build host
195
196
  host, username, password, key = build_host.connect_info
196
197
  Cyclid.logger.debug "create_transport: host: #{host} " \
@@ -213,7 +214,8 @@ module Cyclid
213
214
  user: username,
214
215
  password: password,
215
216
  key: key,
216
- log: log_buffer)
217
+ log: log_buffer,
218
+ ctx: ctx)
217
219
  raise 'failed to connect the transport' unless transport
218
220
 
219
221
  return transport
@@ -0,0 +1,44 @@
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 Plugins
21
+ module Plugins
22
+ # "Log" plugin; will always succeed. Simply emits a message to the log.
23
+ class Log < Action
24
+ def initialize(args = {})
25
+ args.symbolize_keys!
26
+
27
+ # There must be a message to log.
28
+ raise 'a log action requires a message' unless args.include? :message
29
+
30
+ @message = args[:message]
31
+ end
32
+
33
+ # Write the log message, with the context data interpolated
34
+ def perform(log)
35
+ log.write(@message % @ctx)
36
+ true
37
+ end
38
+
39
+ # Register this plugin
40
+ register_plugin 'log'
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,200 @@
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 'fog/google'
17
+ require 'securerandom'
18
+
19
+ # Top level module for the core Cyclid code.
20
+ module Cyclid
21
+ # Module for the Cyclid API
22
+ module API
23
+ # Module for Cyclid Plugins
24
+ module Plugins
25
+ # Google build host
26
+ class GoogleHost < BuildHost
27
+ # SSH is the only acceptable Transport
28
+ def transports
29
+ ['ssh']
30
+ end
31
+ end
32
+
33
+ # Google builder. Creates Google Compute instances.
34
+ class Google < Builder
35
+ def initialize
36
+ @config = load_google_config(Cyclid.config.plugins)
37
+ Cyclid.logger.debug "config=#{@config.inspect}"
38
+ @api = Fog::Compute.new(provider: 'Google',
39
+ google_project: @config[:project],
40
+ google_client_email: @config[:client_email],
41
+ google_json_key_location: @config[:json_key_location])
42
+ end
43
+
44
+ # Create & return a build host
45
+ def get(args = {})
46
+ args.symbolize_keys!
47
+
48
+ Cyclid.logger.debug "google: args=#{args}"
49
+
50
+ # If there is one, split the 'os' into a 'distro' and 'release'
51
+ if args.key? :os
52
+ match = args[:os].match(/\A(\w*)_(.*)\Z/)
53
+ distro = match[1] if match
54
+ release = match[2] if match
55
+ else
56
+ # No OS was specified; use the default
57
+ # XXX Defaults should be configurable
58
+ distro = 'ubuntu'
59
+ release = 'trusty'
60
+ end
61
+
62
+ name = create_name
63
+
64
+ source_image, size = find_source_image(distro, release)
65
+ disk = create_disk(name, size, source_image)
66
+ instance = create_instance(name, disk)
67
+
68
+ Cyclid.logger.debug "instance=#{instance.inspect}"
69
+
70
+ GoogleHost.new(name: name,
71
+ host: instance.public_ip_address,
72
+ username: @config[:username],
73
+ workspace: "/home/#{@config[:username]}",
74
+ password: nil,
75
+ key: @config[:ssh_private_key],
76
+ distro: distro,
77
+ release: release)
78
+ end
79
+
80
+ # Destroy the build host
81
+ def release(_transport, buildhost)
82
+ name = buildhost['name']
83
+
84
+ instance = @api.servers.get(name)
85
+ raise "instance #{name} does not exist" unless instance
86
+
87
+ Cyclid.logger.info "destroying #{name}"
88
+ raise 'failed to destroy instance' unless instance.destroy
89
+ end
90
+
91
+ # Register this plugin
92
+ register_plugin 'google'
93
+
94
+ private
95
+
96
+ # Load the config for the Google plugin and set defaults if they're not
97
+ # in the config
98
+ def load_google_config(config)
99
+ config.symbolize_keys!
100
+
101
+ google_config = config[:google] || {}
102
+ google_config.symbolize_keys!
103
+ Cyclid.logger.debug "config=#{google_config}"
104
+
105
+ raise 'the Google project must be provided' \
106
+ unless google_config.key? :project
107
+
108
+ raise 'the Google client email must be provided' \
109
+ unless google_config.key? :client_email
110
+
111
+ raise 'the JSON key location must be provided' \
112
+ unless google_config.key? :json_key_location
113
+
114
+ # Set defaults
115
+ google_config[:zone] = 'us-central1-a' unless google_config.key? :zone
116
+ google_config[:machine_type] = 'f1-micro' unless google_config.key? :machine_type
117
+ google_config[:network] = 'default' unless google_config.key? :network
118
+ google_config[:username] = 'build' unless google_config.key? :username
119
+ google_config[:ssh_private_key] = File.join(%w(/ etc cyclid id_rsa_build)) \
120
+ unless google_config.key? :ssh_private_key
121
+ google_config[:ssh_public_key] = File.join(%w(/ etc cyclid id_rsa_build.pub)) \
122
+ unless google_config.key? :ssh_public_key
123
+ google_config[:instance_name] = 'cyclid-build' \
124
+ unless google_config.key? :instance_name
125
+
126
+ return google_config
127
+ end
128
+
129
+ # Generate a unique name for the build host
130
+ def create_name
131
+ base = @config[:instance_name]
132
+ "#{base}-#{SecureRandom.hex(16)}"
133
+ end
134
+
135
+ # Map the distro & release to a source image
136
+ def find_source_image(distro, release)
137
+ Cyclid.logger.debug 'attempting to find source image'
138
+
139
+ source_image = nil
140
+ disk_size = 0
141
+
142
+ @api.images.all.each do |image|
143
+ next if image.deprecated
144
+
145
+ match = image.name.match(/^#{distro}-((\d*)-(.*)-v.*$|(\d*)-v.*$)/)
146
+ next unless match
147
+ next unless match[2] == release or match[3] == release
148
+
149
+ # Found one
150
+ Cyclid.logger.info "found image #{image.name} for #{distro}:#{release}"
151
+ source_image = image.name
152
+ disk_size = image.disk_size_gb
153
+
154
+ break
155
+ end
156
+
157
+ # If we didn't find a disk, we have to stop now
158
+ raise "could not find suitable source image for #{distro}:#{release}" \
159
+ unless source_image
160
+
161
+ return source_image, disk_size
162
+ end
163
+
164
+ # Create a new disk image from the source
165
+ def create_disk(name, size, source_image)
166
+ disk = @api.disks.create(name: name,
167
+ size_gb: size,
168
+ zone_name: @config[:zone],
169
+ source_image: source_image)
170
+
171
+ Cyclid.logger.info 'waiting for disk...'
172
+ disk.wait_for { disk.ready? }
173
+
174
+ return disk
175
+ end
176
+
177
+ # Create a compute instance
178
+ def create_instance(name, disk)
179
+ Cyclid.logger.info "creating instance #{name}"
180
+ instance = @api.servers.bootstrap(name: name,
181
+ disks: [disk],
182
+ machine_type: @config[:machine_type],
183
+ zone_name: @config[:zone],
184
+ network: @config[:network],
185
+ username: @config[:username],
186
+ public_key_path: @config[:ssh_public_key],
187
+ private_key_path: @config[:ssh_private_key],
188
+ tags: ['build', 'build-host'])
189
+
190
+ device_name = instance.disks[0]['deviceName']
191
+ instance.set_disk_auto_delete(true, device_name)
192
+
193
+ instance.wait_for { instance.sshable? }
194
+
195
+ return instance
196
+ end
197
+ end
198
+ end
199
+ end
200
+ end
@@ -39,13 +39,13 @@ module Cyclid
39
39
  end
40
40
  end
41
41
 
42
- success = transport.exec 'sudo apt-get update'
42
+ success = transport.exec 'apt-get update'
43
43
  raise 'failed to update repositories' unless success
44
44
  end
45
45
 
46
46
  if env.key? :packages
47
47
  success = transport.exec \
48
- "sudo -E apt-get install -y #{env[:packages].join(' ')}" \
48
+ "apt-get install -y #{env[:packages].join(' ')}" \
49
49
 
50
50
  raise "failed to install packages #{env[:packages].join(' ')}" unless success
51
51
  end
@@ -66,7 +66,7 @@ module Cyclid
66
66
  fragment = "deb #{url} #{release} #{components}"
67
67
 
68
68
  success = transport.exec \
69
- "echo '#{fragment}' | sudo tee -a /etc/apt/sources.list.d/cyclid.list"
69
+ "sh -c \"echo '#{fragment}' | tee -a /etc/apt/sources.list.d/cyclid.list\""
70
70
  raise "failed to add repository #{url}" unless success
71
71
 
72
72
  return unless repo.key? :key_id
@@ -79,7 +79,7 @@ module Cyclid
79
79
  raise "failed to import key #{key_id}" unless success
80
80
 
81
81
  success = transport.exec \
82
- "gpg -a --export #{key_id} | sudo apt-key add -"
82
+ "sh -c 'gpg -a --export #{key_id} | apt-key add -'"
83
83
  raise "failed to add repository key #{key_id}" unless success
84
84
  end
85
85
 
@@ -26,6 +26,9 @@ module Cyclid
26
26
  transport.export_env('DEBIAN_FRONTEND' => 'noninteractive')
27
27
 
28
28
  if env.key? :repos
29
+ # Ensure apt-get-repository is available
30
+ transport.exec 'apt-get install -y software-properties-common'
31
+
29
32
  env[:repos].each do |repo|
30
33
  next unless repo.key? :url
31
34
 
@@ -42,13 +45,13 @@ module Cyclid
42
45
  end
43
46
  end
44
47
 
45
- success = transport.exec 'sudo apt-get update'
48
+ success = transport.exec 'apt-get update'
46
49
  raise 'failed to update repositories' unless success
47
50
  end
48
51
 
49
52
  if env.key? :packages
50
53
  success = transport.exec \
51
- "sudo -E apt-get install -y #{env[:packages].join(' ')}" \
54
+ "apt-get install -y #{env[:packages].join(' ')}" \
52
55
 
53
56
  raise "failed to install packages #{env[:packages].join(' ')}" unless success
54
57
  end
@@ -60,7 +63,7 @@ module Cyclid
60
63
  private
61
64
 
62
65
  def add_ppa_repository(transport, url)
63
- success = transport.exec "sudo apt-add-repository -y #{url}"
66
+ success = transport.exec "apt-add-repository -y #{url}"
64
67
  raise "failed to add repository #{url}" unless success
65
68
  end
66
69
 
@@ -74,7 +77,7 @@ module Cyclid
74
77
  fragment = "deb #{url} #{release} #{components}"
75
78
 
76
79
  success = transport.exec \
77
- "echo '#{fragment}' | sudo tee -a /etc/apt/sources.list.d/cyclid.list"
80
+ "sh -c \"echo '#{fragment}' | tee -a /etc/apt/sources.list.d/cyclid.list\""
78
81
  raise "failed to add repository #{url}" unless success
79
82
 
80
83
  return unless repo.key? :key_id
@@ -87,7 +90,7 @@ module Cyclid
87
90
  raise "failed to import key #{key_id}" unless success
88
91
 
89
92
  success = transport.exec \
90
- "gpg -a --export #{key_id} | sudo apt-key add -"
93
+ "sh -c 'gpg -a --export #{key_id} | apt-key add -'"
91
94
  raise "failed to add repository key #{key_id}" unless success
92
95
  end
93
96
 
@@ -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}"
43
+ success = transport.exec("git clone #{url}", ctx[:workspace])
44
44
  return false unless success
45
45
 
46
46
  # If a branch was given, check it out
@@ -145,7 +145,11 @@ module Cyclid
145
145
  end
146
146
 
147
147
  command << "cd #{path}" if path
148
- command << cmd
148
+ command << if @username == 'root'
149
+ cmd
150
+ else
151
+ "sudo -E #{cmd}"
152
+ end
149
153
  command.join(';')
150
154
  end
151
155
 
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+ # Copyright 2016 Liqwyd Ltd.
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+
17
+ $LOAD_PATH.push File.expand_path('../../app', __FILE__)
18
+
19
+ require 'require_all'
20
+ require 'logger'
21
+ require 'active_record'
22
+
23
+ ENV['RACK_ENV'] = ENV['RACK_ENV'] || 'development'
24
+
25
+ require 'cyclid/config'
26
+
27
+ # Top level module for the core Cyclid code; just stub out to provide the
28
+ # bare minimum required to inject data via. the models.
29
+ module Cyclid
30
+ class << self
31
+ attr_accessor :logger, :config
32
+
33
+ begin
34
+ Cyclid.logger = Logger.new(STDERR)
35
+
36
+ config_path = ENV['CYCLID_CONFIG'] || File.join(%w(/ etc cyclid config))
37
+ Cyclid.config = API::Config.new(config_path)
38
+ rescue StandardError => ex
39
+ abort "Failed to initialize: #{ex}"
40
+ end
41
+ end
42
+ end
43
+
44
+ require 'db'
45
+
46
+ version = (ARGV[0].split('=')[1].to_i if ARGV[0] =~ /VERSION=d+/)
47
+
48
+ current_version = ActiveRecord::Migrator.current_version
49
+
50
+ STDERR.puts '*' * 80
51
+ STDERR.puts "Current version: #{current_version}"
52
+ STDERR.puts '*' * 80
53
+
54
+ migrations_path = File.expand_path('../../db/migrate', __FILE__)
55
+
56
+ ActiveRecord::Migration.verbose = true
57
+ ActiveRecord::Migrator.migrate(migrations_path, version) do |migration|
58
+ next unless migration.version > current_version
59
+ STDERR.puts "#{migration.name}:#{migration.version}"
60
+ true
61
+ end
@@ -0,0 +1,8 @@
1
+ class CreateOrganization < ActiveRecord::Migration
2
+ def change
3
+ create_table :organizations do |t|
4
+ t.string :name, null: false, unique: true
5
+ t.string :owner_email, null: false
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ class CreateUser < ActiveRecord::Migration
2
+ def change
3
+ create_table :users do |t|
4
+ t.string :username, null: false, unique: true
5
+ t.string :email, null: false
6
+ t.string :password
7
+ t.string :secret
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,8 @@
1
+ class CreateJoins < ActiveRecord::Migration
2
+ def change
3
+ create_table :organizations_users, id: false do |t|
4
+ t.belongs_to :organization, index: true
5
+ t.belongs_to :user, index: true
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ class CreateUserPermissions < ActiveRecord::Migration
2
+ def change
3
+ create_table :userpermissions do |t|
4
+ t.boolean :admin, null: false, default: false
5
+ t.boolean :write, null: false, default: false
6
+ t.boolean :read, null: false, default: false
7
+
8
+ t.belongs_to :user, index: true
9
+ t.belongs_to :organization, index:true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ class CreateStage < ActiveRecord::Migration
2
+ def change
3
+ create_table :stages do |t|
4
+ t.string :name, null: false
5
+ t.string :version, null: false, default: '0.0.1'
6
+
7
+ t.belongs_to :organization, index: true
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ class CreateStep < ActiveRecord::Migration
2
+ def change
3
+ create_table :steps do |t|
4
+ t.integer :sequence, null: false
5
+ t.text :action
6
+
7
+ t.belongs_to :stage, index: true
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ class CreateJobRecord < ActiveRecord::Migration
2
+ def change
3
+ create_table :job_records do |t|
4
+ t.string :job_name, index: true
5
+ t.string :job_version
6
+
7
+ t.datetime :started
8
+ t.datetime :ended
9
+
10
+ t.integer :status
11
+ t.text :log
12
+
13
+ t.text :job
14
+
15
+ t.belongs_to :organization, index: true
16
+ t.belongs_to :user, index: true
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ class CreatePluginConfig < ActiveRecord::Migration
2
+ def change
3
+ create_table :plugin_configs do |t|
4
+ t.string :plugin
5
+ t.string :version
6
+
7
+ t.text :config
8
+
9
+ t.belongs_to :organization, index: true
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ class AddEncryptionToOrganizations < ActiveRecord::Migration
2
+ def change
3
+ # RSA keys in DER format
4
+ add_column :organizations, :rsa_private_key, :binary, null: false, default: 0
5
+ add_column :organizations, :rsa_public_key, :binary, null: false, default: 0
6
+
7
+ # Salt for use with other encryption schemes E.g. AES
8
+ add_column :organizations, :salt, :string, null: false, default: 0
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ class AddNameToUsers < ActiveRecord::Migration
2
+ def change
3
+ add_column :users, :name, :string
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'active_support/core_ext/numeric'
2
+
3
+ class ModifyJobLog < ActiveRecord::Migration
4
+ def up
5
+ change_column(:job_records, :log, :text, limit: 16.megabytes - 1)
6
+ end
7
+ end
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(version: 20160715161156) do
14
+ ActiveRecord::Schema.define(version: 20161218133843) do
15
15
 
16
16
  create_table "job_records", force: :cascade do |t|
17
17
  t.string "job_name"
@@ -19,7 +19,7 @@ ActiveRecord::Schema.define(version: 20160715161156) do
19
19
  t.datetime "started"
20
20
  t.datetime "ended"
21
21
  t.integer "status"
22
- t.text "log"
22
+ t.text "log", limit: 16777215
23
23
  t.text "job"
24
24
  t.integer "organization_id"
25
25
  t.integer "user_id"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  module Cyclid
3
3
  module Api
4
- VERSION = '0.2.3'
4
+ VERSION = '0.2.4'
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.2.3
4
+ version: 0.2.4
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: 2016-10-25 00:00:00.000000000 Z
11
+ date: 2016-12-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -192,20 +192,6 @@ dependencies:
192
192
  - - "~>"
193
193
  - !ruby/object:Gem::Version
194
194
  version: '4.1'
195
- - !ruby/object:Gem::Dependency
196
- name: mysql
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - "~>"
200
- - !ruby/object:Gem::Version
201
- version: '2.9'
202
- type: :runtime
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - "~>"
207
- - !ruby/object:Gem::Version
208
- version: '2.9'
209
195
  - !ruby/object:Gem::Dependency
210
196
  name: slack-notifier
211
197
  requirement: !ruby/object:Gem::Requirement
@@ -319,23 +305,52 @@ dependencies:
319
305
  - !ruby/object:Gem::Version
320
306
  version: '0'
321
307
  - !ruby/object:Gem::Dependency
322
- name: mist-client
308
+ name: fog-core
323
309
  requirement: !ruby/object:Gem::Requirement
324
310
  requirements:
325
311
  - - "~>"
326
312
  - !ruby/object:Gem::Version
327
- version: '0'
313
+ version: '1.43'
328
314
  type: :runtime
329
315
  prerelease: false
330
316
  version_requirements: !ruby/object:Gem::Requirement
331
317
  requirements:
332
318
  - - "~>"
333
319
  - !ruby/object:Gem::Version
334
- version: '0'
320
+ version: '1.43'
321
+ - !ruby/object:Gem::Dependency
322
+ name: fog-google
323
+ requirement: !ruby/object:Gem::Requirement
324
+ requirements:
325
+ - - "~>"
326
+ - !ruby/object:Gem::Version
327
+ version: '0.4'
328
+ type: :runtime
329
+ prerelease: false
330
+ version_requirements: !ruby/object:Gem::Requirement
331
+ requirements:
332
+ - - "~>"
333
+ - !ruby/object:Gem::Version
334
+ version: '0.4'
335
+ - !ruby/object:Gem::Dependency
336
+ name: google-api-client
337
+ requirement: !ruby/object:Gem::Requirement
338
+ requirements:
339
+ - - "~>"
340
+ - !ruby/object:Gem::Version
341
+ version: 0.8.6
342
+ type: :runtime
343
+ prerelease: false
344
+ version_requirements: !ruby/object:Gem::Requirement
345
+ requirements:
346
+ - - "~>"
347
+ - !ruby/object:Gem::Version
348
+ version: 0.8.6
335
349
  description: The Cyclid CI system
336
350
  email: contact@cyclid.io
337
351
  executables:
338
352
  - cyclid-db-init
353
+ - cyclid-db-migrate
339
354
  extensions: []
340
355
  extra_rdoc_files: []
341
356
  files:
@@ -380,6 +395,7 @@ files:
380
395
  - app/cyclid/plugins/action/email.rb
381
396
  - app/cyclid/plugins/action/email/html.erb
382
397
  - app/cyclid/plugins/action/email/text.erb
398
+ - app/cyclid/plugins/action/log.rb
383
399
  - app/cyclid/plugins/action/script.rb
384
400
  - app/cyclid/plugins/action/slack.rb
385
401
  - app/cyclid/plugins/action/slack/note.erb
@@ -394,7 +410,7 @@ files:
394
410
  - app/cyclid/plugins/api/github/pull_request.rb
395
411
  - app/cyclid/plugins/api/github/push.rb
396
412
  - app/cyclid/plugins/builder.rb
397
- - app/cyclid/plugins/builder/mist.rb
413
+ - app/cyclid/plugins/builder/google.rb
398
414
  - app/cyclid/plugins/dispatcher.rb
399
415
  - app/cyclid/plugins/dispatcher/local.rb
400
416
  - app/cyclid/plugins/provisioner.rb
@@ -411,6 +427,18 @@ files:
411
427
  - app/cyclid/sinatra/warden/strategies/hmac.rb
412
428
  - app/db.rb
413
429
  - bin/cyclid-db-init
430
+ - bin/cyclid-db-migrate
431
+ - db/migrate/20160208175128_create_organization.rb
432
+ - db/migrate/20160209092652_create_user.rb
433
+ - db/migrate/20160211172351_create_joins.rb
434
+ - db/migrate/20160214105837_create_user_permissions.rb
435
+ - db/migrate/20160216165211_create_stage.rb
436
+ - db/migrate/20160216165454_create_step.rb
437
+ - db/migrate/20160225133151_create_job_record.rb
438
+ - db/migrate/20160308145556_create_plugin_config.rb
439
+ - db/migrate/20160325120748_add_encryption_to_organizations.rb
440
+ - db/migrate/20160715161156_add_name_to_users.rb
441
+ - db/migrate/20161218133843_modify_job_log.rb
414
442
  - db/schema.rb
415
443
  - lib/cyclid/app.rb
416
444
  - lib/cyclid/version.rb
@@ -1,107 +0,0 @@
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 'mist/config'
17
- require 'mist/pool'
18
- require 'mist/client'
19
-
20
- # Top level module for the core Cyclid code.
21
- module Cyclid
22
- # Module for the Cyclid API
23
- module API
24
- # Module for Cyclid Plugins
25
- module Plugins
26
- # Mist build host
27
- class MistHost < BuildHost
28
- # SSH is the only acceptable Transport
29
- def transports
30
- ['ssh']
31
- end
32
- end
33
-
34
- # Mist builder. Calls out to Mist to obtain a build host instance.
35
- class Mist < Builder
36
- def initialize
37
- mist_config_file = ENV.fetch('MIST_CONFIG', File.join(%w(/ etc mist config)))
38
- @config = ::Mist::Config.new(mist_config_file)
39
-
40
- pool = ::Mist::Pool.get(@config.servers)
41
- @client = ::Mist::Client.new(pool)
42
- end
43
-
44
- # Create & return a build host
45
- def get(args = {})
46
- args.symbolize_keys!
47
-
48
- Cyclid.logger.debug "mist: args=#{args}"
49
-
50
- # If there is one, split the 'os' into a 'distro' and 'release'
51
- if args.key? :os
52
- match = args[:os].match(/\A(\w*)_(.*)\Z/)
53
- distro = match[1] if match
54
- release = match[2] if match
55
- else
56
- # No OS was specified; use the default
57
- # XXX Defaults should be configurable
58
- distro = 'ubuntu'
59
- release = 'trusty'
60
- end
61
-
62
- begin
63
- result = @client.call(:create, distro: distro, release: release)
64
- Cyclid.logger.debug "mist result=#{result}"
65
-
66
- raise "failed to create build host: #{result['message']}" \
67
- unless result['status']
68
-
69
- buildhost = MistHost.new(name: result['name'],
70
- host: result['ip'],
71
- username: result['username'],
72
- workspace: "/home/#{result['username']}",
73
- password: nil,
74
- key: @config.ssh_private_key,
75
- server: result['server'],
76
- distro: distro,
77
- release: release)
78
- rescue MessagePack::RPC::TimeoutError => ex
79
- Cyclid.logger.error "Mist create call timedout: #{ex}"
80
- raise "mist failed: #{ex}"
81
- rescue StandardError => ex
82
- Cyclid.logger.error "couldn't get a build host from Mist: #{ex}"
83
- raise "mist failed: #{ex}"
84
- end
85
-
86
- Cyclid.logger.debug "mist buildhost=#{buildhost.inspect}"
87
- return buildhost
88
- end
89
-
90
- # Destroy the build host
91
- def release(_transport, buildhost)
92
- name = buildhost[:name]
93
- server = buildhost[:server]
94
-
95
- begin
96
- @client.call(:destroy, name: name, server: server)
97
- rescue MessagePack::RPC::TimeoutError => ex
98
- Cyclid.logger.error "Mist destroy timed out: #{ex}"
99
- end
100
- end
101
-
102
- # Register this plugin
103
- register_plugin 'mist'
104
- end
105
- end
106
- end
107
- end