From 8f6b593c36d37c0914f68b2420d70c2575b801c3 Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Fri, 11 Jun 2021 13:47:21 +1000 Subject: [PATCH] feat: add record-support-ended (feature toggled off) --- .../client/cli/deployment_commands.rb | 18 +- lib/pact_broker/client/deployments.rb | 8 +- .../deployments/record_support_ended.rb | 103 +++++++++ .../client/deployments/record_undeployment.rb | 2 +- script/record-deployments-and-releases.sh | 14 +- .../deployments/record_support_ended_spec.rb | 208 ++++++++++++++++++ .../deployments/record_undeployment_spec.rb | 4 +- 7 files changed, 346 insertions(+), 11 deletions(-) create mode 100644 lib/pact_broker/client/deployments/record_support_ended.rb create mode 100644 spec/lib/pact_broker/client/deployments/record_support_ended_spec.rb diff --git a/lib/pact_broker/client/cli/deployment_commands.rb b/lib/pact_broker/client/cli/deployment_commands.rb index 2f2f46e7..f4b770d5 100644 --- a/lib/pact_broker/client/cli/deployment_commands.rb +++ b/lib/pact_broker/client/cli/deployment_commands.rb @@ -24,7 +24,7 @@ def record_deployment execute_deployment_command(params, "RecordDeployment") end - desc "record-undeployment", "Record undeployment of a pacticipant version from an environment." + desc "record-undeployment", "Record undeployment of a pacticipant from an environment." long_desc "Note that use of this command is not required if you are deploying over a previous version, as record-deployment will handle that scenario for you. This command is only required if you are permanently removing an application instance from an environment." method_option :pacticipant, required: true, aliases: "-a", desc: "The name of the pacticipant that was undeployed." method_option :environment, required: true, desc: "The name of the environment that the pacticipant version was undeployed from." @@ -57,6 +57,22 @@ def record_release execute_deployment_command(params, "RecordRelease") end + desc "record-support-ended", "Record the end of support for a pacticipant version in an environment." + method_option :pacticipant, required: true, aliases: "-a", desc: "The name of the pacticipant." + method_option :version, required: true, aliases: "-e", desc: "The pacticipant version number for which support is ended." + method_option :environment, required: true, desc: "The name of the environment in which the support is ended." + output_option_json_or_text + shared_authentication_options + + def record_support_ended + params = { + pacticipant_name: options.pacticipant, + version_number: options.version, + environment_name: options.environment + } + execute_deployment_command(params, "RecordSupportEnded") + end + no_commands do def execute_deployment_command(params, command_class_name) require 'pact_broker/client/deployments' diff --git a/lib/pact_broker/client/deployments.rb b/lib/pact_broker/client/deployments.rb index cd097b34..9fecf6e6 100644 --- a/lib/pact_broker/client/deployments.rb +++ b/lib/pact_broker/client/deployments.rb @@ -1,4 +1,4 @@ -require 'pact_broker/client/deployments/record_deployment' -require 'pact_broker/client/deployments/record_release' -require 'pact_broker/client/deployments/record_undeployment' - +require "pact_broker/client/deployments/record_deployment" +require "pact_broker/client/deployments/record_release" +require "pact_broker/client/deployments/record_undeployment" +require "pact_broker/client/deployments/record_support_ended" diff --git a/lib/pact_broker/client/deployments/record_support_ended.rb b/lib/pact_broker/client/deployments/record_support_ended.rb new file mode 100644 index 00000000..4c205750 --- /dev/null +++ b/lib/pact_broker/client/deployments/record_support_ended.rb @@ -0,0 +1,103 @@ +require 'pact_broker/client/base_command' + +module PactBroker + module Client + module Deployments + class RecordSupportEnded < PactBroker::Client::BaseCommand + def initialize(params, options, pact_broker_client_options) + super + @pacticipant_name = params.fetch(:pacticipant_name) + @environment_name = params.fetch(:environment_name) + @version_number = params.fetch(:version_number) + end + + private + + def do_call + if unsupported_versions_resources.empty? + PactBroker::Client::CommandResult.new(false, error_result_message) + else + PactBroker::Client::CommandResult.new(unsupported_versions_resources.all?(&:success?), result_message) + end + end + + attr_reader :pacticipant_name, :environment_name, :version_number + + def currently_supported_versions_link + environment_resource._link("pb:currently-supported-versions") or raise PactBroker::Client::Error.new(not_supported_message) + end + + def currently_supported_version_entities_for_pacticipant_version + @deployed_version_links ||= currently_supported_versions_link.get!(pacticipant: pacticipant_name, version: version_number).embedded_entities!("releasedVersions") + end + + def unsupported_versions_resources + @unsupported_versions_resources ||= currently_supported_version_entities_for_pacticipant_version.collect do | entity | + entity._link!("self").patch(currentlySupported: false) + end + end + + def action + "undeployment" + end + + def environment_resource + index_resource + ._link!("pb:environments") + .get! + ._links("pb:environments") + .find!(environment_name, "No environment found with name '#{environment_name}'") + .get! + end + + def result_message + if json_output? + unsupported_versions_resources.collect{ | resource | resource.response.body }.to_a.to_json + else + unsupported_versions_resources.collect do | undeployed_versions_resource | + if undeployed_versions_resource.success? + green("#{success_result_text_message(undeployed_versions_resource)} in #{pact_broker_name}.") + else + red(undeployed_versions_resource.error_message) + end + end.join("\n") + end + end + + def success_result_text_message(undeployed_versions_resource) + "Recorded support ended for #{pacticipant_name} version #{version_number} in #{environment_name} environment" + end + + def error_result_message + if json_output? + error_message_as_json(error_text) + else + red(error_text) + end + end + + def error_text + if pacticipant_does_not_exist? + "No pacticipant with name '#{pacticipant_name}' found." + else + "#{pacticipant_name} version #{version_number} is not currently released in #{environment_name} environment. Cannot record support ended." + end + end + + def not_supported_message + "This version of the Pact Broker does not support recording end of support. Please upgrade to version 2.80.0 or later." + end + + def pacticipant_does_not_exist? + index_resource._link("pb:pacticipant") && index_resource._link("pb:pacticipant").expand(pacticipant: pacticipant_name).get.does_not_exist? + end + + def check_if_command_supported + unless index_resource.can?("pb:environments") + raise PactBroker::Client::Error.new(not_supported_message) + end + end + end + end + end +end diff --git a/lib/pact_broker/client/deployments/record_undeployment.rb b/lib/pact_broker/client/deployments/record_undeployment.rb index c1629e32..61212702 100644 --- a/lib/pact_broker/client/deployments/record_undeployment.rb +++ b/lib/pact_broker/client/deployments/record_undeployment.rb @@ -89,7 +89,7 @@ def error_result_message def error_text if pacticipant_does_not_exist? - "No pacticipant with name '#{pacticipant_name}' found" + "No pacticipant with name '#{pacticipant_name}' found." else if currently_deployed_version_entities_for_pacticipant.any? target_does_not_match_message diff --git a/script/record-deployments-and-releases.sh b/script/record-deployments-and-releases.sh index 542323e9..5bee45d0 100755 --- a/script/record-deployments-and-releases.sh +++ b/script/record-deployments-and-releases.sh @@ -5,6 +5,14 @@ bundle exec bin/pact-broker create-version-tag --pacticipant Foo --version 2 --t bundle exec bin/pact-broker describe-version --pacticipant Foo --version 2 bundle exec bin/pact-broker create-environment --name test bundle exec bin/pact-broker can-i-deploy --pacticipant Foo --version 2 --to-environment test -bundle exec bin/pact-broker record-deployment --pacticipant Foo --version 2 --environment test --target foo -bundle exec bin/pact-broker record-undeployment --pacticipant Foo --version 2 --environment test --target foo -bundle exec bin/pact-broker record-release --pacticipant Foo --version 2 --environment test \ No newline at end of file + +bundle exec bin/pact-broker record-deployment --pacticipant Foo --version 2 --environment test +bundle exec bin/pact-broker record-deployment --pacticipant Foo --version 2 --environment test --target customer-1 +bundle exec bin/pact-broker record-deployment --pacticipant Foo --version 2 --environment test --target customer-1 + +bundle exec bin/pact-broker record-undeployment --pacticipant Foo --environment test +bundle exec bin/pact-broker record-undeployment --pacticipant Foo --environment test +bundle exec bin/pact-broker record-undeployment --pacticipant Foo --environment test --target customer-1 + +bundle exec bin/pact-broker record-release --pacticipant Foo --version 2 --environment test +bundle exec bin/pact-broker record-support-ended --pacticipant Foo --version 2 --environment test \ No newline at end of file diff --git a/spec/lib/pact_broker/client/deployments/record_support_ended_spec.rb b/spec/lib/pact_broker/client/deployments/record_support_ended_spec.rb new file mode 100644 index 00000000..cabb896c --- /dev/null +++ b/spec/lib/pact_broker/client/deployments/record_support_ended_spec.rb @@ -0,0 +1,208 @@ +require 'pact_broker/client/deployments/record_support_ended' + +module PactBroker + module Client + module Deployments + describe RecordSupportEnded do + let(:params) do + { + pacticipant_name: "Foo", + version_number: version_number, + environment_name: "test" + } + end + let(:version_number) { "2" } + let(:output) { "text" } + let(:options) { { output: output, verbose: true } } + let(:pact_broker_base_url) { "http://broker" } + let(:pact_broker_client_options) { { pact_broker_base_url: pact_broker_base_url } } + + let(:index_body_hash) do + { + _links: { + :'pb:environments' => { + href: environments_url + }, + :'pb:pacticipant' => { + href: pacticipant_url + } + } + } + end + + let(:environments_hash) do + { + _links: { + :'pb:environments' => [ + { + name: "test", + href: test_environment_url + } + ] + } + } + end + + let(:environment_hash) do + { + _links: { + :'pb:currently-supported-versions' => { + href: currently_supported_versions_url + } + } + } + end + + let(:supported_versions_hash) do + { + _embedded: { + releasedVersions: [ + { + number: "customer-1", + _links: { + self: { + href: supported_version_url_1 + } + } + }, + { + number: returned_target_2, + _links: { + self: { + href: supported_version_url_2 + } + } + } + ] + } + } + end + + let(:returned_target_2) { nil } + let(:supported_version_hash) do + { + _embedded: { + version: { + number: "2" + } + } + } + end + + let(:environments_url) { "#{webmock_base_url}/environments" } + let(:test_environment_url) { "#{webmock_base_url}/environments/1234" } + let(:currently_supported_versions_url) { "#{webmock_base_url}/currently-deployed-versions" } + let(:supported_version_url_1) { "#{webmock_base_url}/deployed-version-1" } + let(:supported_version_url_2) { "#{webmock_base_url}/deployed-version-2" } + let(:pacticipant_url) { "#{webmock_base_url}/pacticipant" } + + let(:webmock_base_url) { "http://broker" } + + let!(:index_request) do + stub_request(:get, "http://broker").to_return(status: 200, body: index_body_hash.to_json, headers: { "Content-Type" => "application/hal+json" } ) + end + + let!(:environments_request) do + stub_request(:get, "http://broker/environments").to_return(status: 200, body: environments_hash.to_json, headers: { "Content-Type" => "application/hal+json" } ) + end + + let!(:environment_request) do + stub_request(:get, test_environment_url).to_return(status: 200, body: environment_hash.to_json, headers: { "Content-Type" => "application/hal+json" } ) + end + + let!(:supported_versions_request) do + stub_request(:get, currently_supported_versions_url + "?pacticipant=Foo&version=2").to_return(status: 200, body: supported_versions_hash.to_json, headers: { "Content-Type" => "application/hal+json" } ) + end + + let!(:supported_version_patch_request_1) do + stub_request(:patch, supported_version_url_1).with(body: { currentlySupported: false}.to_json).to_return(status: 200, body: supported_version_hash.to_json, headers: { "Content-Type" => "application/hal+json" }) + end + + let!(:supported_version_patch_request_2) do + stub_request(:patch, supported_version_url_2).with(body: { currentlySupported: false}.to_json).to_return(status: 200, body: supported_version_hash.to_json, headers: { "Content-Type" => "application/hal+json" }) + end + + let!(:pacticipant_request) do + stub_request(:get, pacticipant_url).to_return(status: pacticipant_request_status, body: {}.to_json, headers: { "Content-Type" => "application/hal+json" }) + end + + let(:pacticipant_request_status) { 200 } + + subject { RecordSupportEnded.call(params, options, pact_broker_client_options) } + + its(:success) { is_expected.to eq true } + its(:message) { is_expected.to include "Recorded support ended for Foo version 2 in test environment in the Pact Broker" } + + context "when there is no pb:environments relation in the index" do + let(:index_body_hash) do + { + _links: {} + } + end + + its(:success) { is_expected.to be false } + its(:message) { is_expected.to include "support" } + end + + context "when output is json" do + let(:output) { "json" } + its(:message) { is_expected.to eq [supported_version_hash, supported_version_hash].to_json } + end + + context "when there is an error returned from one of the supported version updates (there should only ever be one supported version, but testing just for the sake of it)" do + let!(:supported_version_patch_request_2) do + stub_request(:patch, supported_version_url_2).to_return(status: 400, body: { errors: { foo: ["some error"]}}.to_json, headers: { "Content-Type" => "application/hal+json" }) + end + + let(:returned_target_2) { "customer-1" } + + its(:success) { is_expected.to be false } + its(:message) { is_expected.to include "Recorded" } + its(:message) { is_expected.to include "some error" } + end + + context "when there is no currently-deployed-versions relation in the environment resource" do + let(:environment_hash) do + { + _links: {} + } + end + + its(:success) { is_expected.to be false } + its(:message) { is_expected.to include "support" } + end + + context "when there is no matching supported versions" do + let(:supported_versions_hash) do + { + _embedded: { + releasedVersions: [] + } + } + end + + let(:expected_message) { "Foo version 2 is not currently released in test environment. Cannot record support ended." } + + its(:success) { is_expected.to be false } + its(:message) { is_expected.to include expected_message } + + context "when there are no supported versions for the pacticipant" do + context "when the pacticipant does not exist" do + let(:pacticipant_request_status) { 404 } + + its(:success) { is_expected.to be false } + its(:message) { is_expected.to include "No pacticipant with name 'Foo' found" } + end + end + + context "when output is json" do + let(:output) { "json" } + + its(:message) { is_expected.to eq({ error: { message: expected_message } }.to_json) } + end + end + + end + end + end +end diff --git a/spec/lib/pact_broker/client/deployments/record_undeployment_spec.rb b/spec/lib/pact_broker/client/deployments/record_undeployment_spec.rb index 9d6e1358..457cb0db 100644 --- a/spec/lib/pact_broker/client/deployments/record_undeployment_spec.rb +++ b/spec/lib/pact_broker/client/deployments/record_undeployment_spec.rb @@ -207,10 +207,10 @@ module Deployments its(:message) { is_expected.to include "Foo is not currently deployed to test environment. Cannot record undeployment." } context "when the pacticipant does not exist" do - let(:pacticipant_request_status) { 200 } + let(:pacticipant_request_status) { 404 } its(:success) { is_expected.to be false } - its(:message) { is_expected.to include "Foo is not currently deployed to test environment. Cannot record undeployment." } + its(:message) { is_expected.to include "No pacticipant with name 'Foo' found" } end end end