twistlock-control 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rubocop.yml +6 -0
  4. data/Gemfile +16 -0
  5. data/Guardfile +30 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +47 -0
  8. data/Rakefile +1 -0
  9. data/features/provisioning_service_instances.feature +14 -0
  10. data/features/step_definitions/provisioning_service_instances_steps.rb +33 -0
  11. data/features/support/env.rb +22 -0
  12. data/lib/twistlock_control.rb +65 -0
  13. data/lib/twistlock_control/actions.rb +7 -0
  14. data/lib/twistlock_control/actions/container.rb +42 -0
  15. data/lib/twistlock_control/actions/container_instance.rb +28 -0
  16. data/lib/twistlock_control/actions/provisioner.rb +25 -0
  17. data/lib/twistlock_control/actions/service.rb +18 -0
  18. data/lib/twistlock_control/actions/service_instance.rb +40 -0
  19. data/lib/twistlock_control/collections.rb +22 -0
  20. data/lib/twistlock_control/entities.rb +11 -0
  21. data/lib/twistlock_control/entities/composite_service.rb +86 -0
  22. data/lib/twistlock_control/entities/container.rb +66 -0
  23. data/lib/twistlock_control/entities/container_instance.rb +22 -0
  24. data/lib/twistlock_control/entities/provisioner.rb +24 -0
  25. data/lib/twistlock_control/entities/provisioning_configuration.rb +65 -0
  26. data/lib/twistlock_control/entities/service.rb +19 -0
  27. data/lib/twistlock_control/entities/service_instance.rb +122 -0
  28. data/lib/twistlock_control/entity.rb +63 -0
  29. data/lib/twistlock_control/provisioner_api.rb +43 -0
  30. data/lib/twistlock_control/rethinkdb_repository.rb +74 -0
  31. data/lib/twistlock_control/version.rb +4 -0
  32. data/spec/actions/container_spec.rb +19 -0
  33. data/spec/actions/provisioner_spec.rb +37 -0
  34. data/spec/actions/service_instance_spec.rb +47 -0
  35. data/spec/collections_spec.rb +14 -0
  36. data/spec/entities/composite_service_spec.rb +126 -0
  37. data/spec/entities/container_spec.rb +8 -0
  38. data/spec/entities/provisioner_spec.rb +56 -0
  39. data/spec/entities/service_instance_spec.rb +33 -0
  40. data/spec/entities/shared_service_specs.rb +4 -0
  41. data/spec/provisioner_api_spec.rb +35 -0
  42. data/spec/rethinkdb_repository_spec.rb +15 -0
  43. data/spec/spec_helper.rb +25 -0
  44. data/twistlock-control.gemspec +29 -0
  45. metadata +172 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a2dc8b1d3d971e07d8c0b16a4dfc4454e70ab808
