1
0
Fork 0
mirror of https://github.com/fog/fog-aws.git synced 2022-11-09 13:50:52 -05:00

create, describe and destroy mount targets

This commit is contained in:
Eugene Howe 2016-10-06 18:52:32 -04:00
parent 98f3af916e
commit 295bac46be
14 changed files with 398 additions and 10 deletions

View file

@ -4,25 +4,35 @@ module Fog
extend Fog::AWS::CredentialFetcher::ServiceMethods
class FileSystemInUse < Fog::Errors::Error; end
class IncorrectFileSystemLifeCycleState < Fog::Errors::Error; end
class InvalidSubnet < Fog::Errors::Error; end
requires :aws_access_key_id, :aws_secret_access_key
recognizes :region, :host, :path, :port, :scheme, :persistent, :instrumentor, :instrumentor_name
model_path 'fog/aws/models/efs'
request_path 'fog/aws/requests/efs'
model :file_system
model :mount_target
collection :file_systems
collection :mount_targets
request :create_file_system
request :create_mount_target
request :delete_file_system
request :delete_mount_target
request :describe_file_systems
request :describe_mount_targets
class Mock
def self.data
@data ||= Hash.new do |hash, region|
hash[region] = Hash.new do |region_hash, key|
region_hash[key] = {
:file_systems => {}
:file_systems => {},
:mount_targets => {}
}
end
end
@ -55,7 +65,7 @@ module Fog
@instrumentor = options[:instrumentor]
@instrumentor_name = options[:instrumentor_name] || 'fog.aws.efs'
@region = 'us-east-1'
@region = options[:region] || 'us-east-1'
@host = options[:host] || "elasticfilesystem.#{@region}.amazonaws.com"
@port = options[:port] || 443
@scheme = options[:scheme] || "https"
@ -134,9 +144,16 @@ module Fog
rescue Excon::Errors::HTTPStatusError => error
match = Fog::AWS::Errors.match_error(error)
raise if match.empty?
if match[:code] == "IncorrectFileSystemLifeCycleState"
raise Fog::AWS::EFS::IncorrectFileSystemLifeCycleState.slurp(error, match[:message])
elsif match[:code] == 'FileSystemInUse'
raise Fog::AWS::EFS::FileSystemInUse.slurp(error, match[:message])
end
raise case match[:message]
when /invalid file system id/i
when /invalid ((file system)|(mount target)) id/i
Fog::AWS::EFS::NotFound.slurp(error, match[:message])
when /invalid subnet id/i
Fog::AWS::EFS::InvalidSubnet.slurp(error, match[:message])
else
Fog::AWS::EFS::Error.slurp(error, "#{match[:code]} => #{match[:message]}")
end

View file

@ -11,6 +11,10 @@ module Fog
attribute :tenancy, :aliases => 'instanceTenancy'
attribute :is_default, :aliases => 'isDefault'
def subnets
service.subnets(:filters => {'vpcId' => self.identity}).all
end
def initialize(attributes={})
self.dhcp_options_id ||= "default"
self.tenancy ||= "default"

View file

@ -13,6 +13,15 @@ module Fog
attribute :number_of_mount_targets, :aliases => 'NumberOfMountTargets'
attribute :size_in_bytes, :aliases => 'SizeInBytes'
def ready?
state == 'available'
end
def mount_targets
requires :identity
service.mount_targets(:file_system_id => self.identity).all
end
def destroy
requires :identity

View file

@ -12,7 +12,7 @@ module Fog
end
def get(identity)
data = service.describe_file_systems(:id => identity).body
data = service.describe_file_systems(:id => identity).body["FileSystems"].first
new(data)
rescue Fog::AWS::EFS::NotFound
nil

View file

@ -0,0 +1,47 @@
module Fog
module AWS
class EFS
class MountTarget < Fog::Model
attr_accessor :security_groups
identity :id, :aliases => "MountTargetId"
attribute :file_system_id, :aliases => "FileSystemId"
attribute :ip_address, :aliases => "IpAddress"
attribute :state, :aliases => "LifeCycleState"
attribute :network_interface_id, :aliases => "NetworkInterfaceId"
attribute :owner_id, :aliases => "OwnerId"
attribute :subnet_id, :aliases => "SubnetId"
def ready?
state == 'available'
end
def destroy
requires :identity
service.delete_mount_target(:id => self.identity)
true
end
def file_system
requires :file_system_id
service.file_systems.get(self.file_system_id)
end
def save
requires :file_system_id, :subnet_id
params = {
:file_system_id => self.file_system_id,
:subnet_id => self.subnet_id,
}
params.merge!('IpAddress' => self.ip_address) if self.ip_address
params.merge!('SecurityGroups' => self.security_groups) if self.security_groups
merge_attributes(service.create_mount_target(params).body)
end
end
end
end
end

