From 8d37ba945115459c0961abc40f74846d5c64f558 Mon Sep 17 00:00:00 2001 From: Sylvain Baubeau Date: Wed, 9 Jul 2014 12:36:54 +0200 Subject: [PATCH] Add trove_datastore and trove_datastore_version types Change-Id: If739b4b26ef98ae9ba09affd4f2eeef4ad1b55fd --- lib/puppet/provider/trove.rb | 61 ++++--------------- lib/puppet/provider/trove_datastore/trove.rb | 52 ++++++++++++++++ .../provider/trove_datastore_version/trove.rb | 60 ++++++++++++++++++ lib/puppet/type/trove_datastore.rb | 26 ++++++++ lib/puppet/type/trove_datastore_version.rb | 38 ++++++++++++ manifests/init.pp | 2 + .../provider/trove_datastore/trove_spec.rb | 57 +++++++++++++++++ .../trove_datastore_version/trove_spec.rb | 50 +++++++++++++++ spec/unit/provider/trove_spec.rb | 14 +++++ 9 files changed, 311 insertions(+), 49 deletions(-) create mode 100644 lib/puppet/provider/trove_datastore/trove.rb create mode 100644 lib/puppet/provider/trove_datastore_version/trove.rb create mode 100644 lib/puppet/type/trove_datastore.rb create mode 100644 lib/puppet/type/trove_datastore_version.rb create mode 100644 spec/unit/provider/trove_datastore/trove_spec.rb create mode 100644 spec/unit/provider/trove_datastore_version/trove_spec.rb create mode 100644 spec/unit/provider/trove_spec.rb diff --git a/lib/puppet/provider/trove.rb b/lib/puppet/provider/trove.rb index 19909e77..4a53bbad 100644 --- a/lib/puppet/provider/trove.rb +++ b/lib/puppet/provider/trove.rb @@ -1,4 +1,4 @@ -require 'csv' +require 'json' require 'puppet/util/inifile' class Puppet::Provider::Trove < Puppet::Provider @@ -89,62 +89,25 @@ correctly configured.") self.class.auth_trove(args) end + def trove_manage(*args) + cmd = args.join(" ") + output = `#{cmd}` + $?.exitstatus + end + def self.reset @trove_conf = nil @trove_credentials = nil end - def self.list_trove_resources(type) - ids = [] - list = auth_trove("#{type}-list", '--format=csv', - '--column=id', '--quote=none') - (list.split("\n")[1..-1] || []).compact.collect do |line| - ids << line.strip - end - return ids + def self.list_trove_resources(type, *args) + json = auth_trove("--json", "#{type}-list", *args) + return JSON.parse(json) end def self.get_trove_resource_attrs(type, id) - attrs = {} - net = auth_trove("#{type}-show", '--format=shell', id) - last_key = nil - (net.split("\n") || []).compact.collect do |line| - if line.include? '=' - k, v = line.split('=', 2) - attrs[k] = v.gsub(/\A"|"\Z/, '') - last_key = k - else - # Handle the case of a list of values - v = line.gsub(/\A"|"\Z/, '') - attrs[last_key] = [attrs[last_key], v].flatten - end - end - return attrs - end - - def self.get_tenant_id(catalog, name) - instance_type = 'keystone_tenant' - instance = catalog.resource("#{instance_type.capitalize!}[#{name}]") - if ! instance - instance = Puppet::Type.type(instance_type).instances.find do |i| - i.provider.name == name - end - end - if instance - return instance.provider.id - else - fail("Unable to find #{instance_type} for name #{name}") - end - end - - def self.parse_creation_output(data) - hash = {} - data.split("\n").compact.each do |line| - if line.include? '=' - hash[line.split('=').first] = line.split('=', 2)[1].gsub(/\A"|"\Z/, '') - end - end - hash + json = auth_trove("--json", "#{type}-show", id) + return JSON.parse(json) end end diff --git a/lib/puppet/provider/trove_datastore/trove.rb b/lib/puppet/provider/trove_datastore/trove.rb new file mode 100644 index 00000000..d356637e --- /dev/null +++ b/lib/puppet/provider/trove_datastore/trove.rb @@ -0,0 +1,52 @@ +require File.join(File.dirname(__FILE__), "..","..","..", + "puppet/provider/trove") + +Puppet::Type.type(:trove_datastore).provide( + :trove, + :parent => Puppet::Provider::Trove +) do + desc <<-EOT + Trove provider to manage datastore type. + EOT + + commands :trove => "trove" + + mk_resource_methods + + def self.instances + list_trove_resources("datastore").collect do |attrs| + new( + :ensure => :present, + :name => attrs["name"], + :id => attrs["id"] + ) + end + end + + def self.prefetch(resources) + instances_ = instances + resources.keys.each do |name| + if provider = instances_.find{ |instance| instance.name == name } + resources[name].provider = provider + end + end + end + + def exists? + @property_hash[:ensure] == :present + end + + def create + if trove_manage(['trove-manage', 'datastore_update', + "#{@resource[:name]}", "''"]) != 0 + fail("Failed to create datastore #{@resource[:name]}") + end + + if trove_manage(['trove-manage', 'datastore_update', + "#{@resource[:name]}", "#{@resource[:version]}"]) != 0 + fail("Failed to set version for datastore #{@resource[:name]}") + end + end + +end + diff --git a/lib/puppet/provider/trove_datastore_version/trove.rb b/lib/puppet/provider/trove_datastore_version/trove.rb new file mode 100644 index 00000000..f02ba236 --- /dev/null +++ b/lib/puppet/provider/trove_datastore_version/trove.rb @@ -0,0 +1,60 @@ +require File.join(File.dirname(__FILE__), "..","..","..", + "puppet/provider/trove") + +Puppet::Type.type(:trove_datastore_version).provide( + :trove, + :parent => Puppet::Provider::Trove +) do + desc <<-EOT + Trove provider to manage datastore version type. + EOT + + commands :trove => "trove" + + mk_resource_methods + + def self.prefetch(resource) + @datastore_version_hash = nil + end + + def self.datastore_version_hash(datastore) + @datastore_version_hash ||= build_datastore_version_hash(datastore) + end + + def datastore_version_hash(datastore) + self.class.datastore_version_hash(datastore) + end + + def self.instances + [] + end + + def exists? + datastore_version_hash(resource[:datastore])[resource[:name]] + end + + def create + cmd = ['trove-manage', 'datastore_version_update', + "#{@resource[:datastore]}", "#{@resource[:name]}", + "#{@resource[:manager]}", "#{@resource[:image_id]}", + "#{@resource[:packages]}", "#{@resource[:active]}"] + if trove_manage(cmd) != 0 + fail("Failed to create datastore version #{@resource[:name]}") + end + end + + def destroy + fail("Datastore version cannot be removed") + end + + private + + def self.build_datastore_version_hash(datastore) + dvs = {} + list_trove_resources("datastore-version", datastore).collect do |attrs| + dvs[attrs["name"]] = attrs + end + dvs + end + +end diff --git a/lib/puppet/type/trove_datastore.rb b/lib/puppet/type/trove_datastore.rb new file mode 100644 index 00000000..7aa94832 --- /dev/null +++ b/lib/puppet/type/trove_datastore.rb @@ -0,0 +1,26 @@ +Puppet::Type.newtype(:trove_datastore) do + + @doc = "Manage creation of Trove datastores" + + ensurable + + newparam(:name, :namevar => true) do + desc "Datastore version name)" + newvalues(/^.*$/) + end + + newparam(:version) do + desc "Datastore version name" + end + + newproperty(:id) do + validate do |v| + raise(Puppet::Error, 'This is a read only property') + end + end + + validate do + raise(Puppet::Error, 'Version must be set') unless self[:version] + end +end + diff --git a/lib/puppet/type/trove_datastore_version.rb b/lib/puppet/type/trove_datastore_version.rb new file mode 100644 index 00000000..856e06d1 --- /dev/null +++ b/lib/puppet/type/trove_datastore_version.rb @@ -0,0 +1,38 @@ +Puppet::Type.newtype(:trove_datastore_version) do + + @doc = "Manage creation of Trove datastore versions" + + ensurable + + newparam(:name, :namevar => true) do + desc "Datastore version" + end + + newparam(:datastore) do + desc "Datastore name)" + end + + newparam(:manager) do + desc "Manager name" + end + + newparam(:image_id) do + desc "Glance image id" + end + + newparam(:packages) do + desc "Packages to install" + end + + newparam(:active) do + desc "State" + end + + validate do + raise(Puppet::Error, 'Datastore must be set') unless self[:datastore] + raise(Puppet::Error, 'Manager must be set') unless self[:manager] + raise(Puppet::Error, 'Image must be set') unless self[:image_id] + raise(Puppet::Error, 'Packages must be set') unless self[:packages] + raise(Puppet::Error, 'State must be set') unless self[:active] + end +end diff --git a/manifests/init.pp b/manifests/init.pp index e30ef6e8..e601b7b3 100644 --- a/manifests/init.pp +++ b/manifests/init.pp @@ -166,4 +166,6 @@ class trove( command => '/bin/echo "Trove config has changed"', refreshonly => true, } + + Trove_datastore<||> -> Trove_datastore_version<||> } diff --git a/spec/unit/provider/trove_datastore/trove_spec.rb b/spec/unit/provider/trove_datastore/trove_spec.rb new file mode 100644 index 00000000..3c059057 --- /dev/null +++ b/spec/unit/provider/trove_datastore/trove_spec.rb @@ -0,0 +1,57 @@ +require 'puppet' +require 'spec_helper' +require 'puppet/provider/trove_datastore/trove' + +provider_class = Puppet::Type.type(:trove_datastore).provider(:trove) + +describe provider_class do + + let :datastore_name do + 'foo' + end + + let :resource do + Puppet::Type::Trove_datastore.new({ + :name => datastore_name, + :version => '0.1', + :ensure => 'present', + }) + end + + let :provider do + described_class.new(resource) + end + + before :each do + described_class.stubs(:list_trove_resources).with('datastore').returns([ + resource + ]) + end + + describe "self.instances" do + it "should have an instances method" do + provider.class.should respond_to(:instances) + end + + it "should list instances" do + datastores = described_class.instances + datastores.size.should == 1 + datastores.map {|provider| provider.name} == datastore_name + end + end + + describe '#create' do + it 'should call trove-manage' do + provider.expects(:trove_manage).with( + ['trove-manage', 'datastore_update', datastore_name, "''"] + ).returns(0) + + provider.expects(:trove_manage).with( + ['trove-manage', 'datastore_update', datastore_name, "0.1"] + ).returns(0) + + provider.create + end + end + +end diff --git a/spec/unit/provider/trove_datastore_version/trove_spec.rb b/spec/unit/provider/trove_datastore_version/trove_spec.rb new file mode 100644 index 00000000..3a2c6c29 --- /dev/null +++ b/spec/unit/provider/trove_datastore_version/trove_spec.rb @@ -0,0 +1,50 @@ +require 'puppet' +require 'spec_helper' +require 'puppet/provider/trove_datastore_version/trove' + +provider_class = Puppet::Type.type(:trove_datastore_version).provider(:trove) + +describe provider_class do + + let :datastore_name do + 'foo' + end + + let :datastore_version do + '1.0' + end + + let :resource do + Puppet::Type::Trove_datastore_version.new({ + :name => datastore_version, + :ensure => 'present', + :datastore => datastore_name, + :manager => 'mysql', + :image_id => '1234', + :packages => 'mysql', + :active => 1 + }) + end + + let :provider do + described_class.new(resource) + end + + describe "self.instances" do + it "should have an instances method" do + provider.class.should respond_to(:instances) + end + end + + describe '#create' do + it 'should call trove-manage' do + provider.expects(:trove_manage).with( + ['trove-manage', 'datastore_version_update', datastore_name, "1.0", + 'mysql', '1234', 'mysql', '1'] + ).returns(0) + + provider.create + end + end + +end diff --git a/spec/unit/provider/trove_spec.rb b/spec/unit/provider/trove_spec.rb new file mode 100644 index 00000000..b38f3d8d --- /dev/null +++ b/spec/unit/provider/trove_spec.rb @@ -0,0 +1,14 @@ +require 'puppet' +require 'spec_helper' +require 'puppet/provider/trove' + + +klass = Puppet::Provider::Trove + +describe Puppet::Provider::Trove do + + after :each do + klass.reset + end + +end