diff --git a/lib/hosting/gcp_apis.rb b/lib/hosting/gcp_apis.rb index c31a55a1d..0bef74720 100644 --- a/lib/hosting/gcp_apis.rb +++ b/lib/hosting/gcp_apis.rb @@ -245,9 +245,8 @@ def resize_vm_disk(zone, disk_source, storage_size_gib) wait_for_operation(zone, data["id"]) end - def list_objects(bucket, pattern) + def list_objects(bucket, pattern, query = {matchGlob: pattern, delimiter: "/"}) connection = Excon.new("https://storage.googleapis.com", headers: @host[:headers]) - query = {matchGlob: pattern, delimiter: "/"} response = connection.get(path: "/storage/v1/b/#{bucket}/o", query: query, expects: [200, 400]) Hosting::GcpApis.check_errors(response) @@ -500,6 +499,22 @@ def add_delete_lifecycle_rule(bucket, prefix) } } + # Delete rules that are already applied + if data["lifecycle"] + existing_rules = data["lifecycle"]["rule"] + + existing_rules.each do |rule| + rule_prefixes = rule.dig("condition", "matchesPrefix") || [] + applied_prefixes = rule_prefixes.select do |rule_prefix| + list_objects(bucket, rule_prefix, {prefix: rule_prefix, maxResults: 1}).any? + end + + if applied_prefixes.empty? + data["lifecycle"]["rule"].delete(rule) + end + end + end + if data.empty? data = {"lifecycle" => {"rule" => [lifecycle_rule]}} else diff --git a/spec/lib/hosting/gcp_apis_spec.rb b/spec/lib/hosting/gcp_apis_spec.rb index cb03d276c..8e3bc60f1 100644 --- a/spec/lib/hosting/gcp_apis_spec.rb +++ b/spec/lib/hosting/gcp_apis_spec.rb @@ -549,6 +549,18 @@ .with(body: JSON.dump({"lifecycle" => {"rule" => [{"action" => {"type" => "Delete"}, "condition" => {age: 0, matchesPrefix: ["test-ubid2"]}}, {"action" => {"type" => "Delete"}, "condition" => {age: 0, matchesPrefix: ["test-ubid"]}}]}})) .to_return(status: 200, body: JSON.dump({}), headers: {"Content-Type" => "application/json"}) api = described_class.new + expect(api).to receive(:list_objects).and_return([1]).at_least(:once) + expect { api.add_delete_lifecycle_rule("test", "test-ubid") }.not_to raise_error + end + + it "adds lifecycle rule and deletes already applied rules" do + stub_request(:post, "https://oauth2.googleapis.com/token").to_return(status: 200, body: JSON.dump({}), headers: {"Content-Type" => "application/json"}) + stub_request(:get, "https://storage.googleapis.com/storage/v1/b/test?fields=lifecycle").to_return(status: 200, body: JSON.dump({"lifecycle" => {"rule" => [{"action" => {"type" => "Delete"}, "condition" => {age: 0, matchesPrefix: ["test-ubid2"]}}]}}), headers: {"Content-Type" => "application/json"}) + stub_request(:patch, "https://storage.googleapis.com/storage/v1/b/test?fields=lifecycle") + .with(body: JSON.dump({"lifecycle" => {"rule" => [{"action" => {"type" => "Delete"}, "condition" => {age: 0, matchesPrefix: ["test-ubid"]}}]}})) + .to_return(status: 200, body: JSON.dump({}), headers: {"Content-Type" => "application/json"}) + api = described_class.new + expect(api).to receive(:list_objects).and_return([]).at_least(:once) expect { api.add_delete_lifecycle_rule("test", "test-ubid") }.not_to raise_error end end