View file

@ -0,0 +1,25 @@
require 'fog/aws/models/efs/mount_target'
module Fog
module AWS
class EFS
class MountTargets < Fog::Collection
attribute :file_system_id
model Fog::AWS::EFS::MountTarget
def all
data = service.describe_mount_targets(:file_system_id => self.file_system_id).body["MountTargets"]
load(data)
end
def get(identity)
data = service.describe_mount_targets(:id => identity).body["MountTargets"].first
new(data)
rescue Fog::AWS::EFS::NotFound
nil
end
end
end
end
end

View file

@ -0,0 +1,64 @@
module Fog
module AWS
class EFS
class Real
# Create a mount target for a specified file system
# http://docs.aws.amazon.com/efs/latest/ug/API_CreateMountTarget.html
# ==== Parameters
# * FileSystemId <~String> - ID of the file system for which to create the mount target.
# * IpAddress <~String> - Valid IPv4 address within the address range of the specified subnet.
# * SecurityGroups <~Array> - Up to five VPC security group IDs, of the form sg-xxxxxxxx. These must be for the same VPC as subnet specified.
# * SubnetId <~String> - ID of the subnet to add the mount target in.
# ==== Returns
# * response<~Excon::Response>
# * body<~Hash>
def create_mount_target(options={})
request({
:path => "mount-targets",
:method => "POST",
'FileSystemId' => options[:file_system_id],
'SubnetId' => options[:subnet_id]
}.merge(options))
end
end
class Mock
def create_mount_target(options={})
response = Excon::Response.new
file_system_id = options[:file_system_id]
subnet_id = options[:subnet_id]
unless file_system = self.data[:file_systems][file_system_id]
raise Fog::AWS::EFS::NotFound.new("invalid file system ID: #{file_system_id}")
end
unless file_system["LifeCycleState"] == 'available'
# this error doesn't include a message for some reason
raise Fog::AWS::EFS::IncorrectFileSystemLifeCycleState.new("")
end
unless subnet = Fog::Compute[:aws].subnets.get(subnet_id)
raise Fog::AWS::EFS::InvalidSubnet.new("invalid subnet ID: #{subnet_id}")
end
id = "fsmt-#{Fog::Mock.random_letters(8)}"
mount_target = {
'MountTargetId' => id,
'FileSystemId' => file_system_id,
'IpAddress' => Fog::AWS::Mock.ip_address,
'OwnerId' => Fog::AWS::Mock.owner_id,
'LifeCycleState' => 'creating',
'NetworkInterfaceId' => "eni-#{Fog::Mock.random_hex(8)}",
'SubnetId' => subnet.identity,
}
self.data[:mount_targets][id] = mount_target
response.body = mount_target
response
end
end
end
end
end

View file

@ -6,7 +6,7 @@ module Fog
# http://docs.aws.amazon.com/efs/latest/ug/API_DeleteFileSystem.html
# ==== Parameters
# * FileSystemId <~String> - ID of the file system you want to delete.
# ==== Response
# ==== Returns
# * response<~Excon::Response>
# * body - Empty
# * status - 204
@ -31,7 +31,7 @@ module Fog
end
if file_system["NumberOfMountTargets"] > 0
raise Fog::AWS::EFS::FileSystemInUse.new("file system still has active mount targets")
raise Fog::AWS::EFS::FileSystemInUse.new("")
end
self.data[:file_systems].delete(id)

View file

@ -0,0 +1,40 @@
module Fog
module AWS
class EFS
class Real
# Delete a mount target
# http://docs.aws.amazon.com/efs/latest/ug/API_DeleteMountTarget.html
# ==== Parameters
# * MountTargetId <~String> - ID of the mount target you want to delete
# ==== Returns
# * response<~Excon::Response>
# * body - Empty
# * status - 204
def delete_mount_target(options={})
id = options.delete(:id)
request(
:path => "mount-targets/#{id}",
:method => "DELETE",
:expects => 204,
)
end
end
class Mock
def delete_mount_target(options={})
id = options.delete(:id)
response = Excon::Response.new
unless self.data[:mount_targets][id]
raise Fog::AWS::EFS::NotFound.new("invalid file system ID: #{id}")
end
self.data[:mount_targets].delete(id)
response.status = 204
response
end
end
end
end
end

