From 737574c81250a8c9ed761ce4e900f5ee29dbae04 Mon Sep 17 00:00:00 2001 From: oct8l Date: Sat, 23 Nov 2024 16:33:06 -0600 Subject: [PATCH 01/28] Allow to recognize the predeployed annotation --- lib/krane/kubernetes_resource/deployment.rb | 8 ++++++++ lib/krane/kubernetes_resource/job.rb | 8 ++++++++ lib/krane/kubernetes_resource/service.rb | 8 ++++++++ 3 files changed, 24 insertions(+) diff --git a/lib/krane/kubernetes_resource/deployment.rb b/lib/krane/kubernetes_resource/deployment.rb index 7c4f81d7a..21ad2269f 100644 --- a/lib/krane/kubernetes_resource/deployment.rb +++ b/lib/krane/kubernetes_resource/deployment.rb @@ -111,6 +111,14 @@ def validate_definition(*, **) @validation_errors.empty? end + def predeployed? + krane_annotation_value("predeployed") == "true" + end + + def kind + @definition["kind"] + end + private def current_generation diff --git a/lib/krane/kubernetes_resource/job.rb b/lib/krane/kubernetes_resource/job.rb index af66c01de..9f8aecf4c 100644 --- a/lib/krane/kubernetes_resource/job.rb +++ b/lib/krane/kubernetes_resource/job.rb @@ -37,6 +37,14 @@ def failure_message end end + def predeployed? + krane_annotation_value("predeployed") == "true" + end + + def kind + @definition["kind"] + end + private def failed_status_condition diff --git a/lib/krane/kubernetes_resource/service.rb b/lib/krane/kubernetes_resource/service.rb index 64909fd51..e2130cf1c 100644 --- a/lib/krane/kubernetes_resource/service.rb +++ b/lib/krane/kubernetes_resource/service.rb @@ -44,6 +44,14 @@ def timeout_message "Please confirm the spec.selector is correct and the targeted workload is healthy." end + def predeployed? + krane_annotation_value("predeployed") == "true" + end + + def kind + @definition["kind"] + end + private def fetch_related_workloads(cache) From 4cc4e62371c705fc7f6e020d503c1276c5543e83 Mon Sep 17 00:00:00 2001 From: oct8l Date: Sat, 23 Nov 2024 16:33:40 -0600 Subject: [PATCH 02/28] Allow the mock resource to be designated as predeployed --- test/helpers/mock_resource.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/helpers/mock_resource.rb b/test/helpers/mock_resource.rb index da53e0fb4..5f9b65257 100644 --- a/test/helpers/mock_resource.rb +++ b/test/helpers/mock_resource.rb @@ -25,6 +25,10 @@ def group "core" end + def predeployed? + false + end + def pretty_timeout_type end From a07509793d2bace48e82ff5d5f8a2ad58bf052c3 Mon Sep 17 00:00:00 2001 From: oct8l Date: Sat, 23 Nov 2024 16:34:16 -0600 Subject: [PATCH 03/28] Fix logic in deciding if something should be predeployed --- lib/krane/resource_deployer.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/krane/resource_deployer.rb b/lib/krane/resource_deployer.rb index 3c79ea6ba..245453eff 100644 --- a/lib/krane/resource_deployer.rb +++ b/lib/krane/resource_deployer.rb @@ -49,7 +49,8 @@ def predeploy_priority_resources(resource_list, predeploy_sequence) predeploy_sequence.each do |resource_type, attributes| matching_resources = resource_list.select do |r| r.type == resource_type && - (!attributes[:group] || r.group == attributes[:group]) + (!attributes[:group] || r.group == attributes[:group]) && + r.predeployed? end StatsD.client.gauge('priority_resources.count', matching_resources.size, tags: statsd_tags) From 8746eb1a8c3a82f663c5212e79905dd2da1ca6e4 Mon Sep 17 00:00:00 2001 From: oct8l Date: Sat, 23 Nov 2024 16:38:20 -0600 Subject: [PATCH 04/28] Add functionality in the discovery to respect the predeployed annotation --- lib/krane/cluster_resource_discovery.rb | 51 +++++++++++++++++++++++++ lib/krane/kubernetes_resource.rb | 5 +++ 2 files changed, 56 insertions(+) diff --git a/lib/krane/cluster_resource_discovery.rb b/lib/krane/cluster_resource_discovery.rb index 44f968906..fd98699f8 100644 --- a/lib/krane/cluster_resource_discovery.rb +++ b/lib/krane/cluster_resource_discovery.rb @@ -18,6 +18,27 @@ def crds end end + def services + @services ||= fetch_services.map do |svc| + Service.new(namespace: namespace, context: context, logger: logger, + definition: svc, statsd_tags: @namespace_tags) + end + end + + def deployments + @deployments ||= fetch_deployments.map do |deployment| + Deployment.new(namespace: namespace, context: context, logger: logger, + definition: deployment, statsd_tags: @namespace_tags) + end + end + + def jobs + @jobs ||= fetch_jobs.map do |job| + Job.new(namespace: namespace, context: context, logger: logger, + definition: job, statsd_tags: @namespace_tags) + end + end + def prunable_resources(namespaced:) black_list = %w(Namespace Node ControllerRevision Event) fetch_resources(namespaced: namespaced).map do |resource| @@ -98,6 +119,36 @@ def fetch_crds end end + def fetch_services + raw_json, err, st = kubectl.run("get", "Service", output: "json", attempts: 5, + use_namespace: false) + if st.success? + MultiJson.load(raw_json)["items"] + else + raise FatalKubeAPIError, "Error retrieving Service: #{err}" + end + end + + def fetch_deployments + raw_json, err, st = kubectl.run("get", "Deployment", output: "json", attempts: 5, + use_namespace: false) + if st.success? + MultiJson.load(raw_json)["items"] + else + raise FatalKubeAPIError, "Error retrieving Deployment: #{err}" + end + end + + def fetch_jobs + raw_json, err, st = kubectl.run("get", "Job", output: "json", attempts: 5, + use_namespace: false) + if st.success? + MultiJson.load(raw_json)["items"] + else + raise FatalKubeAPIError, "Error retrieving Job: #{err}" + end + end + def kubectl @kubectl ||= Kubectl.new(task_config: @task_config, log_failure_by_default: true) end diff --git a/lib/krane/kubernetes_resource.rb b/lib/krane/kubernetes_resource.rb index 2636ae9b0..5bb88cea2 100644 --- a/lib/krane/kubernetes_resource.rb +++ b/lib/krane/kubernetes_resource.rb @@ -381,6 +381,11 @@ def use_generated_name(instance_data) @file = create_definition_tempfile end + def predeployed? + predeployed = krane_annotation_value("predeployed") + predeployed.nil? || predeployed == "false" + end + class Event EVENT_SEPARATOR = "ENDEVENT--BEGINEVENT" FIELD_SEPARATOR = "ENDFIELD--BEGINFIELD" From f4e03857b1fab708ee55308dbec392fcc624b609 Mon Sep 17 00:00:00 2001 From: oct8l Date: Sat, 23 Nov 2024 16:38:44 -0600 Subject: [PATCH 05/28] Add Deployments, Services and Jobs to be deployed after CRs --- lib/krane/deploy_task.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/krane/deploy_task.rb b/lib/krane/deploy_task.rb index 4973b48ac..0c57799a2 100644 --- a/lib/krane/deploy_task.rb +++ b/lib/krane/deploy_task.rb @@ -70,7 +70,10 @@ def predeploy_sequence ).map { |r| [r, default_group] } after_crs = %w( + Deployment + Service Pod + Job ).map { |r| [r, default_group] } crs = cluster_resource_discoverer.crds.select(&:predeployed?).map { |cr| [cr.kind, { group: cr.group }] } From 9c539c9ed5a2762c9de2659331fc59e9f1048e09 Mon Sep 17 00:00:00 2001 From: oct8l Date: Sat, 23 Nov 2024 16:39:02 -0600 Subject: [PATCH 06/28] Fix a couple tests to be up to speed with the new functionality --- test/unit/krane/resource_deployer_test.rb | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/test/unit/krane/resource_deployer_test.rb b/test/unit/krane/resource_deployer_test.rb index fe1f73dd3..7e5b8a10e 100644 --- a/test/unit/krane/resource_deployer_test.rb +++ b/test/unit/krane/resource_deployer_test.rb @@ -66,6 +66,14 @@ def test_deploy_verify_false_no_failure_error def test_predeploy_priority_resources_respects_pre_deploy_list kind = "MockResource" resource = build_mock_resource + priority_list = { kind => { group: "not-#{resource.group}" } } + resource_deployer(kubectl_times: 0).predeploy_priority_resources([resource], priority_list) + end + + def test_predeploy_priority_resources_respects_pre_deploy_list_and_predeployed_true_annotation + kind = "MockResource" + resource = build_mock_resource + resource.expects(:predeployed?).returns(true) watcher = mock("ResourceWatcher") watcher.expects(:run).returns(true) # ResourceDeployer only creates a ResourceWatcher if one or more resources @@ -76,6 +84,18 @@ def test_predeploy_priority_resources_respects_pre_deploy_list resource_deployer.predeploy_priority_resources([resource], priority_list) end + def test_predeploy_priority_resources_respects_pre_deploy_list_and_predeployed_false_annotation + kind = "MockResource" + resource = build_mock_resource + resource.expects(:predeployed?).returns(false) + # ResourceDeployer only creates a ResourceWatcher if one or more resources + # are deployed. See test_predeploy_priority_resources_respects_empty_pre_deploy_list + # for counter example + Krane::ResourceWatcher.expects(:new).never + priority_list = { kind => { group: "core" } } + resource_deployer(kubectl_times: 0).predeploy_priority_resources([resource], priority_list) + end + def test_predeploy_priority_resources_respects_empty_pre_deploy_list resource = build_mock_resource priority_list = [] @@ -98,4 +118,4 @@ def resource_deployer(kubectl_times: 1, prune_allowlist: []) def build_mock_resource(final_status: "success", hits_to_complete: 0, name: "web-pod") MockResource.new(name, hits_to_complete, final_status) end -end +end \ No newline at end of file From d70bd2d1d421b08ee9196c7cc3d1d40c0b440fb9 Mon Sep 17 00:00:00 2001 From: oct8l Date: Sat, 23 Nov 2024 16:45:35 -0600 Subject: [PATCH 07/28] Change test to work now that Services can be predeployed --- test/integration-serial/serial_deploy_test.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/integration-serial/serial_deploy_test.rb b/test/integration-serial/serial_deploy_test.rb index 39a5553b3..9b10a9538 100644 --- a/test/integration-serial/serial_deploy_test.rb +++ b/test/integration-serial/serial_deploy_test.rb @@ -344,8 +344,7 @@ def test_cr_success_with_service assert_deploy_success(deploy_fixtures("crd", subset: %w(web.yml))) - refute_logs_match(/Predeploying priority resources/) - assert_logs_match_all([/Phase 3: Deploying all resources/]) + assert_logs_match_all([/Phase 4: Deploying all resources/]) ensure build_kubectl.run("delete", "-f", filepath, use_namespace: false, log_failure: false) end From ca2035255387ee9d0152ae62acfa8dc8c139ea56 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 25 Nov 2024 10:28:23 -0600 Subject: [PATCH 08/28] Add information to the README about resources that can be marked as 'predeployed' --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 635bef6ca..9419eda57 100644 --- a/README.md +++ b/README.md @@ -166,11 +166,11 @@ before the deployment is considered successful. - Percent (e.g. 90%): The deploy is successful when the number of new pods that are ready is equal to `spec.replicas` * Percent. - _Compatibility_: StatefulSet - `full`: The deployment is successful when all pods are ready. -- `krane.shopify.io/predeployed`: Causes a Custom Resource to be deployed in the pre-deploy phase. - - _Compatibility_: Custom Resource Definition +- `krane.shopify.io/predeployed`: Causes a Custom Resource, Deployment, Service, or Job to be deployed in the pre-deploy phase. + - _Compatibility_: Custom Resource Definition, Deployment, Service, Job - _Default_: `true` - - `true`: The custom resource will be deployed in the pre-deploy phase. - - All other values: The custom resource will be deployed in the main deployment phase. + - `true`: The custom resource, deployment, service, or job will be deployed in the pre-deploy phase. + - All other values: The custom resource, deployment, service, or job will be deployed in the main deployment phase. - `krane.shopify.io/deploy-method-override`: Cause a resource to be deployed by the specified `kubectl` command, instead of the default `apply`. - _Compatibility_: Cannot be used for `PodDisruptionBudget`, since it always uses `create/replace-force` - _Accepted values_: `create`, `replace`, and `replace-force` From 5b45f3bdf91be1739b10f715f1cfc73edcb5cf23 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Tue, 26 Nov 2024 16:05:38 -0600 Subject: [PATCH 09/28] Also allow Ingresses to respect the 'predeployed' annotation --- README.md | 8 ++++---- lib/krane/cluster_resource_discovery.rb | 17 +++++++++++++++++ lib/krane/deploy_task.rb | 1 + lib/krane/kubernetes_resource/ingress.rb | 8 ++++++++ 4 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 9419eda57..88322a343 100644 --- a/README.md +++ b/README.md @@ -166,11 +166,11 @@ before the deployment is considered successful. - Percent (e.g. 90%): The deploy is successful when the number of new pods that are ready is equal to `spec.replicas` * Percent. - _Compatibility_: StatefulSet - `full`: The deployment is successful when all pods are ready. -- `krane.shopify.io/predeployed`: Causes a Custom Resource, Deployment, Service, or Job to be deployed in the pre-deploy phase. - - _Compatibility_: Custom Resource Definition, Deployment, Service, Job +- `krane.shopify.io/predeployed`: Causes a Custom Resource, Deployment, Service, Job, or Ingress to be deployed in the pre-deploy phase. + - _Compatibility_: Custom Resource Definition, Deployment, Service, Job, Ingress - _Default_: `true` - - `true`: The custom resource, deployment, service, or job will be deployed in the pre-deploy phase. - - All other values: The custom resource, deployment, service, or job will be deployed in the main deployment phase. + - `true`: The custom resource, deployment, service, job, or ingress will be deployed in the pre-deploy phase. + - All other values: The custom resource, deployment, service, job, or ingress will be deployed in the main deployment phase. - `krane.shopify.io/deploy-method-override`: Cause a resource to be deployed by the specified `kubectl` command, instead of the default `apply`. - _Compatibility_: Cannot be used for `PodDisruptionBudget`, since it always uses `create/replace-force` - _Accepted values_: `create`, `replace`, and `replace-force` diff --git a/lib/krane/cluster_resource_discovery.rb b/lib/krane/cluster_resource_discovery.rb index fd98699f8..7b8b99b17 100644 --- a/lib/krane/cluster_resource_discovery.rb +++ b/lib/krane/cluster_resource_discovery.rb @@ -39,6 +39,13 @@ def jobs end end + def ingresses + @ingresses ||= fetch_ingresses.map do |ingress| + Ingress.new(namespace: namespace, context: context, logger: logger, + definition: ingress, statsd_tags: @namespace_tags) + end + end + def prunable_resources(namespaced:) black_list = %w(Namespace Node ControllerRevision Event) fetch_resources(namespaced: namespaced).map do |resource| @@ -149,6 +156,16 @@ def fetch_jobs end end + def fetch_ingresses + raw_json, err, st = kubectl.run("get", "Ingress", output: "json", attempts: 5, + use_namespace: false) + if st.success? + MultiJson.load(raw_json)["items"] + else + raise FatalKubeAPIError, "Error retrieving Ingress: #{err}" + end + end + def kubectl @kubectl ||= Kubectl.new(task_config: @task_config, log_failure_by_default: true) end diff --git a/lib/krane/deploy_task.rb b/lib/krane/deploy_task.rb index 0c57799a2..36b928f86 100644 --- a/lib/krane/deploy_task.rb +++ b/lib/krane/deploy_task.rb @@ -72,6 +72,7 @@ def predeploy_sequence after_crs = %w( Deployment Service + Ingress Pod Job ).map { |r| [r, default_group] } diff --git a/lib/krane/kubernetes_resource/ingress.rb b/lib/krane/kubernetes_resource/ingress.rb index e34f4231c..8d8befbda 100644 --- a/lib/krane/kubernetes_resource/ingress.rb +++ b/lib/krane/kubernetes_resource/ingress.rb @@ -14,5 +14,13 @@ def deploy_succeeded? def deploy_failed? false end + + def predeployed? + krane_annotation_value("predeployed") == "true" + end + + def kind + @definition["kind"] + end end end From 52a608dd221cb4fad25a4eb1d7ca83bed8200750 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Fri, 29 Nov 2024 13:11:18 -0600 Subject: [PATCH 10/28] Remove duplicate 'kind' definition --- lib/krane/kubernetes_resource/deployment.rb | 4 ---- lib/krane/kubernetes_resource/ingress.rb | 3 --- lib/krane/kubernetes_resource/job.rb | 4 ---- lib/krane/kubernetes_resource/service.rb | 4 ---- 4 files changed, 15 deletions(-) diff --git a/lib/krane/kubernetes_resource/deployment.rb b/lib/krane/kubernetes_resource/deployment.rb index 21ad2269f..95854fa8e 100644 --- a/lib/krane/kubernetes_resource/deployment.rb +++ b/lib/krane/kubernetes_resource/deployment.rb @@ -115,10 +115,6 @@ def predeployed? krane_annotation_value("predeployed") == "true" end - def kind - @definition["kind"] - end - private def current_generation diff --git a/lib/krane/kubernetes_resource/ingress.rb b/lib/krane/kubernetes_resource/ingress.rb index 8d8befbda..7c947c96e 100644 --- a/lib/krane/kubernetes_resource/ingress.rb +++ b/lib/krane/kubernetes_resource/ingress.rb @@ -19,8 +19,5 @@ def predeployed? krane_annotation_value("predeployed") == "true" end - def kind - @definition["kind"] - end end end diff --git a/lib/krane/kubernetes_resource/job.rb b/lib/krane/kubernetes_resource/job.rb index 9f8aecf4c..b491bc2aa 100644 --- a/lib/krane/kubernetes_resource/job.rb +++ b/lib/krane/kubernetes_resource/job.rb @@ -41,10 +41,6 @@ def predeployed? krane_annotation_value("predeployed") == "true" end - def kind - @definition["kind"] - end - private def failed_status_condition diff --git a/lib/krane/kubernetes_resource/service.rb b/lib/krane/kubernetes_resource/service.rb index e2130cf1c..484629dcd 100644 --- a/lib/krane/kubernetes_resource/service.rb +++ b/lib/krane/kubernetes_resource/service.rb @@ -48,10 +48,6 @@ def predeployed? krane_annotation_value("predeployed") == "true" end - def kind - @definition["kind"] - end - private def fetch_related_workloads(cache) From c598e1eb2896512c19642e6f22ea82407b44d389 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 11:23:29 -0600 Subject: [PATCH 11/28] Refactor predeploy logic and enhance resource handling - Updated `predeploy_sequence` to specify resource groups for better clarity. - Modified `predeployed?` method logic to allow for default behavior based on resource type. - Introduced `default_to_predeployed?` method in multiple resource classes to standardize predeployment behavior. - Removed redundant `predeployed?` methods from `Deployment`, `Job`, and `Service` classes. - Added debug logging in integration tests for better traceability of resource groups during deployment. --- lib/krane/deploy_task.rb | 37 ++++++----- lib/krane/kubernetes_resource.rb | 6 +- lib/krane/kubernetes_resource/config_map.rb | 4 ++ .../kubernetes_resource/custom_resource.rb | 5 ++ .../custom_resource_definition.rb | 4 ++ lib/krane/kubernetes_resource/deployment.rb | 4 -- lib/krane/kubernetes_resource/job.rb | 4 -- .../kubernetes_resource/network_policy.rb | 4 ++ .../persistent_volume_claim.rb | 4 ++ lib/krane/kubernetes_resource/pod.rb | 4 ++ .../kubernetes_resource/resource_quota.rb | 4 ++ lib/krane/kubernetes_resource/role.rb | 4 ++ lib/krane/kubernetes_resource/role_binding.rb | 4 ++ lib/krane/kubernetes_resource/secret.rb | 4 ++ lib/krane/kubernetes_resource/service.rb | 4 -- .../kubernetes_resource/service_account.rb | 4 ++ lib/krane/resource_deployer.rb | 62 ++++++++++--------- 17 files changed, 100 insertions(+), 62 deletions(-) diff --git a/lib/krane/deploy_task.rb b/lib/krane/deploy_task.rb index 36b928f86..670141f55 100644 --- a/lib/krane/deploy_task.rb +++ b/lib/krane/deploy_task.rb @@ -57,25 +57,24 @@ class DeployTask ) def predeploy_sequence - default_group = { group: nil } - before_crs = %w( - ResourceQuota - NetworkPolicy - ConfigMap - PersistentVolumeClaim - ServiceAccount - Role - RoleBinding - Secret - ).map { |r| [r, default_group] } - - after_crs = %w( - Deployment - Service - Ingress - Pod - Job - ).map { |r| [r, default_group] } + before_crs = [ + ["ResourceQuota", { group: nil }], + ["NetworkPolicy", { group: "networking.k8s.io" }], + ["ConfigMap", { group: nil }], + ["PersistentVolumeClaim", { group: nil }], + ["ServiceAccount", { group: nil }], + ["Role", { group: "rbac.authorization.k8s.io" }], + ["RoleBinding", { group: "rbac.authorization.k8s.io" }], + ["Secret", { group: nil }] + ] + + after_crs = [ + ["Deployment", { group: "apps" }], + ["Service", { group: nil }], + ["Ingress", { group: "networking.k8s.io" }], + ["Pod", { group: nil }], + ["Job", { group: "batch" }] + ] crs = cluster_resource_discoverer.crds.select(&:predeployed?).map { |cr| [cr.kind, { group: cr.group }] } Hash[before_crs + crs + after_crs] diff --git a/lib/krane/kubernetes_resource.rb b/lib/krane/kubernetes_resource.rb index 5bb88cea2..f21bef60d 100644 --- a/lib/krane/kubernetes_resource.rb +++ b/lib/krane/kubernetes_resource.rb @@ -383,7 +383,11 @@ def use_generated_name(instance_data) def predeployed? predeployed = krane_annotation_value("predeployed") - predeployed.nil? || predeployed == "false" + default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") + end + + def default_to_predeployed? + false end class Event diff --git a/lib/krane/kubernetes_resource/config_map.rb b/lib/krane/kubernetes_resource/config_map.rb index 364656922..54076c00d 100644 --- a/lib/krane/kubernetes_resource/config_map.rb +++ b/lib/krane/kubernetes_resource/config_map.rb @@ -3,6 +3,10 @@ module Krane class ConfigMap < KubernetesResource TIMEOUT = 30.seconds + def default_to_predeployed? + true + end + def deploy_succeeded? exists? end diff --git a/lib/krane/kubernetes_resource/custom_resource.rb b/lib/krane/kubernetes_resource/custom_resource.rb index 453ce3f8d..fc021a079 100644 --- a/lib/krane/kubernetes_resource/custom_resource.rb +++ b/lib/krane/kubernetes_resource/custom_resource.rb @@ -74,6 +74,11 @@ def validate_definition(*, **) "Validation failed with: #{e}" end + def default_to_predeployed? + # Inherit predeployed behavior from the CRD + @crd&.default_to_predeployed? || false + end + private def kind diff --git a/lib/krane/kubernetes_resource/custom_resource_definition.rb b/lib/krane/kubernetes_resource/custom_resource_definition.rb index f07d84a27..4dad6264d 100644 --- a/lib/krane/kubernetes_resource/custom_resource_definition.rb +++ b/lib/krane/kubernetes_resource/custom_resource_definition.rb @@ -90,6 +90,10 @@ def validate_rollout_conditions @rollout_conditions_validated = true end + def default_to_predeployed? + true + end + private def names_accepted_condition diff --git a/lib/krane/kubernetes_resource/deployment.rb b/lib/krane/kubernetes_resource/deployment.rb index 95854fa8e..7c4f81d7a 100644 --- a/lib/krane/kubernetes_resource/deployment.rb +++ b/lib/krane/kubernetes_resource/deployment.rb @@ -111,10 +111,6 @@ def validate_definition(*, **) @validation_errors.empty? end - def predeployed? - krane_annotation_value("predeployed") == "true" - end - private def current_generation diff --git a/lib/krane/kubernetes_resource/job.rb b/lib/krane/kubernetes_resource/job.rb index b491bc2aa..af66c01de 100644 --- a/lib/krane/kubernetes_resource/job.rb +++ b/lib/krane/kubernetes_resource/job.rb @@ -37,10 +37,6 @@ def failure_message end end - def predeployed? - krane_annotation_value("predeployed") == "true" - end - private def failed_status_condition diff --git a/lib/krane/kubernetes_resource/network_policy.rb b/lib/krane/kubernetes_resource/network_policy.rb index 8cbf622fa..5978bf15d 100644 --- a/lib/krane/kubernetes_resource/network_policy.rb +++ b/lib/krane/kubernetes_resource/network_policy.rb @@ -3,6 +3,10 @@ module Krane class NetworkPolicy < KubernetesResource TIMEOUT = 30.seconds + def default_to_predeployed? + true + end + def status exists? ? "Created" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/persistent_volume_claim.rb b/lib/krane/kubernetes_resource/persistent_volume_claim.rb index 6a2824e15..1bbb1b2b8 100644 --- a/lib/krane/kubernetes_resource/persistent_volume_claim.rb +++ b/lib/krane/kubernetes_resource/persistent_volume_claim.rb @@ -3,6 +3,10 @@ module Krane class PersistentVolumeClaim < KubernetesResource TIMEOUT = 5.minutes + def default_to_predeployed? + true + end + def sync(cache) super @storage_classes = cache.get_all("StorageClass").map { |sc| StorageClass.new(sc) } diff --git a/lib/krane/kubernetes_resource/pod.rb b/lib/krane/kubernetes_resource/pod.rb index 64a93f80a..104371bb2 100644 --- a/lib/krane/kubernetes_resource/pod.rb +++ b/lib/krane/kubernetes_resource/pod.rb @@ -9,6 +9,10 @@ class Pod < KubernetesResource Preempting ) + def default_to_predeployed? + true + end + attr_accessor :stream_logs attr_reader :definition diff --git a/lib/krane/kubernetes_resource/resource_quota.rb b/lib/krane/kubernetes_resource/resource_quota.rb index 8a1032666..4a6f682aa 100644 --- a/lib/krane/kubernetes_resource/resource_quota.rb +++ b/lib/krane/kubernetes_resource/resource_quota.rb @@ -3,6 +3,10 @@ module Krane class ResourceQuota < KubernetesResource TIMEOUT = 30.seconds + def default_to_predeployed? + true + end + def status exists? ? "In effect" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/role.rb b/lib/krane/kubernetes_resource/role.rb index 58588739a..8c0cc8a74 100644 --- a/lib/krane/kubernetes_resource/role.rb +++ b/lib/krane/kubernetes_resource/role.rb @@ -3,6 +3,10 @@ module Krane class Role < KubernetesResource TIMEOUT = 30.seconds + def default_to_predeployed? + true + end + def status exists? ? "Created" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/role_binding.rb b/lib/krane/kubernetes_resource/role_binding.rb index 2ff4874ae..b62b3746c 100644 --- a/lib/krane/kubernetes_resource/role_binding.rb +++ b/lib/krane/kubernetes_resource/role_binding.rb @@ -3,6 +3,10 @@ module Krane class RoleBinding < KubernetesResource TIMEOUT = 30.seconds + def default_to_predeployed? + true + end + def status exists? ? "Created" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/secret.rb b/lib/krane/kubernetes_resource/secret.rb index d484b0d90..c2b473c5e 100644 --- a/lib/krane/kubernetes_resource/secret.rb +++ b/lib/krane/kubernetes_resource/secret.rb @@ -5,6 +5,10 @@ class Secret < KubernetesResource SENSITIVE_TEMPLATE_CONTENT = true SERVER_DRY_RUNNABLE = true + def default_to_predeployed? + true + end + def status exists? ? "Available" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/service.rb b/lib/krane/kubernetes_resource/service.rb index 484629dcd..64909fd51 100644 --- a/lib/krane/kubernetes_resource/service.rb +++ b/lib/krane/kubernetes_resource/service.rb @@ -44,10 +44,6 @@ def timeout_message "Please confirm the spec.selector is correct and the targeted workload is healthy." end - def predeployed? - krane_annotation_value("predeployed") == "true" - end - private def fetch_related_workloads(cache) diff --git a/lib/krane/kubernetes_resource/service_account.rb b/lib/krane/kubernetes_resource/service_account.rb index 4ef4cbcff..355ae7957 100644 --- a/lib/krane/kubernetes_resource/service_account.rb +++ b/lib/krane/kubernetes_resource/service_account.rb @@ -3,6 +3,10 @@ module Krane class ServiceAccount < KubernetesResource TIMEOUT = 30.seconds + def default_to_predeployed? + true + end + def status exists? ? "Created" : "Not Found" end diff --git a/lib/krane/resource_deployer.rb b/lib/krane/resource_deployer.rb index 245453eff..f44998db7 100644 --- a/lib/krane/resource_deployer.rb +++ b/lib/krane/resource_deployer.rb @@ -93,40 +93,42 @@ def deploy_resources(resources, prune: false, verify:, record_summary: true) logger.info("Deploying #{resource.id} (#{resource.pretty_timeout_type})") end - # Apply can be done in one large batch, the rest have to be done individually - applyables, individuals = resources.partition { |r| r.deploy_method == :apply } - # Prunable resources should also applied so that they can be pruned - pruneable_types = @prune_allowlist.map { |t| t.split("/").last } - applyables += individuals.select { |r| pruneable_types.include?(r.type) && !r.deploy_method_override } - - individuals.each do |individual_resource| - individual_resource.deploy_started_at = Time.now.utc - case individual_resource.deploy_method - when :create - err, status = create_resource(individual_resource) - when :replace - err, status = replace_or_create_resource(individual_resource) - when :replace_force - err, status = replace_or_create_resource(individual_resource, force: true) - else - # Fail Fast! This is a programmer mistake. - raise ArgumentError, "Unexpected deploy method! (#{individual_resource.deploy_method.inspect})" - end + StatsD.client.measure('sync.duration', tags: statsd_tags) do + # Apply can be done in one large batch, the rest have to be done individually + applyables, individuals = resources.partition { |r| r.deploy_method == :apply } + # Prunable resources should also applied so that they can be pruned + pruneable_types = @prune_allowlist.map { |t| t.split("/").last } + applyables += individuals.select { |r| pruneable_types.include?(r.type) && !r.deploy_method_override } + + individuals.each do |individual_resource| + individual_resource.deploy_started_at = Time.now.utc + case individual_resource.deploy_method + when :create + err, status = create_resource(individual_resource) + when :replace + err, status = replace_or_create_resource(individual_resource) + when :replace_force + err, status = replace_or_create_resource(individual_resource, force: true) + else + # Fail Fast! This is a programmer mistake. + raise ArgumentError, "Unexpected deploy method! (#{individual_resource.deploy_method.inspect})" + end - next if status.success? + next if status.success? - raise FatalDeploymentError, <<~MSG - Failed to replace or create resource: #{individual_resource.id} - #{individual_resource.sensitive_template_content? ? '' : err} - MSG - end + raise FatalDeploymentError, <<~MSG + Failed to replace or create resource: #{individual_resource.id} + #{individual_resource.sensitive_template_content? ? '' : err} + MSG + end - apply_all(applyables, prune) + apply_all(applyables, prune) - if verify - watcher = Krane::ResourceWatcher.new(resources: resources, deploy_started_at: deploy_started_at, - timeout: @global_timeout, task_config: @task_config, sha: @current_sha) - watcher.run(record_summary: record_summary) + if verify + watcher = Krane::ResourceWatcher.new(resources: resources, deploy_started_at: deploy_started_at, + timeout: @global_timeout, task_config: @task_config, sha: @current_sha) + watcher.run(record_summary: record_summary) + end end end From 873c0508b5db653aa39668328b533a285e46fda3 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 12:14:10 -0600 Subject: [PATCH 12/28] Explicitly set the priority resources to be predeployed --- lib/krane/deploy_task.rb | 37 ++++++++++--------- lib/krane/kubernetes_resource.rb | 6 ++- lib/krane/kubernetes_resource/config_map.rb | 2 +- .../kubernetes_resource/network_policy.rb | 2 +- .../persistent_volume_claim.rb | 2 +- .../kubernetes_resource/resource_quota.rb | 2 +- lib/krane/kubernetes_resource/role.rb | 2 +- lib/krane/kubernetes_resource/role_binding.rb | 2 +- lib/krane/kubernetes_resource/secret.rb | 2 +- .../kubernetes_resource/service_account.rb | 2 +- 10 files changed, 32 insertions(+), 27 deletions(-) diff --git a/lib/krane/deploy_task.rb b/lib/krane/deploy_task.rb index 670141f55..36b928f86 100644 --- a/lib/krane/deploy_task.rb +++ b/lib/krane/deploy_task.rb @@ -57,24 +57,25 @@ class DeployTask ) def predeploy_sequence - before_crs = [ - ["ResourceQuota", { group: nil }], - ["NetworkPolicy", { group: "networking.k8s.io" }], - ["ConfigMap", { group: nil }], - ["PersistentVolumeClaim", { group: nil }], - ["ServiceAccount", { group: nil }], - ["Role", { group: "rbac.authorization.k8s.io" }], - ["RoleBinding", { group: "rbac.authorization.k8s.io" }], - ["Secret", { group: nil }] - ] - - after_crs = [ - ["Deployment", { group: "apps" }], - ["Service", { group: nil }], - ["Ingress", { group: "networking.k8s.io" }], - ["Pod", { group: nil }], - ["Job", { group: "batch" }] - ] + default_group = { group: nil } + before_crs = %w( + ResourceQuota + NetworkPolicy + ConfigMap + PersistentVolumeClaim + ServiceAccount + Role + RoleBinding + Secret + ).map { |r| [r, default_group] } + + after_crs = %w( + Deployment + Service + Ingress + Pod + Job + ).map { |r| [r, default_group] } crs = cluster_resource_discoverer.crds.select(&:predeployed?).map { |cr| [cr.kind, { group: cr.group }] } Hash[before_crs + crs + after_crs] diff --git a/lib/krane/kubernetes_resource.rb b/lib/krane/kubernetes_resource.rb index f21bef60d..361c396b2 100644 --- a/lib/krane/kubernetes_resource.rb +++ b/lib/krane/kubernetes_resource.rb @@ -383,7 +383,11 @@ def use_generated_name(instance_data) def predeployed? predeployed = krane_annotation_value("predeployed") - default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") + if type == "Role" || type == "RoleBinding" + true + else + default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") + end end def default_to_predeployed? diff --git a/lib/krane/kubernetes_resource/config_map.rb b/lib/krane/kubernetes_resource/config_map.rb index 54076c00d..80f0f4782 100644 --- a/lib/krane/kubernetes_resource/config_map.rb +++ b/lib/krane/kubernetes_resource/config_map.rb @@ -3,7 +3,7 @@ module Krane class ConfigMap < KubernetesResource TIMEOUT = 30.seconds - def default_to_predeployed? + def predeployed? true end diff --git a/lib/krane/kubernetes_resource/network_policy.rb b/lib/krane/kubernetes_resource/network_policy.rb index 5978bf15d..89f8d54a6 100644 --- a/lib/krane/kubernetes_resource/network_policy.rb +++ b/lib/krane/kubernetes_resource/network_policy.rb @@ -3,7 +3,7 @@ module Krane class NetworkPolicy < KubernetesResource TIMEOUT = 30.seconds - def default_to_predeployed? + def predeployed? true end diff --git a/lib/krane/kubernetes_resource/persistent_volume_claim.rb b/lib/krane/kubernetes_resource/persistent_volume_claim.rb index 1bbb1b2b8..59f0bdd9d 100644 --- a/lib/krane/kubernetes_resource/persistent_volume_claim.rb +++ b/lib/krane/kubernetes_resource/persistent_volume_claim.rb @@ -3,7 +3,7 @@ module Krane class PersistentVolumeClaim < KubernetesResource TIMEOUT = 5.minutes - def default_to_predeployed? + def predeployed? true end diff --git a/lib/krane/kubernetes_resource/resource_quota.rb b/lib/krane/kubernetes_resource/resource_quota.rb index 4a6f682aa..8df17b3c6 100644 --- a/lib/krane/kubernetes_resource/resource_quota.rb +++ b/lib/krane/kubernetes_resource/resource_quota.rb @@ -3,7 +3,7 @@ module Krane class ResourceQuota < KubernetesResource TIMEOUT = 30.seconds - def default_to_predeployed? + def predeployed? true end diff --git a/lib/krane/kubernetes_resource/role.rb b/lib/krane/kubernetes_resource/role.rb index 8c0cc8a74..a30945d2b 100644 --- a/lib/krane/kubernetes_resource/role.rb +++ b/lib/krane/kubernetes_resource/role.rb @@ -3,7 +3,7 @@ module Krane class Role < KubernetesResource TIMEOUT = 30.seconds - def default_to_predeployed? + def predeployed? true end diff --git a/lib/krane/kubernetes_resource/role_binding.rb b/lib/krane/kubernetes_resource/role_binding.rb index b62b3746c..63c586c85 100644 --- a/lib/krane/kubernetes_resource/role_binding.rb +++ b/lib/krane/kubernetes_resource/role_binding.rb @@ -3,7 +3,7 @@ module Krane class RoleBinding < KubernetesResource TIMEOUT = 30.seconds - def default_to_predeployed? + def predeployed? true end diff --git a/lib/krane/kubernetes_resource/secret.rb b/lib/krane/kubernetes_resource/secret.rb index c2b473c5e..d47474dcf 100644 --- a/lib/krane/kubernetes_resource/secret.rb +++ b/lib/krane/kubernetes_resource/secret.rb @@ -5,7 +5,7 @@ class Secret < KubernetesResource SENSITIVE_TEMPLATE_CONTENT = true SERVER_DRY_RUNNABLE = true - def default_to_predeployed? + def predeployed? true end diff --git a/lib/krane/kubernetes_resource/service_account.rb b/lib/krane/kubernetes_resource/service_account.rb index 355ae7957..cde109eba 100644 --- a/lib/krane/kubernetes_resource/service_account.rb +++ b/lib/krane/kubernetes_resource/service_account.rb @@ -3,7 +3,7 @@ module Krane class ServiceAccount < KubernetesResource TIMEOUT = 30.seconds - def default_to_predeployed? + def predeployed? true end From 876715a07069c95504bdc3f9bfad5677368b58a0 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 13:00:35 -0600 Subject: [PATCH 13/28] Clean up (now) unused definitions --- lib/krane/cluster_resource_discovery.rb | 68 ------------------------- 1 file changed, 68 deletions(-) diff --git a/lib/krane/cluster_resource_discovery.rb b/lib/krane/cluster_resource_discovery.rb index 7b8b99b17..44f968906 100644 --- a/lib/krane/cluster_resource_discovery.rb +++ b/lib/krane/cluster_resource_discovery.rb @@ -18,34 +18,6 @@ def crds end end - def services - @services ||= fetch_services.map do |svc| - Service.new(namespace: namespace, context: context, logger: logger, - definition: svc, statsd_tags: @namespace_tags) - end - end - - def deployments - @deployments ||= fetch_deployments.map do |deployment| - Deployment.new(namespace: namespace, context: context, logger: logger, - definition: deployment, statsd_tags: @namespace_tags) - end - end - - def jobs - @jobs ||= fetch_jobs.map do |job| - Job.new(namespace: namespace, context: context, logger: logger, - definition: job, statsd_tags: @namespace_tags) - end - end - - def ingresses - @ingresses ||= fetch_ingresses.map do |ingress| - Ingress.new(namespace: namespace, context: context, logger: logger, - definition: ingress, statsd_tags: @namespace_tags) - end - end - def prunable_resources(namespaced:) black_list = %w(Namespace Node ControllerRevision Event) fetch_resources(namespaced: namespaced).map do |resource| @@ -126,46 +98,6 @@ def fetch_crds end end - def fetch_services - raw_json, err, st = kubectl.run("get", "Service", output: "json", attempts: 5, - use_namespace: false) - if st.success? - MultiJson.load(raw_json)["items"] - else - raise FatalKubeAPIError, "Error retrieving Service: #{err}" - end - end - - def fetch_deployments - raw_json, err, st = kubectl.run("get", "Deployment", output: "json", attempts: 5, - use_namespace: false) - if st.success? - MultiJson.load(raw_json)["items"] - else - raise FatalKubeAPIError, "Error retrieving Deployment: #{err}" - end - end - - def fetch_jobs - raw_json, err, st = kubectl.run("get", "Job", output: "json", attempts: 5, - use_namespace: false) - if st.success? - MultiJson.load(raw_json)["items"] - else - raise FatalKubeAPIError, "Error retrieving Job: #{err}" - end - end - - def fetch_ingresses - raw_json, err, st = kubectl.run("get", "Ingress", output: "json", attempts: 5, - use_namespace: false) - if st.success? - MultiJson.load(raw_json)["items"] - else - raise FatalKubeAPIError, "Error retrieving Ingress: #{err}" - end - end - def kubectl @kubectl ||= Kubectl.new(task_config: @task_config, log_failure_by_default: true) end From 2f88b9377be591fba5e711c19d495522f751349c Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 13:03:21 -0600 Subject: [PATCH 14/28] Add more resources to the 'after_crs' section of pre-deployment --- lib/krane/deploy_task.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/krane/deploy_task.rb b/lib/krane/deploy_task.rb index 36b928f86..9380bbfc5 100644 --- a/lib/krane/deploy_task.rb +++ b/lib/krane/deploy_task.rb @@ -75,6 +75,14 @@ def predeploy_sequence Ingress Pod Job + CronJob + DaemonSet + HorizontalPodAutoscaler + PodDisruptionBudget + PodSetBase + PodTemplate + ReplicaSet + StatefulSet ).map { |r| [r, default_group] } crs = cluster_resource_discoverer.crds.select(&:predeployed?).map { |cr| [cr.kind, { group: cr.group }] } From 3af0df3b3c210e2b63d5533ff1ff378e88f8a464 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 13:03:33 -0600 Subject: [PATCH 15/28] Documentation updates --- CONTRIBUTING.md | 1 + README.md | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 011d9e552..cc6808dd3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -91,6 +91,7 @@ This gem uses subclasses of `KubernetesResource` to implement custom success/fai 1. Create a file for your type in `lib/krane/kubernetes_resource/` 2. Create a new class that inherits from `KubernetesResource`. Minimally, it should implement the following methods: * `sync` -- Gather the data you'll need to determine `deploy_succeeded?` and `deploy_failed?`. The superclass's implementation fetches the corresponding resource, parses it and stores it in `@instance_data`. You can define your own implementation if you need something else. + * `predeployed?` -- Whether the resource should be [predeployed](README.md#phase-3-predeploying-priority-resources) by default. * `deploy_succeeded?` * `deploy_failed?` 3. Adjust the `TIMEOUT` constant to an appropriate value for this type. diff --git a/README.md b/README.md index 88322a343..1e6835e2b 100644 --- a/README.md +++ b/README.md @@ -166,11 +166,11 @@ before the deployment is considered successful. - Percent (e.g. 90%): The deploy is successful when the number of new pods that are ready is equal to `spec.replicas` * Percent. - _Compatibility_: StatefulSet - `full`: The deployment is successful when all pods are ready. -- `krane.shopify.io/predeployed`: Causes a Custom Resource, Deployment, Service, Job, or Ingress to be deployed in the pre-deploy phase. - - _Compatibility_: Custom Resource Definition, Deployment, Service, Job, Ingress - - _Default_: `true` - - `true`: The custom resource, deployment, service, job, or ingress will be deployed in the pre-deploy phase. - - All other values: The custom resource, deployment, service, job, or ingress will be deployed in the main deployment phase. +- `krane.shopify.io/predeployed`: Causes a Custom Resource or [other resources](https://github.com/powerhome/krane/tree/main/lib/krane/kubernetes_resource) to be deployed in the pre-deploy phase. + - _Compatibility_: CronJob, CustomResource, CustomResourceDefinition, DaemonSet, Deployment, HorizontalPodAutoscaler, Ingress, Job, Pod, PodDisruptionBudget, PodSetBase, PodTemplate, ReplicaSet, Service, StatefulSet + - _Default_: `false` + - `true`: The custom resource or other resource will be deployed in the pre-deploy phase. + - All other values: The custom resource or other resource will be deployed in the main deployment phase. - `krane.shopify.io/deploy-method-override`: Cause a resource to be deployed by the specified `kubectl` command, instead of the default `apply`. - _Compatibility_: Cannot be used for `PodDisruptionBudget`, since it always uses `create/replace-force` - _Accepted values_: `create`, `replace`, and `replace-force` From f873ef1d37f559efb8b1ff2f63618e29bcca4779 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 13:05:11 -0600 Subject: [PATCH 16/28] Remove a missed definition --- lib/krane/kubernetes_resource/ingress.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/krane/kubernetes_resource/ingress.rb b/lib/krane/kubernetes_resource/ingress.rb index 7c947c96e..798eca96e 100644 --- a/lib/krane/kubernetes_resource/ingress.rb +++ b/lib/krane/kubernetes_resource/ingress.rb @@ -14,10 +14,6 @@ def deploy_succeeded? def deploy_failed? false end - - def predeployed? - krane_annotation_value("predeployed") == "true" - end end end From 042fc44648e312407c7306106fc51a674b4add2c Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 14:19:36 -0600 Subject: [PATCH 17/28] Revert change to force Role and RoleBinding to be predeployed at the resource level --- lib/krane/kubernetes_resource.rb | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/lib/krane/kubernetes_resource.rb b/lib/krane/kubernetes_resource.rb index 361c396b2..f21bef60d 100644 --- a/lib/krane/kubernetes_resource.rb +++ b/lib/krane/kubernetes_resource.rb @@ -383,11 +383,7 @@ def use_generated_name(instance_data) def predeployed? predeployed = krane_annotation_value("predeployed") - if type == "Role" || type == "RoleBinding" - true - else - default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") - end + default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") end def default_to_predeployed? From bd5bc2568f6da3ca7a0c4d51847c20715acc88ed Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 14:33:11 -0600 Subject: [PATCH 18/28] Allow CR to be set to predeployed independent of CRDs --- lib/krane/kubernetes_resource/custom_resource.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/krane/kubernetes_resource/custom_resource.rb b/lib/krane/kubernetes_resource/custom_resource.rb index fc021a079..66417f4b8 100644 --- a/lib/krane/kubernetes_resource/custom_resource.rb +++ b/lib/krane/kubernetes_resource/custom_resource.rb @@ -75,8 +75,7 @@ def validate_definition(*, **) end def default_to_predeployed? - # Inherit predeployed behavior from the CRD - @crd&.default_to_predeployed? || false + true end private From 8bbbe90172dbae07a5c0ecd468da41980cc75e0c Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Mon, 2 Dec 2024 14:40:25 -0600 Subject: [PATCH 19/28] Fix line references that have changed --- 1.0-Upgrade.md | 2 +- CONTRIBUTING.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/1.0-Upgrade.md b/1.0-Upgrade.md index a6587e40e..2f8a636f4 100644 --- a/1.0-Upgrade.md +++ b/1.0-Upgrade.md @@ -7,7 +7,7 @@ * There are breaking changes in the public API (such as the renaming of the `KubernetesDeploy` namespace to `Krane`, and the change in default values for different arguments of the public interface). * StatsD metrics will now be generated with the `krane` prefix. * `krane deploy` now considers all namespaced resources eligible for pruning, including -custom resources. See [blacklist](https://github.com/Shopify/krane/blob/main/lib/krane/cluster_resource_discovery.rb#L20) for exceptions. +custom resources. See [blacklist](https://github.com/Shopify/krane/blob/main/lib/krane/cluster_resource_discovery.rb#L22) for exceptions. * `kubernetes-deploy` (now `krane deploy`) / `DeployTask` can no longer deploy global (non-namespaced) resources. A new command called `krane global-deploy` and a related class called `GlobalDeployTask` were added to replace that feature. * `krane deploy` will not render erb templates. Use `krane render | krane deploy --stdin` to reproduce this functionality. * If you attempt to install two gems that have conflicting executables, `gem install` will warn you but the most recently installed one will win. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cc6808dd3..64d76e7c7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -97,7 +97,7 @@ This gem uses subclasses of `KubernetesResource` to implement custom success/fai 3. Adjust the `TIMEOUT` constant to an appropriate value for this type. 4. Add the new class to list of resources in [`deploy_task.rb`](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L8) -5. Add the new resource to the [prune whitelist](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L81) +5. Add the new resource to the [prune whitelist](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L93) 6. Add a basic example of the type to the hello-cloud [fixture set](https://github.com/Shopify/krane/tree/main/test/fixtures/hello-cloud) and appropriate assertions to `#assert_all_up` in [`hello_cloud.rb`](https://github.com/Shopify/krane/blob/main/test/helpers/fixture_sets/hello_cloud.rb). This will get you coverage in several existing tests, such as `test_full_hello_cloud_set_deploy_succeeds`. 7. Add tests for any edge cases you foresee. From 9839b6d7d75c82f7b6cf71fc5f4dec4f2e0ebc5b Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Tue, 3 Dec 2024 09:15:17 -0600 Subject: [PATCH 20/28] Quick and dirty fix to get tests and deployments working properly This will be fixed later on, but getting a proposed version up in a PR to Shopify's Krane is the priority --- lib/krane/kubernetes_resource.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/krane/kubernetes_resource.rb b/lib/krane/kubernetes_resource.rb index f21bef60d..361c396b2 100644 --- a/lib/krane/kubernetes_resource.rb +++ b/lib/krane/kubernetes_resource.rb @@ -383,7 +383,11 @@ def use_generated_name(instance_data) def predeployed? predeployed = krane_annotation_value("predeployed") - default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") + if type == "Role" || type == "RoleBinding" + true + else + default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") + end end def default_to_predeployed? From bbc989f4125732e144c501425d35a6dc68277991 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Tue, 3 Dec 2024 10:08:27 -0600 Subject: [PATCH 21/28] Remove accidental newline --- lib/krane/kubernetes_resource/ingress.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/krane/kubernetes_resource/ingress.rb b/lib/krane/kubernetes_resource/ingress.rb index 798eca96e..e34f4231c 100644 --- a/lib/krane/kubernetes_resource/ingress.rb +++ b/lib/krane/kubernetes_resource/ingress.rb @@ -14,6 +14,5 @@ def deploy_succeeded? def deploy_failed? false end - end end From 6c4c6a9ca35d5f369a1e0b6c6f12c80bc404e10b Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Tue, 3 Dec 2024 13:05:36 -0600 Subject: [PATCH 22/28] Refactor predeployed logic for Kubernetes resources - Introduced a constant `PREDEPLOYED_RESOURCE_TYPES` to manage predeployed resource types. - Updated `predeployed?` method to utilize the new constant for Role and RoleBinding checks. - Removed redundant `predeployed?` methods from ConfigMap, NetworkPolicy, PersistentVolumeClaim, ResourceQuota, Role, RoleBinding, Secret, and ServiceAccount classes, simplifying their implementation. - Set `default_to_predeployed?` to always return true in CustomResourceDefinition. --- lib/krane/kubernetes_resource.rb | 13 ++++++++++++- lib/krane/kubernetes_resource/config_map.rb | 4 ---- .../custom_resource_definition.rb | 5 ++--- lib/krane/kubernetes_resource/network_policy.rb | 4 ---- .../kubernetes_resource/persistent_volume_claim.rb | 4 ---- lib/krane/kubernetes_resource/resource_quota.rb | 4 ---- lib/krane/kubernetes_resource/role.rb | 4 ---- lib/krane/kubernetes_resource/role_binding.rb | 4 ---- lib/krane/kubernetes_resource/secret.rb | 4 ---- lib/krane/kubernetes_resource/service_account.rb | 4 ---- 10 files changed, 14 insertions(+), 36 deletions(-) diff --git a/lib/krane/kubernetes_resource.rb b/lib/krane/kubernetes_resource.rb index 361c396b2..225384dc1 100644 --- a/lib/krane/kubernetes_resource.rb +++ b/lib/krane/kubernetes_resource.rb @@ -381,9 +381,20 @@ def use_generated_name(instance_data) @file = create_definition_tempfile end + PREDEPLOYED_RESOURCE_TYPES = [ + "ResourceQuota", + "NetworkPolicy", + "ConfigMap", + "PersistentVolumeClaim", + "ServiceAccount", + "Role", + "RoleBinding", + "Secret" + ] + def predeployed? predeployed = krane_annotation_value("predeployed") - if type == "Role" || type == "RoleBinding" + if PREDEPLOYED_RESOURCE_TYPES.include?(type) true else default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") diff --git a/lib/krane/kubernetes_resource/config_map.rb b/lib/krane/kubernetes_resource/config_map.rb index 80f0f4782..364656922 100644 --- a/lib/krane/kubernetes_resource/config_map.rb +++ b/lib/krane/kubernetes_resource/config_map.rb @@ -3,10 +3,6 @@ module Krane class ConfigMap < KubernetesResource TIMEOUT = 30.seconds - def predeployed? - true - end - def deploy_succeeded? exists? end diff --git a/lib/krane/kubernetes_resource/custom_resource_definition.rb b/lib/krane/kubernetes_resource/custom_resource_definition.rb index 4dad6264d..f3d9d4a1c 100644 --- a/lib/krane/kubernetes_resource/custom_resource_definition.rb +++ b/lib/krane/kubernetes_resource/custom_resource_definition.rb @@ -57,9 +57,8 @@ def prunable? prunable == "true" end - def predeployed? - predeployed = krane_annotation_value("predeployed") - predeployed.nil? || predeployed == "true" + def default_to_predeployed? + true end def rollout_conditions diff --git a/lib/krane/kubernetes_resource/network_policy.rb b/lib/krane/kubernetes_resource/network_policy.rb index 89f8d54a6..8cbf622fa 100644 --- a/lib/krane/kubernetes_resource/network_policy.rb +++ b/lib/krane/kubernetes_resource/network_policy.rb @@ -3,10 +3,6 @@ module Krane class NetworkPolicy < KubernetesResource TIMEOUT = 30.seconds - def predeployed? - true - end - def status exists? ? "Created" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/persistent_volume_claim.rb b/lib/krane/kubernetes_resource/persistent_volume_claim.rb index 59f0bdd9d..6a2824e15 100644 --- a/lib/krane/kubernetes_resource/persistent_volume_claim.rb +++ b/lib/krane/kubernetes_resource/persistent_volume_claim.rb @@ -3,10 +3,6 @@ module Krane class PersistentVolumeClaim < KubernetesResource TIMEOUT = 5.minutes - def predeployed? - true - end - def sync(cache) super @storage_classes = cache.get_all("StorageClass").map { |sc| StorageClass.new(sc) } diff --git a/lib/krane/kubernetes_resource/resource_quota.rb b/lib/krane/kubernetes_resource/resource_quota.rb index 8df17b3c6..8a1032666 100644 --- a/lib/krane/kubernetes_resource/resource_quota.rb +++ b/lib/krane/kubernetes_resource/resource_quota.rb @@ -3,10 +3,6 @@ module Krane class ResourceQuota < KubernetesResource TIMEOUT = 30.seconds - def predeployed? - true - end - def status exists? ? "In effect" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/role.rb b/lib/krane/kubernetes_resource/role.rb index a30945d2b..58588739a 100644 --- a/lib/krane/kubernetes_resource/role.rb +++ b/lib/krane/kubernetes_resource/role.rb @@ -3,10 +3,6 @@ module Krane class Role < KubernetesResource TIMEOUT = 30.seconds - def predeployed? - true - end - def status exists? ? "Created" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/role_binding.rb b/lib/krane/kubernetes_resource/role_binding.rb index 63c586c85..2ff4874ae 100644 --- a/lib/krane/kubernetes_resource/role_binding.rb +++ b/lib/krane/kubernetes_resource/role_binding.rb @@ -3,10 +3,6 @@ module Krane class RoleBinding < KubernetesResource TIMEOUT = 30.seconds - def predeployed? - true - end - def status exists? ? "Created" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/secret.rb b/lib/krane/kubernetes_resource/secret.rb index d47474dcf..d484b0d90 100644 --- a/lib/krane/kubernetes_resource/secret.rb +++ b/lib/krane/kubernetes_resource/secret.rb @@ -5,10 +5,6 @@ class Secret < KubernetesResource SENSITIVE_TEMPLATE_CONTENT = true SERVER_DRY_RUNNABLE = true - def predeployed? - true - end - def status exists? ? "Available" : "Not Found" end diff --git a/lib/krane/kubernetes_resource/service_account.rb b/lib/krane/kubernetes_resource/service_account.rb index cde109eba..4ef4cbcff 100644 --- a/lib/krane/kubernetes_resource/service_account.rb +++ b/lib/krane/kubernetes_resource/service_account.rb @@ -3,10 +3,6 @@ module Krane class ServiceAccount < KubernetesResource TIMEOUT = 30.seconds - def predeployed? - true - end - def status exists? ? "Created" : "Not Found" end From 5016db4ebc20509a727c7e8dc842869aa110ae24 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Tue, 3 Dec 2024 13:23:38 -0600 Subject: [PATCH 23/28] Move pod predeploy logic with the rest of the "required to predeploy" resources --- lib/krane/kubernetes_resource.rb | 3 ++- lib/krane/kubernetes_resource/pod.rb | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/lib/krane/kubernetes_resource.rb b/lib/krane/kubernetes_resource.rb index 225384dc1..d71b4b6ac 100644 --- a/lib/krane/kubernetes_resource.rb +++ b/lib/krane/kubernetes_resource.rb @@ -389,7 +389,8 @@ def use_generated_name(instance_data) "ServiceAccount", "Role", "RoleBinding", - "Secret" + "Secret", + "Pod" ] def predeployed? diff --git a/lib/krane/kubernetes_resource/pod.rb b/lib/krane/kubernetes_resource/pod.rb index 104371bb2..64a93f80a 100644 --- a/lib/krane/kubernetes_resource/pod.rb +++ b/lib/krane/kubernetes_resource/pod.rb @@ -9,10 +9,6 @@ class Pod < KubernetesResource Preempting ) - def default_to_predeployed? - true - end - attr_accessor :stream_logs attr_reader :definition From bfd40a79c3d9eedab3e098066eb55ffba465affd Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Tue, 3 Dec 2024 15:23:21 -0600 Subject: [PATCH 24/28] Remove the `default_to_predeployed` function from previous iterations on this PR Also add CRDs and CRs to their previous functionality, not using the `default_to_predeployed` functionality --- lib/krane/kubernetes_resource.rb | 10 +--------- lib/krane/kubernetes_resource/custom_resource.rb | 9 +++++---- .../kubernetes_resource/custom_resource_definition.rb | 9 +++------ 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/lib/krane/kubernetes_resource.rb b/lib/krane/kubernetes_resource.rb index d71b4b6ac..eea0dfdca 100644 --- a/lib/krane/kubernetes_resource.rb +++ b/lib/krane/kubernetes_resource.rb @@ -395,15 +395,7 @@ def use_generated_name(instance_data) def predeployed? predeployed = krane_annotation_value("predeployed") - if PREDEPLOYED_RESOURCE_TYPES.include?(type) - true - else - default_to_predeployed? ? (predeployed != "false") : (predeployed == "true") - end - end - - def default_to_predeployed? - false + PREDEPLOYED_RESOURCE_TYPES.include?(type) || predeployed == "true" end class Event diff --git a/lib/krane/kubernetes_resource/custom_resource.rb b/lib/krane/kubernetes_resource/custom_resource.rb index 66417f4b8..e5372aadb 100644 --- a/lib/krane/kubernetes_resource/custom_resource.rb +++ b/lib/krane/kubernetes_resource/custom_resource.rb @@ -62,6 +62,11 @@ def type kind end + def predeployed? + predeployed = krane_annotation_value("predeployed") + predeployed.nil? || predeployed == "true" + end + def validate_definition(*, **) super @@ -74,10 +79,6 @@ def validate_definition(*, **) "Validation failed with: #{e}" end - def default_to_predeployed? - true - end - private def kind diff --git a/lib/krane/kubernetes_resource/custom_resource_definition.rb b/lib/krane/kubernetes_resource/custom_resource_definition.rb index f3d9d4a1c..f07d84a27 100644 --- a/lib/krane/kubernetes_resource/custom_resource_definition.rb +++ b/lib/krane/kubernetes_resource/custom_resource_definition.rb @@ -57,8 +57,9 @@ def prunable? prunable == "true" end - def default_to_predeployed? - true + def predeployed? + predeployed = krane_annotation_value("predeployed") + predeployed.nil? || predeployed == "true" end def rollout_conditions @@ -89,10 +90,6 @@ def validate_rollout_conditions @rollout_conditions_validated = true end - def default_to_predeployed? - true - end - private def names_accepted_condition From c81d176a5cdf5f213f92045c5e27cf527f859621 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Tue, 3 Dec 2024 16:56:09 -0600 Subject: [PATCH 25/28] Add a test case to make sure a 'deployment' kind with the predeployed annotation is correctly deployed in phase 3 --- test/integration-serial/serial_deploy_test.rb | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/integration-serial/serial_deploy_test.rb b/test/integration-serial/serial_deploy_test.rb index 9b10a9538..2c822bf02 100644 --- a/test/integration-serial/serial_deploy_test.rb +++ b/test/integration-serial/serial_deploy_test.rb @@ -525,6 +525,26 @@ def test_resource_discovery_stops_deploys_when_fetch_crds_kubectl_errs ], in_order: true) end + def test_deployment_with_predeploy_annotation_is_predeployed + # Deploy the fixtures with a modified deployment that has the predeploy annotation + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "web.yml.erb"], render_erb: true) do |fixtures| + deployment = fixtures["web.yml.erb"]["Deployment"].first + deployment["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true" + } + end + + assert_deploy_success(result) + + # Verify the deployment was predeployed before other resources by checking log order + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: Deployment/web}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, Deployment\/web, Ingress\/web, Service\/web/, + ], in_order: true) + end + private def rollout_conditions_annotation_key From f342f21cff9c54e5a237e9d63fb09fd140649891 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Wed, 4 Dec 2024 10:37:01 -0600 Subject: [PATCH 26/28] Add a new documentation step when adding a new Kubernetes resource --- CONTRIBUTING.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 64d76e7c7..e8b50acb6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -96,10 +96,11 @@ This gem uses subclasses of `KubernetesResource` to implement custom success/fai * `deploy_failed?` 3. Adjust the `TIMEOUT` constant to an appropriate value for this type. 4. Add the new class to list of resources in - [`deploy_task.rb`](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L8) -5. Add the new resource to the [prune whitelist](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L93) -6. Add a basic example of the type to the hello-cloud [fixture set](https://github.com/Shopify/krane/tree/main/test/fixtures/hello-cloud) and appropriate assertions to `#assert_all_up` in [`hello_cloud.rb`](https://github.com/Shopify/krane/blob/main/test/helpers/fixture_sets/hello_cloud.rb). This will get you coverage in several existing tests, such as `test_full_hello_cloud_set_deploy_succeeds`. -7. Add tests for any edge cases you foresee. + [`deploy_task.rb`](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L12) +5. Add the new resource to the "after_crs" array in [`deploy_task.rb`](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L72) +6. Add the new resource to the [prune whitelist](https://github.com/Shopify/krane/blob/main/lib/krane/deploy_task.rb#L93) +7. Add a basic example of the type to the hello-cloud [fixture set](https://github.com/Shopify/krane/tree/main/test/fixtures/hello-cloud) and appropriate assertions to `#assert_all_up` in [`hello_cloud.rb`](https://github.com/Shopify/krane/blob/main/test/helpers/fixture_sets/hello_cloud.rb). This will get you coverage in several existing tests, such as `test_full_hello_cloud_set_deploy_succeeds`. +8. Add tests for any edge cases you foresee. ### Contributor License Agreement From f8e4c2604c13b9837effa4c743cff6f1ef00bd16 Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Wed, 4 Dec 2024 10:45:18 -0600 Subject: [PATCH 27/28] Add new tests for testing all types of resources: Multiple test cases in `serial_deploy_test.rb` to verify that various Kubernetes resources (Service, Ingress, Job, DaemonSet, PodDisruptionBudget, PodTemplate, ReplicaSet, StatefulSet) with the `krane.shopify.io/predeployed` annotation are correctly predeployed and logged in the expected phases. --- test/integration-serial/serial_deploy_test.rb | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/test/integration-serial/serial_deploy_test.rb b/test/integration-serial/serial_deploy_test.rb index 2c822bf02..e2438d117 100644 --- a/test/integration-serial/serial_deploy_test.rb +++ b/test/integration-serial/serial_deploy_test.rb @@ -545,6 +545,143 @@ def test_deployment_with_predeploy_annotation_is_predeployed ], in_order: true) end + def test_service_with_predeploy_annotation_is_predeployed + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "web.yml.erb"], render_erb: true) do |fixtures| + service = fixtures["web.yml.erb"]["Service"].first + service["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true", + "krane.shopify.io/skip-endpoint-validation" => "true" + } + end + + assert_deploy_success(result) + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: Service/web}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, Deployment\/web, Ingress\/web, Service\/web/, + ], in_order: true) + end + + def test_ingress_with_predeploy_annotation_is_predeployed + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "web.yml.erb"], render_erb: true) do |fixtures| + ingress = fixtures["web.yml.erb"]["Ingress"].first + ingress["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true" + } + end + + assert_deploy_success(result) + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: Ingress/web}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, Deployment\/web, Ingress\/web, Service\/web/, + ], in_order: true) + end + + def test_job_with_predeploy_annotation_is_predeployed + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "job.yml"]) do |fixtures| + job = fixtures["job.yml"]["Job"].first + job["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true" + } + end + + assert_deploy_success(result) + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: Job/hello-job}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, Job\/hello-job/, + ], in_order: true) + end + + def test_daemonset_with_predeploy_annotation_is_predeployed + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "daemon_set.yml"]) do |fixtures| + daemon_set = fixtures["daemon_set.yml"]["DaemonSet"].first + daemon_set["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true" + } + end + + assert_deploy_success(result) + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: DaemonSet/ds-app}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, DaemonSet\/ds-app/, + ], in_order: true) + end + + def test_pod_disruption_budget_with_predeploy_annotation_is_predeployed + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "disruption-budgets.yml"]) do |fixtures| + pdb = fixtures["disruption-budgets.yml"]["PodDisruptionBudget"].first + pdb["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true" + } + end + + assert_deploy_success(result) + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: PodDisruptionBudget/test}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, PodDisruptionBudget\/test/, + ], in_order: true) + end + + def test_pod_template_with_predeploy_annotation_is_predeployed + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "template-runner.yml"]) do |fixtures| + template = fixtures["template-runner.yml"]["PodTemplate"].first + template["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true" + } + end + + assert_deploy_success(result) + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: PodTemplate/hello-cloud-template-runner}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, PodTemplate\/hello-cloud-template-runner/, + ], in_order: true) + end + + def test_replica_set_with_predeploy_annotation_is_predeployed + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "bare_replica_set.yml"]) do |fixtures| + rs = fixtures["bare_replica_set.yml"]["ReplicaSet"].first + rs["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true" + } + end + + assert_deploy_success(result) + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: ReplicaSet/bare-replica-set}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, ReplicaSet\/bare-replica-set/, + ], in_order: true) + end + + def test_stateful_set_with_predeploy_annotation_is_predeployed + result = deploy_fixtures("hello-cloud", subset: ["configmap-data.yml", "stateful_set.yml"]) do |fixtures| + stateful_set = fixtures["stateful_set.yml"]["StatefulSet"].first + stateful_set["metadata"]["annotations"] = { + "krane.shopify.io/predeployed" => "true" + } + end + + assert_deploy_success(result) + assert_logs_match_all([ + "Phase 3: Predeploying priority resources", + %r{Successfully deployed in \d+.\ds: StatefulSet/stateful-busybox}, + "Phase 4: Deploying all resources", + /Successfully deployed in \d+.\ds: ConfigMap\/hello-cloud-configmap-data, Service\/stateful-busybox, StatefulSet\/stateful-busybox/, + ], in_order: true) + end + private def rollout_conditions_annotation_key From d85f7de439610c4153761b3ab73f5e40a9ab126d Mon Sep 17 00:00:00 2001 From: Colton Gerke Date: Wed, 4 Dec 2024 11:39:49 -0600 Subject: [PATCH 28/28] Documentation updates Remove a pedantic documentation change that increases the number of changes in this fork for little benefit Fix link that points to the Power fork instead of Krane fork --- 1.0-Upgrade.md | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/1.0-Upgrade.md b/1.0-Upgrade.md index 2f8a636f4..a6587e40e 100644 --- a/1.0-Upgrade.md +++ b/1.0-Upgrade.md @@ -7,7 +7,7 @@ * There are breaking changes in the public API (such as the renaming of the `KubernetesDeploy` namespace to `Krane`, and the change in default values for different arguments of the public interface). * StatsD metrics will now be generated with the `krane` prefix. * `krane deploy` now considers all namespaced resources eligible for pruning, including -custom resources. See [blacklist](https://github.com/Shopify/krane/blob/main/lib/krane/cluster_resource_discovery.rb#L22) for exceptions. +custom resources. See [blacklist](https://github.com/Shopify/krane/blob/main/lib/krane/cluster_resource_discovery.rb#L20) for exceptions. * `kubernetes-deploy` (now `krane deploy`) / `DeployTask` can no longer deploy global (non-namespaced) resources. A new command called `krane global-deploy` and a related class called `GlobalDeployTask` were added to replace that feature. * `krane deploy` will not render erb templates. Use `krane render | krane deploy --stdin` to reproduce this functionality. * If you attempt to install two gems that have conflicting executables, `gem install` will warn you but the most recently installed one will win. diff --git a/README.md b/README.md index 9813380f6..0a50e398e 100644 --- a/README.md +++ b/README.md @@ -167,7 +167,7 @@ before the deployment is considered successful. - Percent (e.g. 90%): The deploy is successful when the number of new pods that are ready is equal to `spec.replicas` * Percent. - _Compatibility_: StatefulSet - `full`: The deployment is successful when all pods are ready. -- `krane.shopify.io/predeployed`: Causes a Custom Resource or [other resources](https://github.com/powerhome/krane/tree/main/lib/krane/kubernetes_resource) to be deployed in the pre-deploy phase. +- `krane.shopify.io/predeployed`: Causes a Custom Resource or [other resources](https://github.com/shopify/krane/tree/main/lib/krane/kubernetes_resource) to be deployed in the pre-deploy phase. - _Compatibility_: CronJob, CustomResource, CustomResourceDefinition, DaemonSet, Deployment, HorizontalPodAutoscaler, Ingress, Job, Pod, PodDisruptionBudget, PodSetBase, PodTemplate, ReplicaSet, Service, StatefulSet - _Default_: `false` - `true`: The custom resource or other resource will be deployed in the pre-deploy phase.