diff --git a/README.md b/README.md index 2fb385c..2909f3f 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,16 @@ These steps expect two environment vars ### DNS AWS will setup a private ip and private dns hostname for the VM once running. Optionally we can setup a human readable DNS entry to resolve the VMPooler provider `spicy-proton` fqdn -DNS is integrated via Google's CloudDNS service. To enable, a CloudDNS zone name must be provided in the config (see the example yaml file dns_zone_resource_name) +DNS is integrated via Google's CloudDNS service. +GCE authorization is handled via a service account (or personal account) private key (json format) and can be configured via + +1. GOOGLE_APPLICATION_CREDENTIALS environment variable eg GOOGLE_APPLICATION_CREDENTIALS=/my/home/directory/my_account_key.json + +Provider config needed: +1. domain +2. project +3. dns_zone_resource_name +(see the example yaml file) An A record is then created in that zone upon instance creation with the VM's internal IP, and deleted when the instance is destroyed. @@ -44,8 +53,7 @@ do not have the pool label, and can be configured to allow a specific list of un ### Pre-requisite - An IAM user must exist in the target AWS account with permissions to create, delete vms etc -- if using DNS, a DNS zone needs to be created in CloudDNS, and configured in the provider's config section with the name of that zone (dns_zone_resource_name). When not specified, the DNS setup and teardown is skipped. - +- if using DNS see section above, and a service account with permissions to change Cloud DNS need to exist ## License diff --git a/lib/vmpooler/providers/ec2.rb b/lib/vmpooler/providers/ec2.rb index b142675..9dfc108 100644 --- a/lib/vmpooler/providers/ec2.rb +++ b/lib/vmpooler/providers/ec2.rb @@ -3,6 +3,7 @@ require 'bigdecimal' require 'bigdecimal/util' require 'vmpooler/providers/base' +require 'vmpooler/cloud_dns' require 'aws-sdk-ec2' require 'vmpooler/aws_setup' @@ -61,8 +62,6 @@ module Vmpooler end end - attr_reader :dns - # main configuration options def region return provider_config['region'] if provider_config['region'] @@ -85,6 +84,10 @@ module Vmpooler end # dns + def project + provider_config['project'] + end + def domain provider_config['domain'] end @@ -267,10 +270,13 @@ module Vmpooler @logger.log('s', "[>] [#{pool_name}] '#{new_vmname}' instance ready to accept traffic") created_instance = get_vm(pool_name, new_vmname) - @redis.hset("vmpooler__vm__#{new_vmname}", 'host', created_instance['name']) + @redis.with_metrics do |redis| + redis.hset("vmpooler__vm__#{new_vmname}", 'host', created_instance['name']) + end # extra setup steps provision_node_aws(created_instance['private_dns_name'], pool_name, new_vmname) if to_provision(pool_name) == 'true' || to_provision(pool_name) == true + dns_setup(created_instance) if domain created_instance end @@ -363,7 +369,7 @@ module Vmpooler # [String] vm_name : Name of the existing VM # returns # [boolean] true : once the operations are finished - def destroy_vm(_pool_name, vm_name) + def destroy_vm(pool_name, vm_name) debug_logger('destroy_vm') deleted = false @@ -374,6 +380,7 @@ module Vmpooler instances = connection.instances(filters: filters).first return true if instances.nil? + instance_hash = get_vm(pool_name, vm_name) debug_logger("trigger delete_instance #{vm_name}") # vm_hash = get_vm(pool_name, vm_name) instances.terminate @@ -384,6 +391,8 @@ module Vmpooler debug_logger("failed waiting for instance terminated #{vm_name}: #{e}") end + dns_teardown(instance_hash) if domain + deleted end @@ -437,6 +446,16 @@ module Vmpooler # END BASE METHODS + def dns_setup(created_instance) + dns = Vmpooler::PoolManager::CloudDns.new(project, dns_zone_resource_name) + dns.dns_create_or_replace(created_instance) + end + + def dns_teardown(created_instance) + dns = Vmpooler::PoolManager::CloudDns.new(project, dns_zone_resource_name) + dns.dns_teardown(created_instance) + end + def get_current_user(vm_name) @redis.with_metrics do |redis| user = redis.hget("vmpooler__vm__#{vm_name}", 'token:user') @@ -494,6 +513,7 @@ module Vmpooler 'status' => vm_object.state&.name, # One of the following values: pending, running, shutting-down, terminated, stopping, stopped # 'zone' => vm_object.zone, 'image_size' => vm_object.instance_type, + 'ip' => vm_object.private_ip_address, 'private_ip_address' => vm_object.private_ip_address, 'private_dns_name' => vm_object.private_dns_name } diff --git a/spec/unit/providers/ec2_spec.rb b/spec/unit/providers/ec2_spec.rb index 5225835..9f33376 100644 --- a/spec/unit/providers/ec2_spec.rb +++ b/spec/unit/providers/ec2_spec.rb @@ -53,23 +53,28 @@ EOT describe '#manual tests live' do context 'in itsysops' do - let(:vmname) { "instance-50" } - let(:poolname) { "ubuntu-2004-arm64" } + let(:vmname) { "instance-60" } + let(:poolname) { "amazon-7-x86_64-local" } + let(:amisize) { "c5.xlarge" } let(:config) { YAML.load(<<~EOT --- :config: max_tries: 3 retry_factor: 10 + site_name: 'vmpooler-local-dev' :providers: :ec2: connection_pool_timeout: 1 zone: '#{zone}' region: '#{region}' + project: 'vmpooler-test' + dns_zone_resource_name: 'vmpooler-test-puppet-net' + domain: 'vmpooler-test.puppet.net' :pools: - name: '#{poolname}' alias: [ 'mockpool' ] - amisize: 'a1.large' - template: 'ami-03c1b544a7566b3e5' + amisize: '#{amisize}' + template: 'ami-31394949' size: 5 timeout: 10 ready_ttl: 1440 @@ -83,6 +88,7 @@ EOT } skip 'gets a vm' do result = subject.create_vm(poolname, vmname) + result = subject.destroy_vm(poolname, vmname) #subject.vms_in_pool("amazon-6-x86_64-ec2") #subject.provision_node_aws("ip-10-227-4-97.amz-dev.puppet.net", poolname) # subject.create_snapshot(poolname, vmname, "foo") diff --git a/vmpooler-provider-ec2.gemspec b/vmpooler-provider-ec2.gemspec index dd6986a..e084e70 100644 --- a/vmpooler-provider-ec2.gemspec +++ b/vmpooler-provider-ec2.gemspec @@ -16,9 +16,11 @@ Gem::Specification.new do |s| s.files = Dir[ "lib/**/*" ] s.require_paths = ["lib"] s.add_dependency 'aws-sdk-ec2', '~> 1' - s.add_dependency 'net-ssh', '~> 6.2.0.rc2' + s.add_dependency 'net-ssh', '>= 6.2', '< 7.1' s.add_development_dependency 'vmpooler', '>= 1.3.0', '~> 2.3' + #s.add_development_dependency 'vmpooler-provider-gce', '>= 0.4.0', '~> 0.4' + s.add_development_dependency 'vmpooler-provider-gce', '>= 0.4.0', '~> 0.4' # Testing dependencies s.add_development_dependency 'climate_control', '>= 0.2.0' diff --git a/vmpooler.yaml.example b/vmpooler.yaml.example index 28b92a3..24fdb64 100644 --- a/vmpooler.yaml.example +++ b/vmpooler.yaml.example @@ -81,7 +81,10 @@ # Overwrites the global domain parameter. This should match the dns zone domain set for the dns_zone_resource_name. # It is used to infer the domain part of the FQDN ie $vm_name.$domain # When setting multiple providers at the same time, this value should be set for each GCE pools. -# (optional) If not explicitely set, the FQDN is inferred using the global 'domain' config parameter +# (optional) when not set, the dns setup / teardown is skipped and the instance is reachable via the private_dns_name +# - project +# The GCP project name where the DNS zone resource exists +# (optional) # Example: :aws: @@ -91,6 +94,7 @@ volume_size: '10' dns_zone_resource_name: 'subdomain-example-com' domain: 'subdomain.example.com' + project: 'gcp-project-1' # :pools: #