View file

@ -0,0 +1,61 @@
module Fog
module AWS
class EFS
class Real
# Describe all mount targets for a filesystem, or specified mount target
# http://docs.aws.amazon.com/efs/latest/ug/API_DescribeMountTargets.html
# ==== Parameters
# * FileSystemId<~String> - Id of file system to describe mount targets for. Required unless MountTargetId is specified
# * MountTargetId<~String> - Specific mount target to describe. Required if FileSystemId is not specified
# ==== Returns
# * response<~Excon::Response>
# * body<~Hash>
def describe_mount_targets(options={})
params = {}
if options[:marker]
params['Marker'] = options[:marker]
end
if options[:max_records]
params['MaxRecords'] = options[:max_records]
end
if options[:id]
params['MountTargetId'] = options[:id]
end
if options[:file_system_id]
params['FileSystemId'] = options[:file_system_id]
end
request({
:path => "mount-targets"
}.merge(params))
end
end
class Mock
def describe_mount_targets(options={})
response = Excon::Response.new
mount_targets = if id = options[:id]
if mount_target = self.data[:mount_targets][id]
[mount_target]
else
raise Fog::AWS::EFS::NotFound.new("invalid file system ID: #{id}")
end
elsif file_system_id = options[:file_system_id]
self.data[:mount_targets].values.select { |mt| mt["FileSystemId"] == file_system_id }
else
raise Fog::AWS::EFS::Error.new("file system ID or mount target ID must be specified")
end
mount_targets.each do |mount_target|
mount_target['LifeCycleState'] = 'available'
self.data[:mount_targets][mount_target["MountTargetId"]] = mount_target
end
response.body = {"MountTargets" => mount_targets}
response
end
end
end
end
end

View file

@ -0,0 +1,25 @@
Shindo.tests("AWS::EFS | mount target", ["aws", "efs"]) do
if ENV['FILE_SYSTEM_ID']
@file_system = Fog::AWS[:efs].file_systems.get(ENV["FILE_SYSTEM_ID"])
else
@file_system = Fog::AWS[:efs].file_systems.create(:creation_token => "fogtoken#{rand(999).to_s}")
end
@file_system.wait_for { ready? }
if Fog.mocking?
vpc = Fog::Compute[:aws].vpcs.create(cidr_block: "10.0.0.0/16")
Fog::Compute[:aws].subnets.create(vpc_id: vpc.id, cidr_block: "10.0.1.0/24")
end
mount_target_params = {
:file_system_id => @file_system.identity,
:subnet_id => Fog::Compute[:aws].vpcs.first.subnets.first.identity
}
model_tests(Fog::AWS[:efs].mount_targets, mount_target_params, true)
unless ENV["LEAVE_FILE_SYSTEM"] = 'true'
@file_system.destroy
end
end

View file

@ -0,0 +1,20 @@
Shindo.tests("AWS::EFS | mount targets", ["aws", "efs"]) do
if ENV['FILE_SYSTEM_ID']
@file_system = Fog::AWS[:efs].file_systems.get(ENV["FILE_SYSTEM_ID"])
else
@file_system = Fog::AWS[:efs].file_systems.create(:creation_token => "fogtoken#{rand(999).to_s}")
end
@file_system.wait_for { ready? }
mount_target_params = {
:file_system_id => @file_system.identity,
:subnet_id => Fog::Compute[:aws].vpcs.first.subnets.first.identity
}
collection_tests(Fog::AWS[:efs].mount_targets(:file_system_id => @file_system.identity), mount_target_params, true)
unless ENV["LEAVE_FILE_SYSTEM"] = 'true'
@file_system.destroy
end
end

View file

