From 3aa83897493b283854fdd89e46d2a701a3f6b880 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Tue, 30 Jun 2015 10:38:59 -0700 Subject: [PATCH 1/3] Discard/skip empty tags --- lib/vmpooler/api/v1.rb | 2 ++ spec/vmpooler/api/v1_spec.rb | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/lib/vmpooler/api/v1.rb b/lib/vmpooler/api/v1.rb index dfba6fb..8fdc590 100644 --- a/lib/vmpooler/api/v1.rb +++ b/lib/vmpooler/api/v1.rb @@ -499,6 +499,8 @@ module Vmpooler arg[tag] = arg[tag].match(filter).captures.join if arg[tag].match(filter) end + next if arg[tag].nil? or arg[tag].empty? + backend.hset('vmpooler__vm__' + params[:hostname], 'tag:' + tag, arg[tag]) backend.hset('vmpooler__tag__' + Date.today.to_s, params[:hostname] + ':' + tag, arg[tag]) end diff --git a/spec/vmpooler/api/v1_spec.rb b/spec/vmpooler/api/v1_spec.rb index 788bc24..7c17b82 100644 --- a/spec/vmpooler/api/v1_spec.rb +++ b/spec/vmpooler/api/v1_spec.rb @@ -323,6 +323,15 @@ describe Vmpooler::API::V1 do expect(last_response.status).to eq(200) end + it 'skips empty tags' do + put "#{prefix}/vm/testhost", '{"tags":{"tested_by":""}}' + + expect(last_response).to be_ok + expect(last_response.header['Content-Type']).to eq('application/json') + expect(last_response.body).to eq(JSON.pretty_generate({'ok' => true})) + expect(last_response.status).to eq(200) + end + it 'does not set tags if request body format is invalid' do put "#{prefix}/vm/testhost", '{"tags":{"tested"}}' From 6523062b62852709b5d49e01bc27fcb61cc3b525 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Tue, 30 Jun 2015 10:57:49 -0700 Subject: [PATCH 2/3] Allow for only a [configurable] tag set --- lib/vmpooler/api/v1.rb | 4 ++++ spec/vmpooler/api/v1_spec.rb | 17 +++++++++++++++++ vmpooler.yaml.example | 6 ++++++ 3 files changed, 27 insertions(+) diff --git a/lib/vmpooler/api/v1.rb b/lib/vmpooler/api/v1.rb index 8fdc590..e24c03c 100644 --- a/lib/vmpooler/api/v1.rb +++ b/lib/vmpooler/api/v1.rb @@ -476,6 +476,10 @@ module Vmpooler unless arg.is_a?(Hash) failure = true end + + if config['allowed_tags'] + failure = true if not (arg.keys - config['allowed_tags']).empty? + end else failure = true end diff --git a/spec/vmpooler/api/v1_spec.rb b/spec/vmpooler/api/v1_spec.rb index 7c17b82..7ef1b5e 100644 --- a/spec/vmpooler/api/v1_spec.rb +++ b/spec/vmpooler/api/v1_spec.rb @@ -341,6 +341,23 @@ describe Vmpooler::API::V1 do expect(last_response.status).to eq(400) end + context '(allowed_tags configured)' do + let(:config) { { + config: { + 'allowed_tags' => ['created_by', 'project', 'url'] + } + } } + + it 'fails if specified tag is not in allowed_tags array' do + put "#{prefix}/vm/testhost", '{"tags":{"created_by":"rspec","tested_by":"rspec"}}' + + expect(last_response).to_not be_ok + expect(last_response.header['Content-Type']).to eq('application/json') + expect(last_response.body).to eq(JSON.pretty_generate({'ok' => false})) + expect(last_response.status).to eq(400) + end + end + context '(tagfilter configured)' do let(:config) { { tagfilter: { 'url' => '(.*)\/' }, diff --git a/vmpooler.yaml.example b/vmpooler.yaml.example index dda99cc..114a7c4 100644 --- a/vmpooler.yaml.example +++ b/vmpooler.yaml.example @@ -156,6 +156,9 @@ # Same as vm_lifetime, but applied if a valid authentication token is # included during the request. # +# - allowed_tags +# If set, restricts tags to those specified in this array. +# # - domain # If set, returns a top-level 'domain' JSON key in POST requests @@ -169,6 +172,9 @@ vm_checktime: 15 vm_lifetime: 12 vm_lifetime_auth: 24 + allowed_tags: + - 'created_by' + - 'project' domain: 'company.com' # :pools: From c720f12c05b76bea997c618b25394415471aa667 Mon Sep 17 00:00:00 2001 From: Scott Schneider Date: Tue, 30 Jun 2015 12:46:54 -0700 Subject: [PATCH 3/3] Move tag-filtering and exporting to API helper methods --- lib/vmpooler/api/helpers.rb | 20 ++++++++++++++++++++ lib/vmpooler/api/v1.rb | 13 ++----------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/lib/vmpooler/api/helpers.rb b/lib/vmpooler/api/helpers.rb index a97455b..334a99b 100644 --- a/lib/vmpooler/api/helpers.rb +++ b/lib/vmpooler/api/helpers.rb @@ -79,6 +79,26 @@ module Vmpooler return false end + def export_tags(backend, hostname, tags) + tags.each_pair do |tag, value| + next if value.nil? or value.empty? + + backend.hset('vmpooler__vm__' + hostname, 'tag:' + tag, value) + backend.hset('vmpooler__tag__' + Date.today.to_s, hostname + ':' + tag, value) + end + end + + def filter_tags(tags) + return unless Vmpooler::API.settings.config[:tagfilter] + + tags.each_pair do |tag, value| + next unless filter = Vmpooler::API.settings.config[:tagfilter][tag] + tags[tag] = value.match(filter).captures.join if value.match(filter) + end + + tags + end + def mean(list) s = list.map(&:to_f).reduce(:+).to_f (s > 0 && list.length > 0) ? s / list.length.to_f : 0 diff --git a/lib/vmpooler/api/v1.rb b/lib/vmpooler/api/v1.rb index e24c03c..d27c474 100644 --- a/lib/vmpooler/api/v1.rb +++ b/lib/vmpooler/api/v1.rb @@ -497,17 +497,8 @@ module Vmpooler backend.hset('vmpooler__vm__' + params[:hostname], param, arg) when 'tags' - arg.keys.each do |tag| - if Vmpooler::API.settings.config[:tagfilter] and Vmpooler::API.settings.config[:tagfilter][tag] - filter = Vmpooler::API.settings.config[:tagfilter][tag] - arg[tag] = arg[tag].match(filter).captures.join if arg[tag].match(filter) - end - - next if arg[tag].nil? or arg[tag].empty? - - backend.hset('vmpooler__vm__' + params[:hostname], 'tag:' + tag, arg[tag]) - backend.hset('vmpooler__tag__' + Date.today.to_s, params[:hostname] + ':' + tag, arg[tag]) - end + filter_tags(arg) + export_tags(backend, params[:hostname], arg) end end