From 5fb3a15d1934f6cbd79e82cd3ca5fe79ecaeb35d Mon Sep 17 00:00:00 2001 From: Rupak Ganguly Date: Mon, 29 Sep 2014 14:24:40 -0400 Subject: [PATCH 1/5] Enable service to use volumes_from and generate a volumes_from flag in the docker string. --- app/models/concerns/docker_runnable.rb | 7 +++ app/models/service.rb | 18 +++++++ app/models/shared_volume.rb | 23 +++++++++ .../20140929181001_create_shared_volumes.rb | 12 +++++ db/schema.rb | 13 ++++- spec/models/service_spec.rb | 29 ++++++++++- spec/models/shared_volume_spec.rb | 51 +++++++++++++++++++ .../support/shared/docker_runnable_example.rb | 30 ++++++++--- 8 files changed, 173 insertions(+), 10 deletions(-) create mode 100644 app/models/shared_volume.rb create mode 100644 db/migrate/20140929181001_create_shared_volumes.rb create mode 100644 spec/models/shared_volume_spec.rb diff --git a/app/models/concerns/docker_runnable.rb b/app/models/concerns/docker_runnable.rb index 2821b01..961b537 100644 --- a/app/models/concerns/docker_runnable.rb +++ b/app/models/concerns/docker_runnable.rb @@ -12,6 +12,7 @@ def docker_run_string expose_flags, environment_flags, volume_flags, + volumes_from_flags, from, command ].flatten.compact.join(' ').strip @@ -64,4 +65,10 @@ def volume_flags end end + def volumes_from_flags + return unless volumes_from && volumes_from.present? + volumes_from.map do |svol| + "--volumes-from #{svol.exported_from_service_name}" + end + end end diff --git a/app/models/service.rb b/app/models/service.rb index 216726d..a3f6dde 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -15,6 +15,10 @@ class Service < ActiveRecord::Base class_name: 'ServiceLink', foreign_key: 'linked_from_service_id', dependent: :destroy + has_many :volumes_from, + class_name: 'SharedVolume', + foreign_key: 'mounted_on_service_id', + dependent: :destroy # Only here for the dependent destroy. Want to remove any service link joins that may point # to this model as the 'linked_to_service' @@ -23,6 +27,13 @@ class Service < ActiveRecord::Base foreign_key: 'linked_to_service_id', dependent: :destroy + # Only here for the dependent destroy. Want to remove any service mount joins that may point + # to this model as the 'mounted_on_service' + has_many :mounted_volumes, + class_name: 'SharedVolume', + foreign_key: 'exported_from_service_id', + dependent: :destroy + serialize :ports, Array serialize :expose, Array serialize :environment, Array @@ -90,6 +101,13 @@ def update_with_relationships(attributes) ) end + attributes[:volumes_from] ||= [] + attributes[:volumes_from].map! do |svol| + self.volumes_from.find_or_initialize_by( + exported_from_service_id: svol[:service_id] + ) + end + attributes[:volumes] ||= [] attributes[:volumes].map! { |vol| vol.to_hash } diff --git a/app/models/shared_volume.rb b/app/models/shared_volume.rb new file mode 100644 index 0000000..4e5e392 --- /dev/null +++ b/app/models/shared_volume.rb @@ -0,0 +1,23 @@ +class SharedVolume < ActiveRecord::Base + self.table_name = 'shared_volumes' + + belongs_to :exported_from_service, class_name: 'Service' + + validates :exported_from_service, uniqueness: { scope: :mounted_on_service_id }, presence: true + validate :cannot_mount_self + + def exported_from_service_name + "#{exported_from_service.name}" + end + + private + + def cannot_mount_self + if mounted_on_service_id.present? && + exported_from_service_id.present? && + mounted_on_service_id == exported_from_service_id + + errors.add(:base, "can't mount self") + end + end +end diff --git a/db/migrate/20140929181001_create_shared_volumes.rb b/db/migrate/20140929181001_create_shared_volumes.rb new file mode 100644 index 0000000..279a03c --- /dev/null +++ b/db/migrate/20140929181001_create_shared_volumes.rb @@ -0,0 +1,12 @@ +class CreateSharedVolumes < ActiveRecord::Migration + def change + create_table :shared_volumes do |t| + t.references :exported_from_service, index: true + t.references :mounted_on_service, index: true + + t.timestamps + end + + add_index :shared_volumes, [:exported_from_service_id, :mounted_on_service_id], unique: true, name: 'index_shared_volume_keys' + end +end diff --git a/db/schema.rb b/db/schema.rb index 6c63802..4923b3e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20140919202446) do +ActiveRecord::Schema.define(version: 20140929181001) do create_table "app_categories", force: true do |t| t.string "name" @@ -98,6 +98,17 @@ add_index "services", ["app_id"], name: "index_services_on_app_id" add_index "services", ["name"], name: "index_services_on_name" + create_table "shared_volumes", force: true do |t| + t.integer "exported_from_service_id" + t.integer "mounted_on_service_id" + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "shared_volumes", ["exported_from_service_id", "mounted_on_service_id"], name: "index_shared_volume_keys", unique: true + add_index "shared_volumes", ["exported_from_service_id"], name: "index_shared_volumes_on_exported_from_service_id" + add_index "shared_volumes", ["mounted_on_service_id"], name: "index_shared_volumes_on_mounted_on_service_id" + create_table "template_repos", force: true do |t| t.string "name" t.datetime "created_at" diff --git a/spec/models/service_spec.rb b/spec/models/service_spec.rb index 59836c3..a9fccd5 100644 --- a/spec/models/service_spec.rb +++ b/spec/models/service_spec.rb @@ -180,7 +180,7 @@ double(:image_status, info: { 'Config' => { - 'ExposedPorts' => {'3000/tcp' => {} } + 'ExposedPorts' => { '3000/tcp' => {} } } }) end @@ -280,6 +280,33 @@ end end + context 'when volumes_from are not provided' do + it 'updates with an empty volumes_from list' do + expect(subject).to receive(:update).with(hash_including(volumes_from: [])) + subject.update_with_relationships(attrs) + end + + end + + context 'when volumes_from are provided' do + let(:attrs_with_volumes_from) do + attrs.merge( + volumes_from: [{ service_id: 1 }] + ) + end + + let(:shared_volume) { SharedVolume.new(exported_from_service_id: 1) } + + before do + subject.stub_chain(:volumes_from, :find_or_initialize_by).and_return(shared_volume) + end + + it 'populates the related shared volumes' do + expect(subject).to receive(:update).with(hash_including(volumes_from: [shared_volume])) + subject.update_with_relationships(attrs_with_volumes_from) + end + end + context 'when ports are not provided' do it 'updates with an empty ports list' do expect(subject).to receive(:update).with(hash_including(ports: [])) diff --git a/spec/models/shared_volume_spec.rb b/spec/models/shared_volume_spec.rb new file mode 100644 index 0000000..1bacd7c --- /dev/null +++ b/spec/models/shared_volume_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' + +describe SharedVolume do + it { should belong_to(:exported_from_service) } + + describe 'validations' do + + it { should validate_presence_of :exported_from_service } + + describe 'uniqueness validations' do + before do + # we need a record in the DB for the uniqueness validations to work + vol_from = Service.create!(name: 'vol_from') + mounted_on = Service.create!(name: 'mounted_on') + SharedVolume.create!( + exported_from_service: vol_from, + mounted_on_service_id: mounted_on.id + ) + end + + it { should validate_uniqueness_of(:exported_from_service).scoped_to(:mounted_on_service_id) } + end + + describe 'mounting self' do + + it 'errors when volume from and mounted on service ids match' do + subject.exported_from_service_id = 3 + subject.mounted_on_service_id = 3 + expect(subject.valid?).to be_false + expect(subject.errors[:base]).to include "can't mount self" + end + + it 'does not error if one of the ids is nil' do + subject.exported_from_service = Service.new + expect(subject.valid?).to be_true + end + end + end + + describe '#exported_from_service_name' do + let(:exported_from_service) { Service.new(name: 'my_service') } + + before do + subject.exported_from_service = exported_from_service + end + + it 'returns the volumes_from service name ' do + expect(subject.exported_from_service_name).to eql 'my_service' + end + end +end diff --git a/spec/support/shared/docker_runnable_example.rb b/spec/support/shared/docker_runnable_example.rb index 6c7c0a0..d91485f 100644 --- a/spec/support/shared/docker_runnable_example.rb +++ b/spec/support/shared/docker_runnable_example.rb @@ -35,7 +35,7 @@ model.ports = [{ 'host_interface' => '0.0.0.0', 'host_port' => '8000', - 'container_port' => '3000', + 'container_port' => '3000' }] end @@ -48,10 +48,10 @@ before do model.ports = [{ - 'host_interface' => nil, - 'host_port' => '', - 'container_port' => '3000', - }] + 'host_interface' => nil, + 'host_port' => '', + 'container_port' => '3000' + }] end it 'does not include the colon affixed to the host port info' do @@ -60,13 +60,12 @@ end end - context 'when the UDP protocol is specified' do before do model.ports = [{ 'container_port' => '3000', - 'proto' => 'udp', + 'proto' => 'udp' }] end @@ -81,7 +80,7 @@ before do model.ports = [{ 'container_port' => '3000', - 'proto' => 'tcp', + 'proto' => 'tcp' }] end @@ -145,6 +144,21 @@ expect(model.docker_run_string).to include expected end end + + context 'when volumes_from flags are specified' do + + before do + exported_from_service = Service.new(name: 'foobar') + vol_from = SharedVolume.new(exported_from_service: exported_from_service) + model.volumes_from << vol_from + end + + it 'generates a docker command with --volumes-from' do + expected = '--volumes-from foobar' + expect(model.docker_run_string).to include expected + end + end + end describe '#docker_status' do From cf8c47ed56f94a0293c78ab9e55e2e97e1cd64ff Mon Sep 17 00:00:00 2001 From: Rupak Ganguly Date: Mon, 29 Sep 2014 15:12:33 -0400 Subject: [PATCH 2/5] Add serializers for service and shared_volume. --- app/serializers/service_serializer.rb | 2 ++ app/serializers/shared_volume_serializer.rb | 14 +++++++++++++ spec/serializers/service_serializer_spec.rb | 3 ++- .../shared_volume_serializer_spec.rb | 20 +++++++++++++++++++ 4 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 app/serializers/shared_volume_serializer.rb create mode 100644 spec/serializers/shared_volume_serializer_spec.rb diff --git a/app/serializers/service_serializer.rb b/app/serializers/service_serializer.rb index 2eba954..e196d38 100644 --- a/app/serializers/service_serializer.rb +++ b/app/serializers/service_serializer.rb @@ -11,6 +11,8 @@ class ServiceSerializer < ActiveModel::Serializer has_many :links, serializer: ServiceLinkSerializer + has_many :volumes_from, serializer: SharedVolumeSerializer + def load_state service_state[:load_state] end diff --git a/app/serializers/shared_volume_serializer.rb b/app/serializers/shared_volume_serializer.rb new file mode 100644 index 0000000..cca027c --- /dev/null +++ b/app/serializers/shared_volume_serializer.rb @@ -0,0 +1,14 @@ +class SharedVolumeSerializer < ActiveModel::Serializer + self.root = false + + attributes :service_id, :service_name, :errors + + def service_id + object.exported_from_service.id + end + + def service_name + object.exported_from_service.name + end + +end diff --git a/spec/serializers/service_serializer_spec.rb b/spec/serializers/service_serializer_spec.rb index 6273239..2534ba2 100644 --- a/spec/serializers/service_serializer_spec.rb +++ b/spec/serializers/service_serializer_spec.rb @@ -8,7 +8,7 @@ double(:image_status, info: { 'Config' => { - 'ExposedPorts' => {'3000/tcp' => {} } + 'ExposedPorts' => { '3000/tcp' => {} } } }) end @@ -29,6 +29,7 @@ :ports, :expose, :volumes, + :volumes_from, :command, :app, :categories, diff --git a/spec/serializers/shared_volume_serializer_spec.rb b/spec/serializers/shared_volume_serializer_spec.rb new file mode 100644 index 0000000..f1d5bd9 --- /dev/null +++ b/spec/serializers/shared_volume_serializer_spec.rb @@ -0,0 +1,20 @@ +require 'spec_helper' + +describe SharedVolumeSerializer do + let(:service) { Service.new } + let(:shared_volume_model) { SharedVolume.new } + + before do + shared_volume_model.exported_from_service = service + end + + it 'exposes the attributes to be jsonified' do + serialized = described_class.new(shared_volume_model).as_json + expected_keys = [ + :service_id, + :service_name, + :errors + ] + expect(serialized.keys).to match_array expected_keys + end +end From efcdae549cbf32042d3d389d6368926e425f08a7 Mon Sep 17 00:00:00 2001 From: Rupak Ganguly Date: Tue, 30 Sep 2014 09:56:52 -0400 Subject: [PATCH 3/5] Add volumes_from attribute to image and update service converter. --- app/models/converters/service_converter.rb | 5 ++ app/models/image.rb | 2 + app/serializers/image_serializer.rb | 3 +- .../shared_volume_service_exists_validator.rb | 14 ++++++ ...140929193656_add_volumes_from_to_images.rb | 5 ++ db/schema.rb | 3 +- .../converters/service_converter_spec.rb | 11 ++++ spec/serializers/image_serializer_spec.rb | 1 + ...ed_volume_service_exists_validator_spec.rb | 50 +++++++++++++++++++ 9 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 app/validators/shared_volume_service_exists_validator.rb create mode 100644 db/migrate/20140929193656_add_volumes_from_to_images.rb create mode 100644 spec/validators/shared_volume_service_exists_validator_spec.rb diff --git a/app/models/converters/service_converter.rb b/app/models/converters/service_converter.rb index d1dd5f2..f78206c 100644 --- a/app/models/converters/service_converter.rb +++ b/app/models/converters/service_converter.rb @@ -18,6 +18,7 @@ def to_image expose: service.expose, environment: service.environment, volumes: service.volumes, + volumes_from: service_volumes_from, command: service.command, type: service.type ) @@ -33,5 +34,9 @@ def service_links service.links.map { |link| { 'service' => link.linked_to_service.name, 'alias' => link.alias } } end + def service_volumes_from + service.volumes_from.map { |shared_vol| { 'service' => shared_vol.exported_from_service.name } } + end + end end diff --git a/app/models/image.rb b/app/models/image.rb index 05ea3c3..fd75872 100644 --- a/app/models/image.rb +++ b/app/models/image.rb @@ -9,6 +9,7 @@ class Image < ActiveRecord::Base serialize :expose, Array serialize :environment, Array serialize :volumes, Array + serialize :volumes_from, Array belongs_to :template @@ -17,4 +18,5 @@ class Image < ActiveRecord::Base validates :ports, has_container_ports: true, has_unique_ports: true validates :links, has_link_alias: true, service_link_exists: true validates :volumes, has_container_paths: true + validates :volumes_from, shared_volume_service_exists: true end diff --git a/app/serializers/image_serializer.rb b/app/serializers/image_serializer.rb index 517bb33..ba7b7f1 100644 --- a/app/serializers/image_serializer.rb +++ b/app/serializers/image_serializer.rb @@ -1,7 +1,8 @@ class ImageSerializer < ActiveModel::Serializer self.root = false - attributes :id, :category, :name, :source, :description, :type, :expose, :ports, :links, :environment, :volumes, :command + attributes :id, :category, :name, :source, :description, :type, :expose, + :ports, :links, :environment, :volumes, :volumes_from, :command def category object.categories.first unless object.categories.blank? diff --git a/app/validators/shared_volume_service_exists_validator.rb b/app/validators/shared_volume_service_exists_validator.rb new file mode 100644 index 0000000..76643bf --- /dev/null +++ b/app/validators/shared_volume_service_exists_validator.rb @@ -0,0 +1,14 @@ +class SharedVolumeServiceExistsValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return unless value.present? && record.respond_to?(:template) + value.each do |shared_vol| + next if template_image_names_for(record).include? shared_vol['service'] + record.errors[attribute] << 'service exporting shared volumes must exist' + break + end + end + + def template_image_names_for(model) + model.template ? model.template.images.map(&:name) : [] + end +end diff --git a/db/migrate/20140929193656_add_volumes_from_to_images.rb b/db/migrate/20140929193656_add_volumes_from_to_images.rb new file mode 100644 index 0000000..45b5380 --- /dev/null +++ b/db/migrate/20140929193656_add_volumes_from_to_images.rb @@ -0,0 +1,5 @@ +class AddVolumesFromToImages < ActiveRecord::Migration + def change + add_column :images, :volumes_from, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index 4923b3e..7fdfc2d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20140929181001) do +ActiveRecord::Schema.define(version: 20140929193656) do create_table "app_categories", force: true do |t| t.string "name" @@ -52,6 +52,7 @@ t.integer "template_id" t.datetime "created_at" t.datetime "updated_at" + t.text "volumes_from" end add_index "images", ["image_id"], name: "index_images_on_image_id", unique: true diff --git a/spec/models/converters/service_converter_spec.rb b/spec/models/converters/service_converter_spec.rb index 43ed467..5a09c9b 100644 --- a/spec/models/converters/service_converter_spec.rb +++ b/spec/models/converters/service_converter_spec.rb @@ -66,5 +66,16 @@ service1.categories.build(app_category: app_categories(:category1)) end end + + context 'when handling services with volumes_from' do + before do + service1.volumes_from.create(exported_from_service: services(:service2)) + end + + it 'populates the image with volumes_from' do + expect(subject.to_image.volumes_from).to eql [{ 'service' => 'my-other-service' }] + end + end + end end diff --git a/spec/serializers/image_serializer_spec.rb b/spec/serializers/image_serializer_spec.rb index 648f2d7..ba3e4e7 100644 --- a/spec/serializers/image_serializer_spec.rb +++ b/spec/serializers/image_serializer_spec.rb @@ -17,6 +17,7 @@ :links, :environment, :volumes, + :volumes_from, :command ] expect(serialized.keys).to match_array expected_keys diff --git a/spec/validators/shared_volume_service_exists_validator_spec.rb b/spec/validators/shared_volume_service_exists_validator_spec.rb new file mode 100644 index 0000000..5bd436d --- /dev/null +++ b/spec/validators/shared_volume_service_exists_validator_spec.rb @@ -0,0 +1,50 @@ +require 'spec_helper' + +describe SharedVolumeServiceExistsValidator do + + let(:image_one) { Image.new(name: 'foo') } + let(:image_two) { Image.new(name: 'bar') } + let(:template) { Template.new(images: [image_one, image_two]) } + let(:record) { Image.new(template: template) } + let(:attribute) { 'volumes_from' } + + subject { described_class.new(attributes: [attribute]) } + + context 'when the attribute is valid' do + + let(:value) do + [ + { 'service' => 'foo' }, + { 'service' => 'bar' } + ] + end + + it 'returns no errors for volumes_from with existing services' do + subject.validate_each(record, attribute, value) + expect(record.errors).to be_empty + end + + end + + context 'when the attribute is not valid' do + + let(:value) do + [ + { 'service' => 'baz' }, + { 'service' => 'quux' } + ] + end + + it 'should set an error on the record' do + subject.validate_each(record, attribute, value) + expect(record.errors).to_not be_empty + end + + it 'should quit validating after the first error is detected' do + subject.validate_each(record, attribute, value) + expect(record.errors[attribute].size).to eq 1 + end + + end + +end From c9443dabe915db8f751a77efe386138398ac39f6 Mon Sep 17 00:00:00 2001 From: Rupak Ganguly Date: Tue, 30 Sep 2014 13:21:53 -0400 Subject: [PATCH 4/5] Add volumes_from support to templates, template builder, serializer, and converters. --- app/builders/template_builder/from_fig.rb | 7 +++++ app/models/converters/template_converter.rb | 15 +++++++++ app/serializers/template_file_serializer.rb | 1 + .../template_builder/from_fig_spec.rb | 2 ++ .../converters/template_converter_spec.rb | 31 +++++++++++++++++++ .../template_file_serializer_spec.rb | 9 +++++- spec/support/fixtures/fig.yml | 2 ++ spec/support/fixtures/wordpress.pmx | 9 ++++-- 8 files changed, 73 insertions(+), 3 deletions(-) diff --git a/app/builders/template_builder/from_fig.rb b/app/builders/template_builder/from_fig.rb index 08483b4..d51e554 100644 --- a/app/builders/template_builder/from_fig.rb +++ b/app/builders/template_builder/from_fig.rb @@ -30,6 +30,7 @@ def image_from_fig_service(name, service_def) image.expose = service_def['expose'] image.volumes = volumes(service_def['volumes']) image.environment = service_def['environment'] + image.volumes_from = shared_volumes(service_def['volumes_from']) end end @@ -54,5 +55,11 @@ def volumes(volumes_array) end end + def shared_volumes(vol_from_array) + Array(vol_from_array).map do |vol_from| + { 'service' => vol_from } + end + end + end end diff --git a/app/models/converters/template_converter.rb b/app/models/converters/template_converter.rb index d986778..ab13755 100644 --- a/app/models/converters/template_converter.rb +++ b/app/models/converters/template_converter.rb @@ -20,6 +20,13 @@ def to_app linked_from_service.links = service_links_from_image(image) end + # Set-up shared volumes for services + template.images.each do |image| + next unless image.volumes_from? + the_service = find_service(image.name) + the_service.volumes_from = shared_volumes_from_image(image) + end + App.new( name: template.name, from: "Template: #{template.name}", @@ -62,6 +69,14 @@ def service_links_from_image(image) end end + def shared_volumes_from_image(image) + image.volumes_from.map do |vol_from| + SharedVolume.new( + exported_from_service: find_service(vol_from['service']) + ) + end + end + def find_service(name) services.find { |service| service.name == name } end diff --git a/app/serializers/template_file_serializer.rb b/app/serializers/template_file_serializer.rb index 47c6c57..ce2d1b9 100644 --- a/app/serializers/template_file_serializer.rb +++ b/app/serializers/template_file_serializer.rb @@ -11,6 +11,7 @@ class TemplateFileImageSerializer < ActiveModel::Serializer :links, :environment, :volumes, + :volumes_from, :command def category diff --git a/spec/builders/template_builder/from_fig_spec.rb b/spec/builders/template_builder/from_fig_spec.rb index 2233181..5fc8a1d 100644 --- a/spec/builders/template_builder/from_fig_spec.rb +++ b/spec/builders/template_builder/from_fig_spec.rb @@ -54,6 +54,8 @@ expect(subject.images.find_by(name: 'db').volumes).to be_blank expect(subject.images.find_by(name: 'web').expose).to be_blank expect(subject.images.find_by(name: 'db').expose).to eq(['3306']) + expect(subject.images.find_by(name: 'web').volumes_from).to be_blank + expect(subject.images.find_by(name: 'db').volumes_from).to eq([{ 'service' => 'web' }]) end end diff --git a/spec/models/converters/template_converter_spec.rb b/spec/models/converters/template_converter_spec.rb index ea1fd2e..972d6ea 100644 --- a/spec/models/converters/template_converter_spec.rb +++ b/spec/models/converters/template_converter_spec.rb @@ -27,6 +27,7 @@ environment: { var: 'val' }, command: '/boom shaka', volumes: ['volumes'], + volumes_from: ['service1'], type: 'mysql' ) end @@ -121,5 +122,35 @@ end end + context 'with shared volumes' do + + let(:image1) { Image.new(name: 'I1', source: 'I1:latest') } + let(:image2) { Image.new(name: 'I2', source: 'I2:latest') } + + before do + image2.volumes_from = [{ 'service' => 'I1' }] + template.images = [image1, image2] + end + + it 'creates a service for both images' do + app = subject.to_app + expect(app.services.size).to eq 2 + end + + it 'creates shared volumes where appropriate' do + app = subject.to_app + s1, s2 = app.services + expect(s1.volumes_from.size).to eq 0 + expect(s2.volumes_from.size).to eq 1 + end + + it 'shared volumes linked to the services correctly' do + app = subject.to_app + s1, s2 = app.services + expect(s2.volumes_from.first.exported_from_service_id).to eq s2.id + expect(s2.volumes_from.first.mounted_on_service_id).to eq s1.id + end + end + end end diff --git a/spec/serializers/template_file_serializer_spec.rb b/spec/serializers/template_file_serializer_spec.rb index d465219..785828f 100644 --- a/spec/serializers/template_file_serializer_spec.rb +++ b/spec/serializers/template_file_serializer_spec.rb @@ -33,7 +33,9 @@ type: 'ghi', categories: ['jkl'], expose: [8000], - environment: [{ 'variable' => 'mno', 'value' => 'pqr' }] + environment: [{ 'variable' => 'mno', 'value' => 'pqr' }], + volumes: [{ 'host_path' => '/tmp/foo', 'container_path' => '/tmp/bar' }], + volumes_from: [{ 'service' => 'baz' }] ) ] ) @@ -63,6 +65,11 @@ environment: - variable: mno value: pqr + volumes: + - host_path: "/tmp/foo" + container_path: "/tmp/bar" + volumes_from: + - service: baz EXPECTED end diff --git a/spec/support/fixtures/fig.yml b/spec/support/fixtures/fig.yml index 191ec4b..d0c1675 100644 --- a/spec/support/fixtures/fig.yml +++ b/spec/support/fixtures/fig.yml @@ -18,3 +18,5 @@ db: environment: - variable: MYSQL_ROOT_PASSWORD value: mysecretpassword + volumes_from: + - web diff --git a/spec/support/fixtures/wordpress.pmx b/spec/support/fixtures/wordpress.pmx index 8385fe2..0e1d2db 100644 --- a/spec/support/fixtures/wordpress.pmx +++ b/spec/support/fixtures/wordpress.pmx @@ -24,7 +24,12 @@ } ], "category": "DB Tier", - "type": "mysql" + "type": "mysql", + "volumes_from": [ + { + "service": "WP" + } + ], }, { "name": "WP", @@ -50,7 +55,7 @@ } ], "volumes": [ - { + { "host_path": "cache/", "container_path": "/tmp/cache" } From 8ececad01a65187411045c7937b1bf21e10a2c79 Mon Sep 17 00:00:00 2001 From: Rupak Ganguly Date: Tue, 30 Sep 2014 15:02:08 -0400 Subject: [PATCH 5/5] Add support for volumes_from to the apps, templates and services controllers. --- app/controllers/apps_controller.rb | 3 ++- app/controllers/services_controller.rb | 1 + app/controllers/templates_controller.rb | 4 ++-- spec/controllers/templates_controller_spec.rb | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/apps_controller.rb b/app/controllers/apps_controller.rb index 7d9209e..dfbdaca 100644 --- a/app/controllers/apps_controller.rb +++ b/app/controllers/apps_controller.rb @@ -77,7 +77,8 @@ def app_params environment: [[:variable, :value, :required]], ports: [[:host_interface, :host_port, :container_port, :proto]], expose: [], - volumes: [[:host_path, :container_path]] + volumes: [[:host_path, :container_path]], + volumes_from: [[:service]] ) end diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 65a72d6..1e13785 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -51,6 +51,7 @@ def service_params(extras=nil) ports: [[:host_interface, :host_port, :container_port, :proto]], expose: [], volumes: [[:host_path, :container_path]], + volumes_from: [[:service_id]], links: [[:service_id, :alias]], environment: [[:variable, :value, :required]] ) diff --git a/app/controllers/templates_controller.rb b/app/controllers/templates_controller.rb index 1ddbe44..1cd7d5d 100644 --- a/app/controllers/templates_controller.rb +++ b/app/controllers/templates_controller.rb @@ -49,8 +49,8 @@ def template_create_params expose: [], links: [[:service_id, :alias]], environment: [[:variable, :value, :required]], - links: [[:service_id, :alias]], - ports: [[:host_interface, :host_port, :container_port, :proto]] + ports: [[:host_interface, :host_port, :container_port, :proto]], + volumes_from: [[:service_id]] ]] ) end diff --git a/spec/controllers/templates_controller_spec.rb b/spec/controllers/templates_controller_spec.rb index edd2253..bd3e406 100644 --- a/spec/controllers/templates_controller_spec.rb +++ b/spec/controllers/templates_controller_spec.rb @@ -43,6 +43,7 @@ { 'variable' => 'GIT_REPO', 'value' => 'https://github.com/fermayo/hello-world-php.git' } ], 'volumes' => [], + 'volumes_from' => [{ 'service_id' => '3' }], 'command' => '/start web' } ]