Implementing the tag_vm_user method

This method gets the user name based on the token:user metadata in redis,
cleans it up to be safe for a label name (lowercase, numbers and dash or underscore only),
and update the existing instance labels adding a new one called token-user
This commit is contained in:
Samuel Beaulieu 2021-12-09 11:35:29 -06:00
parent f6791baba0
commit 8594160fbe
No known key found for this signature in database
GPG key ID: 12030F74136D0F34
2 changed files with 72 additions and 10 deletions

View file

@ -488,6 +488,37 @@ module Vmpooler
end end
end end
# tag_vm_user This method is called once we know who is using the VM (it is running). This method enables seeing
# who is using what in the provider pools.
#
# inputs
# [String] pool_name : Name of the pool
# [String] vm_name : Name of the VM to check if ready
# returns
# [Boolean] : true if successful, false if an error occurred and it should retry
def tag_vm_user(pool, vm)
@redis.with_metrics do |redis|
user = get_current_user(vm)
vm_hash = get_vm(pool, vm)
return false if vm_hash.nil?
new_labels = vm_hash['labels']
# bailing in this case since labels should exist, and continuing would mean losing them
return false if new_labels.nil?
# add new label called token-user, with value as user
new_labels['token-user'] = user
begin
instances_set_labels_request_object = Google::Apis::ComputeV1::InstancesSetLabelsRequest.new(label_fingerprint:vm_hash['label_fingerprint'], labels: new_labels)
result = connection.set_instance_labels(project, zone(pool), vm, instances_set_labels_request_object)
wait_for_zone_operation(project, zone(pool), result, connection)
rescue StandardError => _e
return false
end
return true
end
end
# END BASE METHODS
def should_be_ignored(item, allowlist) def should_be_ignored(item, allowlist)
allowlist.map!(&:downcase) # remove uppercase from configured values because its not valid as resource label allowlist.map!(&:downcase) # remove uppercase from configured values because its not valid as resource label
array_flattened_labels = [] array_flattened_labels = []
@ -501,7 +532,18 @@ module Vmpooler
!(allowlist & array_flattened_labels).empty? # the allow list specify a fully qualified label eg user=Bob and the item has it !(allowlist & array_flattened_labels).empty? # the allow list specify a fully qualified label eg user=Bob and the item has it
end end
# END BASE METHODS def get_current_user(vm)
@redis.with_metrics do |redis|
user = redis.hget("vmpooler__vm__#{vm}", 'token:user')
return "" if user.nil?
# cleanup so it's a valid label value
# can't have upercase
user = user.downcase
# replace invalid chars with dash
user = user.gsub(/[^0-9a-z_-]/, '-')
return user
end
end
# Compute resource wait for operation to be DONE (synchronous operation) # Compute resource wait for operation to be DONE (synchronous operation)
def wait_for_zone_operation(project, zone, result, connection, retries=5) def wait_for_zone_operation(project, zone, result, connection, retries=5)
@ -549,7 +591,9 @@ module Vmpooler
'boottime' => vm_object.creation_timestamp, 'boottime' => vm_object.creation_timestamp,
'status' => vm_object.status, # One of the following values: PROVISIONING, STAGING, RUNNING, STOPPING, SUSPENDING, SUSPENDED, REPAIRING, and TERMINATED 'status' => vm_object.status, # One of the following values: PROVISIONING, STAGING, RUNNING, STOPPING, SUSPENDING, SUSPENDED, REPAIRING, and TERMINATED
'zone' => vm_object.zone, 'zone' => vm_object.zone,
'machine_type' => vm_object.machine_type 'machine_type' => vm_object.machine_type,
'labels' => vm_object.labels,
'label_fingerprint' => vm_object.label_fingerprint
#'powerstate' => powerstate #'powerstate' => powerstate
} }
end end

View file

@ -38,7 +38,7 @@ EOT
) )
} }
let(:vmname) { 'vm13' } let(:vmname) { 'vm15' }
let(:connection) { MockComputeServiceConnection.new } let(:connection) { MockComputeServiceConnection.new }
let(:redis_connection_pool) { Vmpooler::PoolManager::GenericConnectionPool.new( let(:redis_connection_pool) { Vmpooler::PoolManager::GenericConnectionPool.new(
metrics: metrics, metrics: metrics,
@ -61,6 +61,8 @@ EOT
skip 'runs in gce' do skip 'runs in gce' do
puts "creating" puts "creating"
result = subject.create_vm(poolname, vmname) result = subject.create_vm(poolname, vmname)
subject.get_vm(poolname, vmname)
=begin
puts "create snapshot w/ one disk" puts "create snapshot w/ one disk"
result = subject.create_snapshot(poolname, vmname, "sams") result = subject.create_snapshot(poolname, vmname, "sams")
puts "create disk" puts "create disk"
@ -69,6 +71,7 @@ EOT
result = subject.create_snapshot(poolname, vmname, "sams2") result = subject.create_snapshot(poolname, vmname, "sams2")
puts "revert snapshot" puts "revert snapshot"
result = subject.revert_snapshot(poolname, vmname, "sams") result = subject.revert_snapshot(poolname, vmname, "sams")
=end
#result = subject.destroy_vm(poolname, vmname) #result = subject.destroy_vm(poolname, vmname)
end end
@ -738,4 +741,19 @@ EOT
end end
end end
describe '#get_current_user' do
it 'should downcase and replace invalid chars with dashes' do
redis_connection_pool.with_metrics do |redis|
redis.hset("vmpooler__vm__#{vmname}", 'token:user', "BOBBY.PUPPET")
expect(subject.get_current_user(vmname)).to eq("bobby-puppet")
end
end
it 'returns "" for nil values' do
redis_connection_pool.with_metrics do |redis|
expect(subject.get_current_user(vmname)).to eq("")
end
end
end
end end