secured-cloud-vagrant 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/Gemfile +12 -0
- data/LICENSE.txt +9 -0
- data/README.md +340 -0
- data/README.txt +358 -0
- data/Rakefile +22 -0
- data/Vagrantfile_multipleVMs +124 -0
- data/Vagrantfile_singleVM +43 -0
- data/dummy.box +0 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/lib/secured-cloud-vagrant.rb +22 -0
- data/lib/secured-cloud-vagrant/action.rb +259 -0
- data/lib/secured-cloud-vagrant/actions/assign_public_ips.rb +142 -0
- data/lib/secured-cloud-vagrant/actions/check_state.rb +64 -0
- data/lib/secured-cloud-vagrant/actions/create.rb +112 -0
- data/lib/secured-cloud-vagrant/actions/delete.rb +105 -0
- data/lib/secured-cloud-vagrant/actions/has_public_ips.rb +53 -0
- data/lib/secured-cloud-vagrant/actions/power_off.rb +22 -0
- data/lib/secured-cloud-vagrant/actions/power_on.rb +22 -0
- data/lib/secured-cloud-vagrant/actions/power_vm.rb +100 -0
- data/lib/secured-cloud-vagrant/actions/read_ssh_info.rb +148 -0
- data/lib/secured-cloud-vagrant/actions/reboot.rb +98 -0
- data/lib/secured-cloud-vagrant/actions/release_ips_confirm.rb +25 -0
- data/lib/secured-cloud-vagrant/actions/wait_for_state.rb +54 -0
- data/lib/secured-cloud-vagrant/actions/warn_networks.rb +32 -0
- data/lib/secured-cloud-vagrant/actions/warn_provision.rb +32 -0
- data/lib/secured-cloud-vagrant/commands/list.rb +149 -0
- data/lib/secured-cloud-vagrant/commands/ssh_config.rb +43 -0
- data/lib/secured-cloud-vagrant/configs/authentication_info.rb +49 -0
- data/lib/secured-cloud-vagrant/configs/config.rb +87 -0
- data/lib/secured-cloud-vagrant/configs/ip_mapping.rb +71 -0
- data/lib/secured-cloud-vagrant/configs/virtual_machine.rb +136 -0
- data/lib/secured-cloud-vagrant/plugin.rb +77 -0
- data/lib/secured-cloud-vagrant/provider.rb +73 -0
- data/lib/secured-cloud-vagrant/version.rb +5 -0
- data/locales/en.yml +91 -0
- data/secured-cloud-vagrant.gemspec +59 -0
- data/templates/os_templates.erb +12 -0
- metadata +160 -0
@@ -0,0 +1,136 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
require_relative "ip_mapping"
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module SecuredCloud
|
7
|
+
module Configuration
|
8
|
+
class VirtualMachine < Vagrant.plugin(2, :config)
|
9
|
+
|
10
|
+
attr_accessor :name
|
11
|
+
attr_accessor :description
|
12
|
+
attr_accessor :storageGB
|
13
|
+
attr_accessor :memoryMB
|
14
|
+
attr_accessor :vcpus
|
15
|
+
attr_accessor :osTemplateUrl
|
16
|
+
attr_accessor :imageResourceUrl
|
17
|
+
attr_accessor :newOsPassword
|
18
|
+
attr_accessor :nodeResourceUrl
|
19
|
+
attr_accessor :orgResourceUrl
|
20
|
+
attr_accessor :ipMappings
|
21
|
+
|
22
|
+
|
23
|
+
def initialize
|
24
|
+
|
25
|
+
@name = UNSET_VALUE
|
26
|
+
@description = UNSET_VALUE
|
27
|
+
@storageGB = UNSET_VALUE
|
28
|
+
@memoryMB = UNSET_VALUE
|
29
|
+
@vcpus = UNSET_VALUE
|
30
|
+
@osTemplateUrl = UNSET_VALUE
|
31
|
+
@imageResourceUrl = UNSET_VALUE
|
32
|
+
@newOsPassword = UNSET_VALUE
|
33
|
+
@nodeResourceUrl = UNSET_VALUE
|
34
|
+
@orgResourceUrl = UNSET_VALUE
|
35
|
+
@ipMappings = UNSET_VALUE
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
def validate(machine)
|
40
|
+
|
41
|
+
errors = _detected_errors
|
42
|
+
|
43
|
+
if @name.nil? || @name.empty?
|
44
|
+
errors << "The VM name must be properly defined "
|
45
|
+
end
|
46
|
+
|
47
|
+
if !@ipMappings.nil? && !@ipMappings.respond_to?(:each)
|
48
|
+
errors << "A valid array of IP mappings must be specified "
|
49
|
+
else
|
50
|
+
@ipMappings.each do |ipMapping|
|
51
|
+
ipMapping.validate(machine)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
{ "Secured Cloud Provider" => errors}
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def merge(other)
|
61
|
+
|
62
|
+
super.tap do |result|
|
63
|
+
|
64
|
+
result.name = (other.name == UNSET_VALUE) ? @name : other.name
|
65
|
+
result.description = (other.description == UNSET_VALUE) ? @description : other.description
|
66
|
+
result.storageGB = (other.storageGB == UNSET_VALUE) ? @storageGB : other.storageGB
|
67
|
+
result.memoryMB = (other.memoryMB == UNSET_VALUE) ? @memoryMB : other.memoryMB
|
68
|
+
result.vcpus = (other.vcpus == UNSET_VALUE) ? @vcpus : other.vcpus
|
69
|
+
result.osTemplateUrl = (other.osTemplateUrl == UNSET_VALUE) ? @osTemplateUrl : other.osTemplateUrl
|
70
|
+
result.imageResourceUrl = (other.imageResourceUrl == UNSET_VALUE) ? @imageResourceUrl : other.imageResourceUrl
|
71
|
+
result.newOsPassword = (other.newOsPassword == UNSET_VALUE) ? @newOsPassword : other.newOsPassword
|
72
|
+
result.nodeResourceUrl = (other.nodeResourceUrl == UNSET_VALUE) ? @nodeResourceUrl : other.nodeResourceUrl
|
73
|
+
result.orgResourceUrl = (other.orgResourceUrl == UNSET_VALUE) ? @orgResourceUrl : other.orgResourceUrl
|
74
|
+
|
75
|
+
if(other.ipMappings == UNSET_VALUE || other.ipMappings.nil?)
|
76
|
+
result.ipMappings = @ipMappings
|
77
|
+
elsif @ipMappings == UNSET_VALUE || @ipMappings.nil?
|
78
|
+
result.ipMappings = other.ipMappings
|
79
|
+
else
|
80
|
+
result.ipMappings = @ipMappings.concat(other.ipMappings)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def finalize!
|
87
|
+
|
88
|
+
@name = nil if (@name == UNSET_VALUE)
|
89
|
+
@description = nil if (@description == UNSET_VALUE)
|
90
|
+
@storageGB = nil if (@storageGB == UNSET_VALUE)
|
91
|
+
@memoryMB = nil if (@memoryMB == UNSET_VALUE)
|
92
|
+
@vcpus = nil if (@vcpus == UNSET_VALUE)
|
93
|
+
@osTemplateUrl = nil if (@osTemplateUrl == UNSET_VALUE)
|
94
|
+
@imageResourceUrl = nil if( @imageResourceUrl == UNSET_VALUE)
|
95
|
+
@newOsPassword = nil if (@newOsPassword == UNSET_VALUE)
|
96
|
+
@nodeResourceUrl = nil if (@nodeResourceUrl == UNSET_VALUE)
|
97
|
+
@orgResourceUrl = nil if (@orgResourceUrl == UNSET_VALUE)
|
98
|
+
|
99
|
+
if (@ipMappings == UNSET_VALUE || @ipMappings == nil)
|
100
|
+
@ipMappings = Array.new
|
101
|
+
else
|
102
|
+
finalizeIpMappings
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
def finalizeIpMappings
|
109
|
+
|
110
|
+
if(!@ipMappings.empty?)
|
111
|
+
|
112
|
+
ipMappingsList = Array.new
|
113
|
+
|
114
|
+
@ipMappings.each do |ipMapping|
|
115
|
+
|
116
|
+
currentIpMapping = IpMapping.new
|
117
|
+
currentIpMapping.privateIp = ipMapping[:privateIp]
|
118
|
+
currentIpMapping.newPublicIpCount = ipMapping[:newPublicIpCount]
|
119
|
+
currentIpMapping.publicIpsFromReserved = ipMapping[:publicIpsFromReserved]
|
120
|
+
|
121
|
+
currentIpMapping.finalize!
|
122
|
+
ipMappingsList << currentIpMapping
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
@ipMappings = ipMappingsList
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
begin
|
2
|
+
require "vagrant"
|
3
|
+
rescue LoadError
|
4
|
+
raise "This plugin must run within Vagrant."
|
5
|
+
end
|
6
|
+
|
7
|
+
module VagrantPlugins
|
8
|
+
module SecuredCloud
|
9
|
+
|
10
|
+
class SecuredCloudPlugin < Vagrant.plugin('2')
|
11
|
+
|
12
|
+
name 'Secured Cloud Vagrant Plugin'
|
13
|
+
|
14
|
+
description <<-DESC
|
15
|
+
This plugin installs a provider that allows Vagrant to manage virtual machine in Secured Cloud
|
16
|
+
DESC
|
17
|
+
|
18
|
+
provider('secured_cloud') do
|
19
|
+
|
20
|
+
# Setup logging
|
21
|
+
setup_logging
|
22
|
+
|
23
|
+
require_relative "provider"
|
24
|
+
SecuredCloudProvider
|
25
|
+
end
|
26
|
+
|
27
|
+
config(:secured_cloud, :provider) do
|
28
|
+
require_relative "configs/config"
|
29
|
+
Configuration::Config
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
command('ssh-config') do
|
34
|
+
require_relative "commands/ssh_config"
|
35
|
+
Command::SshConfig
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
command('list') do
|
40
|
+
require_relative "commands/list"
|
41
|
+
Command::List
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def self.setup_logging
|
46
|
+
|
47
|
+
require "log4r"
|
48
|
+
|
49
|
+
level = nil
|
50
|
+
|
51
|
+
begin
|
52
|
+
level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
|
53
|
+
rescue NameError
|
54
|
+
# This means that the logging constant wasn't found,
|
55
|
+
# which is fine. We just keep `level` as `FATAL`. But
|
56
|
+
# we tell the user.
|
57
|
+
level = Log4r.const_get('FATAL')
|
58
|
+
end
|
59
|
+
|
60
|
+
# Some constants, such as "true" resolve to booleans, so the
|
61
|
+
# above error checking doesn't catch it. This will check to make
|
62
|
+
# sure that the log level is an integer, as Log4r requires.
|
63
|
+
level = nil if !level.is_a?(Integer)
|
64
|
+
|
65
|
+
# Set the logging level on all "vagrant" namespaced
|
66
|
+
# logs as long as we have a valid level.
|
67
|
+
if level
|
68
|
+
logger = Log4r::Logger.new('vagrant::secured_cloud')
|
69
|
+
logger.outputters = Log4r::Outputter.stdout
|
70
|
+
logger.level = level
|
71
|
+
logger = nil
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module SecuredCloud
|
5
|
+
class SecuredCloudProvider < Vagrant.plugin(2, :provider)
|
6
|
+
|
7
|
+
def initialize(machine)
|
8
|
+
@machine = machine
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def action(name)
|
13
|
+
|
14
|
+
# Attempt to get the action method from the Action class if it
|
15
|
+
# exists, otherwise return nil to show that we don't support the
|
16
|
+
# given action.
|
17
|
+
return Action.send(name) if Action.respond_to?(name)
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# This method is called if the underlying machine ID changes. Providers
|
22
|
+
# can use this method to load in new data for the actual backing
|
23
|
+
# machine or to realize that the machine is now gone (the ID can
|
24
|
+
# become `nil`). No parameters are given, since the underlying machine
|
25
|
+
# is simply the machine instance given to this object. And no
|
26
|
+
# return value is necessary.
|
27
|
+
def machine_id_changed
|
28
|
+
end
|
29
|
+
|
30
|
+
# This should return a hash of information that explains how to
|
31
|
+
# SSH into the machine. If the machine is not at a point where
|
32
|
+
# SSH is even possible, then `nil` should be returned.
|
33
|
+
#
|
34
|
+
# The general structure of this returned hash should be the
|
35
|
+
# following:
|
36
|
+
#
|
37
|
+
# {
|
38
|
+
# :host => "1.2.3.4",
|
39
|
+
# :port => "22",
|
40
|
+
# :username => "mitchellh",
|
41
|
+
# :private_key_path => "/path/to/my/key"
|
42
|
+
# }
|
43
|
+
#
|
44
|
+
# **Note:** Vagrant only supports private key based authentication,
|
45
|
+
# mainly for the reason that there is no easy way to exec into an
|
46
|
+
# `ssh` prompt with a password, whereas we can pass a private key
|
47
|
+
# via commandline.
|
48
|
+
#
|
49
|
+
# @return [Hash] SSH information. For the structure of this hash
|
50
|
+
# read the accompanying documentation for this method.
|
51
|
+
def ssh_info
|
52
|
+
env = @machine.action(:read_ssh_info)
|
53
|
+
env[:vm_conn_info]
|
54
|
+
end
|
55
|
+
|
56
|
+
# This should return the state of the machine within this provider.
|
57
|
+
# The state must be an instance of {MachineState}. Please read the
|
58
|
+
# documentation of that class for more information.
|
59
|
+
def state
|
60
|
+
|
61
|
+
env = @machine.action("read_machine_state")
|
62
|
+
|
63
|
+
vm_name = (env[:vm_name].nil? || env[:vm_name].empty?) ? env[:machine].provider_config.vm.name : env[:vm_name]
|
64
|
+
|
65
|
+
state = (env[:machine_state].nil?) ? :unknown : env[:machine_state]
|
66
|
+
short_desc = I18n.t("secured_cloud_vagrant.states.#{state}.short")
|
67
|
+
long_desc = I18n.t("secured_cloud_vagrant.states.#{state}.long", :vm_name => vm_name)
|
68
|
+
|
69
|
+
Vagrant::MachineState.new(state, short_desc, long_desc)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/locales/en.yml
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
en:
|
2
|
+
secured_cloud_vagrant:
|
3
|
+
info:
|
4
|
+
not_created: "VM has not been created."
|
5
|
+
already_active: "VM is already active"
|
6
|
+
already_off: "VM is already off"
|
7
|
+
creating: "Creating a new VM ..."
|
8
|
+
destroying: "Destroying the VM ..."
|
9
|
+
powering_off: "Powering OFF the VM ..."
|
10
|
+
powering_on: "Powering ON the VM ..."
|
11
|
+
assigning_public_ips: "Assigning public IPs to VM ..."
|
12
|
+
reloading: "Rebooting the VM ..."
|
13
|
+
task_status: "%{percentage}% : %{task_desc}"
|
14
|
+
success:
|
15
|
+
create_vm: |-
|
16
|
+
VM %{vm_name} was successfully created with the following resource URL:
|
17
|
+
%{resource_url}
|
18
|
+
delete_vm: "VM '%{vm_name}' was successfully deleted"
|
19
|
+
power_vm: "VM '%{vm_name}' was successfully powered %{power_status}"
|
20
|
+
reboot_vm: "VM '%{vm_name}' was successfully rebooted"
|
21
|
+
assign_public_ip:
|
22
|
+
global_pool: "VM '%{vm_name}' has been successfully assigned a public IP from the global pool"
|
23
|
+
reserve_pool: "VM '%{vm_name}' has been successfully assigned public IP '%{public_ip}' from the reserve pool"
|
24
|
+
warnings:
|
25
|
+
no_public_ips: "Cannot connect to private VM '%{vm_name}'"
|
26
|
+
network_support: |-
|
27
|
+
Warning! The Secured Cloud provider doesn't support any of the Vagrant
|
28
|
+
high-level network configurations (`config.vm.network`). They will be
|
29
|
+
silently ignored.
|
30
|
+
provision_support: |-
|
31
|
+
Warning! The Secured Cloud provider doesn't support any of the Vagrant
|
32
|
+
high-level provision configurations (`config.vm.provision`). They will be
|
33
|
+
silently ignored.
|
34
|
+
errors:
|
35
|
+
unspecified_auth: |-
|
36
|
+
The authentication information must be correctly specified in the Vagrantfile
|
37
|
+
in order to be able to get the available %{resource_type}.
|
38
|
+
powering_vm: |-
|
39
|
+
There was an issue powering %{power_status} VM '%{vm_name}'.
|
40
|
+
Please check the following error message for details:
|
41
|
+
|
42
|
+
Error Message: %{error_message}
|
43
|
+
deleting_vm: |-
|
44
|
+
There was an issue with deleting VM '%{vm_name}'.
|
45
|
+
Please check the following error message for details:
|
46
|
+
|
47
|
+
Error Message: %{error_message}
|
48
|
+
creating_vm: |-
|
49
|
+
There was an issue with creating VM '%{vm_name}'.
|
50
|
+
Please check the following error message for details:
|
51
|
+
|
52
|
+
Error Message: %{error_message}
|
53
|
+
rebooting_vm: |-
|
54
|
+
There was an issue with reloading VM '%{vm_name}'.
|
55
|
+
Please check the following error message for details:
|
56
|
+
|
57
|
+
Error Message: %{error_message}
|
58
|
+
assigning_public_ip: |-
|
59
|
+
There was an issue with assigning a public IP to VM '%{vm_name}'.
|
60
|
+
Please check the following error message for details:
|
61
|
+
|
62
|
+
Error Message: %{error_message}
|
63
|
+
internal_server_error: "An internal server error occured. Please try again later."
|
64
|
+
request_timed_out: "The request made to the Secured Cloud API to %{request} timed out"
|
65
|
+
generic_error: "%{error_message}"
|
66
|
+
commands:
|
67
|
+
release_ips_confirmation: "Do you want to release the public IP(s) of the VM? [y/N]"
|
68
|
+
vm-config: |-
|
69
|
+
The following are the VM details required to connect to the Vagrant-managed VM:
|
70
|
+
HostName %{host_name}
|
71
|
+
User %{username}
|
72
|
+
Port %{port}
|
73
|
+
StrictHostKeyChecking no
|
74
|
+
PasswordAuthentication yes
|
75
|
+
Password ********
|
76
|
+
states:
|
77
|
+
not_created:
|
78
|
+
short: "not created"
|
79
|
+
long: "VM '%{vm_name}' is not created. Run 'vagrant up' to create it."
|
80
|
+
active:
|
81
|
+
short: "running"
|
82
|
+
long: |-
|
83
|
+
VM '%{vm_name}' is running. To stop it, you can run 'vagrant halt'.
|
84
|
+
To destroy it, you can run 'vagrant destroy'.
|
85
|
+
stopped:
|
86
|
+
short: "stopped"
|
87
|
+
long: "VM '%{vm_name}' is stopped. Run 'vagrant up' to start it."
|
88
|
+
unknown:
|
89
|
+
short: "unknown"
|
90
|
+
long: "Something is wrong, the state of VM '%{vm_name}' is unknown."
|
91
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'secured-cloud-vagrant/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "secured-cloud-vagrant"
|
8
|
+
spec.version = VagrantPlugins::SecuredCloud::VERSION
|
9
|
+
spec.authors = ["Leanne Borg", "Alan Vella"]
|
10
|
+
spec.email = ["leanneb@ccbilleu.com", "alanv@ccbilleu.com"]
|
11
|
+
spec.summary = "Enables Vagrant to manage machines in SecuredCloud."
|
12
|
+
spec.description = "This is a Vagrant plugin that allows Vagrant users to manage virtual machines in the SecuredCloud."
|
13
|
+
spec.homepage = "http://phoenixnap.com/secured-cloud/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
#spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.5"
|
22
|
+
spec.add_development_dependency "rake", "~> 10.1", ">= 10.1.1"
|
23
|
+
|
24
|
+
spec.add_dependency "log4r", "~> 1.1", ">= 1.1.10"
|
25
|
+
spec.add_dependency "secured_cloud_api_client", "~> 0.0", ">= 0.0.8"
|
26
|
+
|
27
|
+
# The following block of code determines the files that should be included
|
28
|
+
# in the gem. It does this by reading all the files in the directory where
|
29
|
+
# this gemspec is, and parsing out the ignored files from the gitignore.
|
30
|
+
# Note that the entire gitignore(5) syntax is not supported, specifically
|
31
|
+
# the "!" syntax, but it should mostly work correctly.
|
32
|
+
root_path = File.dirname(__FILE__)
|
33
|
+
all_files = Dir.chdir(root_path) { Dir.glob("**/{*,.*}") }
|
34
|
+
all_files.reject! { |file| [".", ".."].include?(File.basename(file)) }
|
35
|
+
gitignore_path = File.join(root_path, ".gitignore")
|
36
|
+
gitignore = File.readlines(gitignore_path)
|
37
|
+
gitignore.map! { |line| line.chomp.strip }
|
38
|
+
gitignore.reject! { |line| line.empty? || line =~ /^(#|!)/ }
|
39
|
+
|
40
|
+
unignored_files = all_files.reject do |file|
|
41
|
+
# Ignore any directories, the gemspec only cares about files
|
42
|
+
next true if File.directory?(file)
|
43
|
+
|
44
|
+
# Ignore any paths that match anything in the gitignore. We do
|
45
|
+
# two tests here:
|
46
|
+
#
|
47
|
+
# - First, test to see if the entire path matches the gitignore.
|
48
|
+
# - Second, match if the basename does, this makes it so that things
|
49
|
+
# like '.DS_Store' will match sub-directories too (same behavior
|
50
|
+
# as git).
|
51
|
+
#
|
52
|
+
gitignore.any? do |ignore|
|
53
|
+
File.fnmatch(ignore, file, File::FNM_PATHNAME) ||
|
54
|
+
File.fnmatch(ignore, File.basename(file), File::FNM_PATHNAME)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
spec.files = unignored_files
|
59
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% if !os_templates.nil? && !os_templates.empty? -%>
|
2
|
+
|
3
|
+
<% os_templates.each_pair do |key, value| -%>
|
4
|
+
Resource URL: <%= key %>
|
5
|
+
OS Name: <%= value.get_name %>
|
6
|
+
OS Version: <%= value.get_version %>
|
7
|
+
Minimum Storage: <%= value.get_minimum_storage_space %> GB
|
8
|
+
Default Admin Username: <%= value.get_administrator_username %>
|
9
|
+
Disk Expandable: <%= (value.get_disk_expandable) ? "Y" : "N" %>
|
10
|
+
|
11
|
+
<% end -%>
|
12
|
+
<% end -%>
|