@ -20,15 +20,77 @@ Shindo.tests('AWS::EFS | file systems', ['aws', 'efs']) do
result
end
file_system = Fog::AWS[:efs].describe_file_systems(:creation_token => @creation_token).body["FileSystems"].first
file_system_id = Fog::AWS[:efs].describe_file_systems(:creation_token => @creation_token).body["FileSystems"].first["FileSystemId"]
file_system = Fog::AWS[:efs].file_systems.get(file_system_id)
tests("#describe_file_systems(id: #{file_system["FileSystemId"]})").formats(AWS::EFS::Formats::DESCRIBE_FILE_SYSTEMS_RESULT) do
Fog::AWS[:efs].describe_file_systems(:id => file_system["FileSystemId"]).body
tests("#describe_file_systems(id: #{file_system_id})").formats(AWS::EFS::Formats::DESCRIBE_FILE_SYSTEMS_RESULT) do
Fog::AWS[:efs].describe_file_systems(:id => file_system_id).body
end
if Fog.mocking?
vpc = Fog::Compute[:aws].vpcs.create(cidr_block: "10.0.0.0/16")
Fog::Compute[:aws].subnets.create(vpc_id: vpc.id, cidr_block: "10.0.1.0/24")
end
subnet_id = Fog::Compute[:aws].vpcs.first.subnets.first.identity
raises(Fog::AWS::EFS::InvalidSubnet, "invalid subnet ID: foobar") do
Fog::AWS[:efs].create_mount_target(:file_system_id => file_system_id, :subnet_id => "foobar")
end
raises(Fog::AWS::EFS::NotFound, "invalid file system ID: foobar") do
Fog::AWS[:efs].create_mount_target(:file_system_id => "foobar", :subnet_id => subnet_id)
end
if Fog.mocking?
tests("#create_mount_target") do
Fog::AWS[:efs].data[:file_systems][file_system_id]["LifeCycleState"] = 'creating'
raises(Fog::AWS::EFS::IncorrectFileSystemLifeCycleState) do
Fog::AWS[:efs].create_mount_target(:file_system_id => file_system_id, :subnet_id => subnet_id)
end
Fog::AWS[:efs].data[:file_systems][file_system_id]["LifeCycleState"] = 'available'
end
end
tests("#create_mount_target(file_system_id: #{file_system_id}, subnet_id: #{subnet_id})").formats(AWS::EFS::Formats::MOUNT_TARGET_FORMAT) do
Fog::AWS[:efs].create_mount_target(:file_system_id => file_system_id, :subnet_id => subnet_id).body
end
tests("#describe_mount_targets(file_system_id: #{file_system_id})").formats(AWS::EFS::Formats::DESCRIBE_MOUNT_TARGETS_RESULT) do
Fog::AWS[:efs].describe_mount_targets(:file_system_id => file_system_id).body
end
mount_target_id = Fog::AWS[:efs].describe_mount_targets(:file_system_id => file_system_id).body["MountTargets"].first["MountTargetId"]
tests("#describe_mount_targets(id: #{mount_target_id})").formats(AWS::EFS::Formats::DESCRIBE_MOUNT_TARGETS_RESULT) do
Fog::AWS[:efs].describe_mount_targets(:id => mount_target_id).body
end
raises(Fog::AWS::EFS::Error, 'file system ID or mount target ID must be specified') do
Fog::AWS[:efs].describe_mount_targets
end
tests("#delete_mount_target(id: #{mount_target_id})") do
returns(true) do
result = Fog::AWS[:efs].delete_mount_target(:id => mount_target_id)
result.body.empty?
end
end
file_system.wait_for { number_of_mount_targets == 0 }
if Fog.mocking?
Fog::AWS[:efs].data[:file_systems][file_system_id]["NumberOfMountTargets"] = 1
raises(Fog::AWS::EFS::FileSystemInUse) do
Fog::AWS[:efs].delete_file_system(:id => file_system_id)
end
Fog::AWS[:efs].data[:file_systems][file_system_id]["NumberOfMountTargets"] = 0
end
tests("#delete_file_system") do
returns(true) do
result = Fog::AWS[:efs].delete_file_system(:id => file_system["FileSystemId"])
result = Fog::AWS[:efs].delete_file_system(:id => file_system_id)
result.body.empty?
end
end

View file

@ -16,9 +16,23 @@ class AWS
}
}
MOUNT_TARGET_FORMAT = {
"FileSystemId" => String,
"IpAddress" => String,
"LifeCycleState" => String,
"MountTargetId" => String,
"NetworkInterfaceId" => String,
"OwnerId" => String,
"SubnetId" => String
}
DESCRIBE_FILE_SYSTEMS_RESULT = {
"FileSystems" => [FILE_SYSTEM_FORMAT]
}
DESCRIBE_MOUNT_TARGETS_RESULT = {
"MountTargets" => [MOUNT_TARGET_FORMAT]
}
end
end
end