diff --git a/lib/k8s/stack.rb b/lib/k8s/stack.rb index 5ae0483..6b8a25f 100644 --- a/lib/k8s/stack.rb +++ b/lib/k8s/stack.rb @@ -129,7 +129,10 @@ def keep_resource!(resource) # @param resource [K8s::Resource] # @return [Boolean] def keep_resource?(resource) - @keep_resources["#{resource.kind}:#{resource.metadata.name}@#{resource.metadata.namespace}"] == resource.metadata&.annotations&.dig(@checksum_annotation) + keep_annotation = @keep_resources["#{resource.kind}:#{resource.metadata.name}@#{resource.metadata.namespace}"] + return false unless keep_annotation + + keep_annotation == resource.metadata&.annotations&.dig(@checksum_annotation) end # Delete all stack resources that were not applied @@ -158,6 +161,8 @@ def prune(client, keep_resources:, skip_forbidden: true) if resource_label != name # apiserver did not respect labelSelector + elsif resource.metadata&.ownerReferences && !resource.metadata.ownerReferences.empty? + logger.info "Server resource #{resource.apiVersion}:#{resource.apiKind}/#{resource.metadata.name} in namespace #{resource.metadata.namespace} has ownerReferences and will be kept" elsif keep_resources && keep_resource?(resource) # resource is up-to-date else diff --git a/spec/k8s/stack_spec.rb b/spec/k8s/stack_spec.rb index 4aca143..29382c8 100644 --- a/spec/k8s/stack_spec.rb +++ b/spec/k8s/stack_spec.rb @@ -80,6 +80,32 @@ end end + context "which has extra resources with owner references" do + let(:resources) { + subject.resources + } + + before do + extra_resource = subject.prepare_resource(subject.resources.pop) + extra_resource.metadata.ownerReferences = [ + { + :apiVersion=>"certmanager.k8s.io/v1alpha1", + :kind=>"Certificate", + :name=>"kontena-lens" + } + ] + returned_resources = resources.dup + returned_resources = returned_resources.map { |r| subject.prepare_resource(r) unless r.nil? } + allow(client).to receive(:get_resources).with([K8s::Resource, K8s::Resource]).and_return(returned_resources) + allow(client).to receive(:list_resources).with(labelSelector: { 'k8s.kontena.io/stack' => 'whoami' }, skip_forbidden: true).and_return(returned_resources + [extra_resource]) + end + + it "keeps the resource" do + expect(client).not_to receive(:delete_resource) + subject.apply(client, prune: true) + end + end + context "which has extra resources on server" do let(:resources) { subject.resources