4
+ data.tar.gz: a37cadbbaf5ef9f0f0541905cb6479dcb5992157
5
+ SHA512:
6
+ metadata.gz: 2bc1a81f14f78aa5e612ebef2ff2acbebae0cb3bbaa397e70f654b43ee35ad9ce884d27dc0836b882aa0d13e0cb25481d44b9c6b38179833581dbf1941b77f74
7
+ data.tar.gz: 411fb2e9bdcd275d36754054ee3d1d6cbc7607929ca8003821dc86d5825d9a203ca8efa32a89949510b5189b7baac0b925395cdbd2ad2e7608d2a6b66389c45e
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ rethinkdb_data
data/.rubocop.yml ADDED
@@ -0,0 +1,6 @@
1
+ Style/Tab:
2
+ Enabled: false
3
+ Style/IndentationWidth:
4
+ Width: 1
5
+ Metrics/LineLength:
6
+ Max: 120
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rspec'
4
+ gem 'rspec-mocks'
5
+ gem 'webmock'
6
+ gem 'guard'
7
+ gem 'guard-rspec'
8
+ gem 'cucumber', require: false, group: :development
9
+ gem 'guard-cucumber', group: :development
10
+ gem 'rubocop', require: false
11
+ gem 'guard-rubocop', group: :development
12
+ gem 'simplecov', require: false, group: :test
13
+ gem 'psych'
14
+
15
+ # Specify your gem's dependencies in twistlock-control-models.gemspec
16
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,30 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ # Note: The cmd option is now required due to the increasing number of ways
5
+ # rspec may be run, below are examples of the most common uses.
6
+ # * bundler: 'bundle exec rspec'
7
+ # * bundler binstubs: 'bin/rspec'
8
+ # * spring: 'bin/rsspec' (This will use spring if running and you have
9
+ # installed the spring binstubs per the docs)
10
+ # * zeus: 'zeus rspec' (requires the server to be started separetly)
11
+ # * 'just' rspec: 'rspec'
12
+ guard :rspec, cmd: 'bundle exec rspec -c' do
13
+ watch(/^spec\/.+_spec\.rb$/) { 'spec' }
14
+ watch(/^lib\/.+\.rb$/) { 'spec' }
15
+ watch('spec/spec_helper.rb') { 'spec' }
16
+ end
17
+
18
+ guard :rubocop do
19
+ watch(/.+\.rb$/)
20
+ watch(/(?:.+\/)?\.rubocop\.yml$/) { |m| File.dirname(m[0]) }
21
+ end
22
+
23
+ guard 'cucumber' do
24
+ watch(/^features\/.+\.feature$/)
25
+ watch(%r{^features\/support\/.+$}) { 'features' }
26
+
27
+ watch(%r{^features/step_definitions/(.+)_steps\.rb$}) do |m|
28
+ Dir[File.join("**/#{m[1]}.feature")][0] || 'features'
29
+ end
30
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Tinco Andringa
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,47 @@
1
+ # TwistlockControl
2
+
3
+ The Twistlock Control system.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'twistlock-control'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install twistlock-control
18
+
19
+ ## Usage
20
+
21
+ The TwistlockControl system has a user interface called Rotterdam. Rotterdam executes
22
+ the logic functions in here to manipulate the Twistlock provisioners.
23
+
24
+ Actions that Rotterdam needs that this library implements:
25
+
26
+ * Defining services
27
+ * Importing container descriptions
28
+ * Creating service instances
29
+ * Configuring service instances
30
+ * Adding provisioners
31
+ * Provisioning service instances on provisioners
32
+
33
+ To aid these actions, Rotterdam needs to subscribe to the following resources:
34
+
35
+ * Defined services
36
+ * Imported container descriptions
37
+ * Service instances
38
+ * Provisioners
39
+ * Container instances
40
+
41
+ ## Contributing
42
+
43
+ 1. Fork it
44
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
45
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
46
+ 4. Push to the branch (`git push origin my-new-feature`)
47
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,14 @@
1
+ Feature: Provisioning service instances
2
+
3
+ In order for the user to make use of a service instance, it has to be
4
+ provisioned on a machine that's connected to Twistlock.
5
+
6
+ Scenario: A simple one-container service
7
+
8
+ Given a user has defined a service
9
+ Given a provisioner is configured
10
+ And a user has created an instance of that service
11
+ Then the user should be presented with a configurable representation of the service
12
+ When the user configures the service instance
13
+ And the user gives the provision command
14
+ Then a container instance should be provisioned
@@ -0,0 +1,33 @@
1
+ Given(/^(?:a|the) user has defined a service$/) do
2
+ dir = Dir.pwd + '/../redis-container'
3
+ @service = Container.new(name: 'redis', url: dir)
4
+ @service.save
5
+ end
6
+
7
+ Given(/^a provisioner is configured$/) do
8
+ @provisioner = Provisioner.new(name: 'my-provisioner', url: 'localhost')
9
+ @provisioner.save
10
+ end
11
+
12
+ Given(/^(?:a|the) user has created an instance of that service$/) do
13
+ @service_instance = TwistlockControl::Actions::ServiceInstance.add('my-instance', @service)
14
+ end
15
+
16
+ Then(/^(?:a|the) user should be presented with a configurable representation of the service$/) do
17
+ @container_configuration = @service_instance.container_configurations.first
18
+ end
19
+
20
+ When(/^(?:a|the) user configures the service instance$/) do
21
+ @container_configuration.provisioner = @provisioner
22
+ end
23
+
24
+ When(/^(?:a|the) user gives the provision command$/) do
25
+ api_double = double
26
+ expect(api_double).to receive(:provision_container).and_return({})
27
+ expect(@provisioner).to receive(:api).and_return(api_double)
28
+ TwistlockControl::Actions::ContainerInstance.add(@container_configuration)
29
+ end
30
+
31
+ Then(/^a container instance should be provisioned$/) do
32
+ expect(ContainerInstance.all.length).to equal(1)
33
+ end
@@ -0,0 +1,22 @@
1
+ require 'twistlock_control'
2
+
3
+ require 'cucumber/rspec/doubles'
4
+
5
+ include TwistlockControl
6
+
7
+ def repositories
8
+ %w(provisioners services service_instances container_instances)
9
+ .map { |n| TwistlockControl::RethinkDBRepository[n] }
10
+ end
11
+
12
+ Before do
13
+ TwistlockControl.configure do |c|
14
+ c.database_name = 'test'
15
+ end
16
+
17
+ repositories.each(&:create_table)
18
+ end
19
+
20
+ After do
21
+ repositories.each(&:delete_all)
22
+ end
@@ -0,0 +1,65 @@
1
+ require 'connection_pool'
2
+ require 'rethinkdb'
3
+
4
+ require_relative 'twistlock_control/provisioner_api'
5
+ require_relative 'twistlock_control/rethinkdb_repository'
6
+
7
+ require_relative 'twistlock_control/entities'
8
+ require_relative 'twistlock_control/actions'
9
+ require_relative 'twistlock_control/collections'
10
+
11
+ #
12
+ # TwistLockControl main module.
13
+ #
14
+ # Configure TwistlockControl by calling `TwistlockControl.configure`
15
+ # and passing it a block in which you set the attributes.
16
+ #
17
+ module TwistlockControl
18
+ class << self
19
+ attr_accessor :connection_pool_size,
20
+ :connection_pool_timeout,
21
+ :rethinkdb_host,
22
+ :rethinkdb_port,
23
+ :database_name
24
+
25
+ def configure
26
+ yield self
27
+
28
+ set_defaults
29
+
30
+ setup_connection_pool
31
+ end
32
+
33
+ def database
34
+ RethinkDB::RQL.new.db(database_name)
35
+ end
36
+
37
+ def with_connection
38
+ @connection_pool.with do |conn|
39
+ yield conn
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def set_defaults
46
+ @connection_pool_size ||= 5
47
+ @connection_pool_timeout ||= 5
48
+ @rethinkdb_host ||= 'localhost'
49
+ @rethinkdb_port ||= 28_015
50
+ @database_name ||= 'twistlock-control'
51
+ end
52
+
53
+ def setup_connection_pool
54
+ @connection_pool = ConnectionPool.new(
55
+ size: connection_pool_size,
56
+ timeout: connection_pool_timeout
57
+ ) do
58
+ RethinkDB::Connection.new(
59
+ host: rethinkdb_host,
60
+ port: rethinkdb_port
61
+ )
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,7 @@
1
+ %w(
2
+ container
3
+ container_instance
4
+ provisioner
5
+ service
6
+ service_instance
7
+ ).each { |action| require_relative("actions/#{action}") }
@@ -0,0 +1,42 @@
1
+ module TwistlockControl
2
+ # Actions that Rotterdam needs that this library implements:
3
+ module Actions
4
+ # * Importing container descriptions
5
+ module Container
6
+ class << self
7
+ def add(properties)
8
+ container = Entities::Container.new(properties)
9
+ synchronize_description(container)
10
+ container
11
+ end
12
+
13
+ def update
14
+ fail 'not implemented'
15
+ end
16
+
17
+ def remove
18
+ fail 'not implemented'
19
+ end
20
+
21
+ def synchronize_description(container)
22
+ container.description = fetch_container_description(container)
23
+ container.save
24
+ end
25
+
26
+ private
27
+
28
+ def fetch_container_description(container)
29
+ nonce = SecureRandom.hex[0..7]
30
+ dirname = "/tmp/#{container.name}-#{nonce}"
31
+ FileUtils.mkdir_p dirname
32
+ Dir.chdir(dirname) do
33
+ `git clone -n --depth=1 #{container.url} .`
34
+ `git checkout HEAD twistlock.yml`
35
+ result = `cat twistlock.yml && rm -rf #{dirname}`
36
+ Entities::ContainerDescription.new(YAML.load(result))
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,28 @@
1
+ module TwistlockControl
2
+ # Actions that Rotterdam needs that this library implements:
3
+ module Actions
4
+ # * Provisioning service instances on provisioners
5
+ module ContainerInstance
6
+ class << self
7
+ # Provision takes a ContainerConfiguration and when
8
+ # it is done provisioning it will notify the ContainerConfiguration
9
+ # of the ip address and container id of the provisioned container.
10
+ def add(container_configuration)
11
+ # TODO: figure out how to have internal actions like provisioning
12
+ # without polluting the entities with logic
13
+ provisioner = container_configuration.provisioner.api
14
+ properties = provisioner.provision_container(container_configuration)
15
+ instance = Entities::ContainerInstance.new(properties)
16
+ instance.save
17
+ instance
18
+ end
19
+
20
+ def update
21
+ end
22
+
23
+ def remove
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ module TwistlockControl
2
+ # Actions that Rotterdam needs that this library implements:
3
+ module Actions
4
+ # * Adding provisioners
5
+ module Provisioner
6
+ class << self
7
+ def add(properties)
8
+ provisioner = Entities::Provisioner.new(properties)
9
+ provisioner.save
10
+ provisioner
11
+ end
12
+
13
+ def update(id, properties)
14
+ provisioner = Entities::Provisioner.find_by_id(id)
15
+ provisioner.attributes = provisioner.attributes.merge properties
16
+ provisioner.save
17
+ end
18
+
19
+ def remove(id)
20
+ Entities::Provisioner.delete(id)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,18 @@
1
+ module TwistlockControl
2
+ # Actions that Rotterdam needs that this library implements:
3
+ module Actions
4
+ # * Defining services
5
+ module Service
6
+ class << self
7
+ def add
8
+ end
9
+
10
+ def update
11
+ end
12
+
13
+ def remove
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,40 @@
1
+ module TwistlockControl
2
+ # Actions that Rotterdam needs that this library implements:
3
+ module Actions
4
+ # * Creating service instances
5
+ # * Configuring service instances
6
+ module ServiceInstance
7
+ class << self
8
+ def add(name, service)
9
+ configuration = build_configuration(service)
10
+ instance = Entities::ServiceInstance.new(service_id: service.id, name: name, configuration: configuration)
11
+ instance.save
12
+ instance
13
+ end
14
+
15
+ def update
16
+ fail 'not implemented'
17
+ end
18
+
19
+ def remove
20
+ fail 'not implemented'
21
+ end
22
+
23
+ private
24
+
25
+ def build_configuration(service)
26
+ case service.service_type
27
+ when :container then Entities::ContainerConfiguration.new(service_id: service.id)
28
+ when :composite
29
+ Entities::CompositeConfiguration.new(
30
+ service_id: service.id,
31
+ configurations: service.services.map { |s| build_configuration(s) }
32
+ )
33
+ else
34
+ fail "Unknown service type: #{service.service_type}"
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end