cyclid 0.2.3 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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