From f19694e1e352bbf391fc3aa197fc8b35708b6cee Mon Sep 17 00:00:00 2001 From: Taka Nishida Date: Mon, 16 Dec 2024 17:16:29 +0900 Subject: [PATCH 1/3] Allow configuring "auto_stop_setting" through Environments API "auto_stop_setting" is added recently in https://gitlab.com/gitlab-org/gitlab/-/merge_requests/173804. This MR allows configuring it through Environments API. Changelog: added --- .../clusters/clusters_controller.rb | 2 +- app/models/environment.rb | 6 ++++++ lib/api/entities/environment.rb | 1 + lib/api/environments.rb | 4 +++- .../api/schemas/public_api/v4/environment.json | 3 +++ spec/requests/api/environments_spec.rb | 18 ++++++++++++++++-- 6 files changed, 30 insertions(+), 4 deletions(-) diff --git a/app/controllers/clusters/clusters_controller.rb b/app/controllers/clusters/clusters_controller.rb index f7071c4d05df51..642f176363ace4 100644 --- a/app/controllers/clusters/clusters_controller.rb +++ b/app/controllers/clusters/clusters_controller.rb @@ -31,7 +31,7 @@ def index end end - # Overridding ActionController::Metal#status is NOT a good idea + # Overriding ActionController::Metal#status is NOT a good idea def cluster_status respond_to do |format| format.json do diff --git a/app/models/environment.rb b/app/models/environment.rb index 446d458fa0d6b9..15577419c4a857 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -49,6 +49,8 @@ class Environment < ApplicationRecord has_one :latest_opened_most_severe_alert, -> { open_order_by_severity }, class_name: 'AlertManagement::Alert', inverse_of: :environment + after_initialize :set_initial_auto_stop_setting + before_validation :generate_slug, if: ->(env) { env.slug.blank? } before_validation :ensure_environment_tier @@ -638,6 +640,10 @@ def guess_tier self.class.tiers[:other] end end + + def set_initial_auto_stop_setting + self.auto_stop_setting ||= :always + end end Environment.prepend_mod_with('Environment') diff --git a/lib/api/entities/environment.rb b/lib/api/entities/environment.rb index b87cf13782ded8..fd2137aae63e3b 100644 --- a/lib/api/entities/environment.rb +++ b/lib/api/entities/environment.rb @@ -14,6 +14,7 @@ class Environment < Entities::EnvironmentBasic expose :kubernetes_namespace, if: ->(_, _) { can_read_cluster_agent? } expose :flux_resource_path, if: ->(_, _) { can_read_cluster_agent? } expose :description, documentation: { type: 'string', example: 'description' } + expose :auto_stop_setting, documentation: { type: 'string', example: 'always' } private diff --git a/lib/api/environments.rb b/lib/api/environments.rb index db8ff7102ee23c..53785da4c1502b 100644 --- a/lib/api/environments.rb +++ b/lib/api/environments.rb @@ -71,6 +71,7 @@ class Environments < ::API::Base optional :kubernetes_namespace, type: String, desc: 'The Kubernetes namespace to associate with this environment' optional :flux_resource_path, type: String, desc: 'The Flux resource path to associate with this environment' optional :description, type: String, desc: 'The description of the environment' + optional :auto_stop_setting, type: String, values: Environment.auto_stop_settings.keys, desc: 'The auto stop setting for the environment. Allowed values are `always` and `with_action`' end route_setting :authentication, job_token_allowed: true post ':id/environments' do @@ -112,6 +113,7 @@ class Environments < ::API::Base optional :kubernetes_namespace, type: String, desc: 'The Kubernetes namespace to associate with this environment' optional :flux_resource_path, type: String, desc: 'The Flux resource path to associate with this environment' optional :description, type: String, desc: 'The description of the environment' + optional :auto_stop_setting, type: String, values: Environment.auto_stop_settings.keys, desc: 'The auto stop setting for the environment. Allowed values are `always` and `with_action`' end route_setting :authentication, job_token_allowed: true put ':id/environments/:environment_id' do @@ -119,7 +121,7 @@ class Environments < ::API::Base environment = user_project.environments.find(params[:environment_id]) - update_params = declared_params(include_missing: false).extract!(:external_url, :tier, :cluster_agent_id, :kubernetes_namespace, :flux_resource_path, :description) + update_params = declared_params(include_missing: false).extract!(:external_url, :tier, :cluster_agent_id, :kubernetes_namespace, :flux_resource_path, :description, :auto_stop_setting) if update_params[:cluster_agent_id] agent = ::Clusters::AgentsFinder.new(user_project, current_user).execute.find_by_id(params[:cluster_agent_id]) diff --git a/spec/fixtures/api/schemas/public_api/v4/environment.json b/spec/fixtures/api/schemas/public_api/v4/environment.json index 523083dbdb3a70..18f5457a68c108 100644 --- a/spec/fixtures/api/schemas/public_api/v4/environment.json +++ b/spec/fixtures/api/schemas/public_api/v4/environment.json @@ -79,6 +79,9 @@ }, "flux_resource_path": { "$ref": "../../types/nullable_string.json" + }, + "auto_stop_setting": { + "type": "string" } }, "additionalProperties": false diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb index 3f889050968640..2fdbb6ca52d802 100644 --- a/spec/requests/api/environments_spec.rb +++ b/spec/requests/api/environments_spec.rb @@ -26,6 +26,7 @@ expect(json_response.first['external_url']).to eq(environment.external_url) expect(json_response.first['project']).to match_schema('public_api/v4/project') expect(json_response.first).not_to have_key('last_deployment') + expect(json_response.first['auto_stop_setting']).to eq('always') end it 'returns 200 HTTP status when using JOB-TOKEN auth' do @@ -133,7 +134,7 @@ describe 'POST /projects/:id/environments' do context 'as a member' do it 'creates an environment with valid params' do - post api("/projects/#{project.id}/environments", user), params: { name: "mepmep", tier: 'staging', description: 'description' } + post api("/projects/#{project.id}/environments", user), params: { name: "mepmep", tier: 'staging', description: 'description', auto_stop_setting: "with_action" } expect(response).to have_gitlab_http_status(:created) expect(response).to match_response_schema('public_api/v4/environment') @@ -142,6 +143,7 @@ expect(json_response['slug']).to eq('mepmep') expect(json_response['tier']).to eq('staging') expect(json_response['external']).to be nil + expect(json_response['auto_stop_setting']).to eq('with_action') end context 'when associating a cluster agent' do @@ -351,6 +353,16 @@ expect(response).to have_gitlab_http_status(:ok) end + it 'returns 200 HTTP status when auto_stop_setting is changed' do + job = create(:ci_build, :running, project: project, user: user) + + put api("/projects/#{project.id}/environments/#{environment.id}"), + params: { auto_stop_setting: 'with_action', job_token: job.token } + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response['auto_stop_setting']).to eq('with_action') + end + context 'when associating a cluster agent' do let_it_be(:cluster_agent) { create(:cluster_agent, project: project) } let_it_be(:foreign_cluster_agent) { create(:cluster_agent) } @@ -591,7 +603,8 @@ environment.update!( cluster_agent: create(:cluster_agent, project: project), kubernetes_namespace: 'flux-system', - flux_resource_path: 'HelmRelease/flux-system' + flux_resource_path: 'HelmRelease/flux-system', + auto_stop_setting: 'with_action' ) get api("/projects/#{project.id}/environments/#{environment.id}", user) @@ -602,6 +615,7 @@ expect(json_response['cluster_agent']).to be_present expect(json_response['kubernetes_namespace']).to eq('flux-system') expect(json_response['flux_resource_path']).to eq('HelmRelease/flux-system') + expect(json_response['auto_stop_setting']).to eq('with_action') end end -- GitLab From 9537b51fbdb58b4fc2fb033b248e445d47761271 Mon Sep 17 00:00:00 2001 From: Taka Nishida Date: Tue, 17 Dec 2024 13:03:15 +0900 Subject: [PATCH 2/3] Doc: Add auto_stop_setting --- doc/api/environments.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/doc/api/environments.md b/doc/api/environments.md index 006e155ff22d1f..f20b5a156779f1 100644 --- a/doc/api/environments.md +++ b/doc/api/environments.md @@ -10,6 +10,7 @@ DETAILS: **Tier:** Free, Premium, Ultimate **Offering:** GitLab.com, Self-managed, GitLab Dedicated +> Parameter `auto_stop_setting` [added](https://gitlab.com/gitlab-org/gitlab/-/issues/428625) in GitLab 17.8. > Support for [GitLab CI/CD job token](../ci/jobs/ci_job_token.md) authentication [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/414549) in GitLab 16.2. ## List environments @@ -49,7 +50,8 @@ Example response: "logs_api_path": "/project/-/logs/k8s.json?environment_name=review%2Ffix-foo", "auto_stop_at": "2019-06-03T18:55:13.252Z", "kubernetes_namespace": "flux-system", - "flux_resource_path": "HelmRelease/flux-system" + "flux_resource_path": "HelmRelease/flux-system", + "auto_stop_setting": "always" } ] ``` @@ -184,7 +186,8 @@ Example of response "created_by_user_id": 42 }, "kubernetes_namespace": "flux-system", - "flux_resource_path": "HelmRelease/flux-system" + "flux_resource_path": "HelmRelease/flux-system", + "auto_stop_setting": "always" } ``` @@ -208,6 +211,7 @@ POST /projects/:id/environments | `cluster_agent_id` | integer | no | The cluster agent to associate with this environment. | | `kubernetes_namespace` | string | no | The Kubernetes namespace to associate with this environment. | | `flux_resource_path` | string | no | The Flux resource path to associate with this environment. This must be the full resource path. For example, `helm.toolkit.fluxcd.io/v2/namespaces/gitlab-agent/helmreleases/gitlab-agent`. | +| `auto_stop_setting` | string | no | The auto stop setting for the environment. Allowed values are `always` or `with_action`. | ```shell curl --data "name=deploy&external_url=https://deploy.gitlab.example.com" \ @@ -228,7 +232,8 @@ Example response: "created_at": "2019-05-25T18:55:13.252Z", "updated_at": "2019-05-27T18:55:13.252Z", "kubernetes_namespace": "flux-system", - "flux_resource_path": "HelmRelease/flux-system" + "flux_resource_path": "HelmRelease/flux-system", + "auto_stop_setting": "always" } ``` @@ -254,6 +259,7 @@ PUT /projects/:id/environments/:environments_id | `cluster_agent_id` | integer or null | no | The cluster agent to associate with this environment or `null` to remove it. | | `kubernetes_namespace` | string or null | no | The Kubernetes namespace to associate with this environment or `null` to remove it. | | `flux_resource_path` | string or null | no | The Flux resource path to associate with this environment or `null` to remove it. | +| `auto_stop_setting` | string or null | no | The auto stop setting for the environment. Allowed values are `always` or `with_action`. | ```shell curl --request PUT --data "external_url=https://staging.gitlab.example.com" \ @@ -274,7 +280,8 @@ Example response: "created_at": "2019-05-25T18:55:13.252Z", "updated_at": "2019-05-27T18:55:13.252Z", "kubernetes_namespace": "flux-system", - "flux_resource_path": "HelmRelease/flux-system" + "flux_resource_path": "HelmRelease/flux-system", + "auto_stop_setting": "always" } ``` @@ -370,7 +377,8 @@ Example response: "created_at": "2019-05-25T18:55:13.252Z", "updated_at": "2019-05-27T18:55:13.252Z", "kubernetes_namespace": "flux-system", - "flux_resource_path": "HelmRelease/flux-system" + "flux_resource_path": "HelmRelease/flux-system", + "auto_stop_setting": "always" } ``` -- GitLab From 916582ce194b930817a72882b632c2724aee782c Mon Sep 17 00:00:00 2001 From: Taka Nishida Date: Tue, 17 Dec 2024 16:14:16 +0900 Subject: [PATCH 3/3] Set default value for auto_stop_setting for API --- app/models/environment.rb | 6 ------ lib/api/environments.rb | 2 +- spec/requests/api/environments_spec.rb | 8 ++++---- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/models/environment.rb b/app/models/environment.rb index 15577419c4a857..446d458fa0d6b9 100644 --- a/app/models/environment.rb +++ b/app/models/environment.rb @@ -49,8 +49,6 @@ class Environment < ApplicationRecord has_one :latest_opened_most_severe_alert, -> { open_order_by_severity }, class_name: 'AlertManagement::Alert', inverse_of: :environment - after_initialize :set_initial_auto_stop_setting - before_validation :generate_slug, if: ->(env) { env.slug.blank? } before_validation :ensure_environment_tier @@ -640,10 +638,6 @@ def guess_tier self.class.tiers[:other] end end - - def set_initial_auto_stop_setting - self.auto_stop_setting ||= :always - end end Environment.prepend_mod_with('Environment') diff --git a/lib/api/environments.rb b/lib/api/environments.rb index 53785da4c1502b..aa1a16d2b82473 100644 --- a/lib/api/environments.rb +++ b/lib/api/environments.rb @@ -71,7 +71,7 @@ class Environments < ::API::Base optional :kubernetes_namespace, type: String, desc: 'The Kubernetes namespace to associate with this environment' optional :flux_resource_path, type: String, desc: 'The Flux resource path to associate with this environment' optional :description, type: String, desc: 'The description of the environment' - optional :auto_stop_setting, type: String, values: Environment.auto_stop_settings.keys, desc: 'The auto stop setting for the environment. Allowed values are `always` and `with_action`' + optional :auto_stop_setting, type: String, default: "with_action", values: Environment.auto_stop_settings.keys, desc: 'The auto stop setting for the environment. Allowed values are `always` and `with_action`' end route_setting :authentication, job_token_allowed: true post ':id/environments' do diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb index 2fdbb6ca52d802..078500b9d963c9 100644 --- a/spec/requests/api/environments_spec.rb +++ b/spec/requests/api/environments_spec.rb @@ -8,7 +8,7 @@ let_it_be(:non_member) { create(:user) } let_it_be(:reporter) { create(:user) } let_it_be(:project) { create(:project, :private, :repository, namespace: user.namespace, maintainers: user, developers: developer, reporters: reporter) } - let_it_be_with_reload(:environment) { create(:environment, project: project, description: 'description') } + let_it_be_with_reload(:environment) { create(:environment, :auto_stop_always, project: project, description: 'description') } describe 'GET /projects/:id/environments', :aggregate_failures do context 'as member of the project' do @@ -134,7 +134,7 @@ describe 'POST /projects/:id/environments' do context 'as a member' do it 'creates an environment with valid params' do - post api("/projects/#{project.id}/environments", user), params: { name: "mepmep", tier: 'staging', description: 'description', auto_stop_setting: "with_action" } + post api("/projects/#{project.id}/environments", user), params: { name: "mepmep", tier: 'staging', description: 'description' } expect(response).to have_gitlab_http_status(:created) expect(response).to match_response_schema('public_api/v4/environment') @@ -604,7 +604,7 @@ cluster_agent: create(:cluster_agent, project: project), kubernetes_namespace: 'flux-system', flux_resource_path: 'HelmRelease/flux-system', - auto_stop_setting: 'with_action' + auto_stop_setting: 'always' ) get api("/projects/#{project.id}/environments/#{environment.id}", user) @@ -615,7 +615,7 @@ expect(json_response['cluster_agent']).to be_present expect(json_response['kubernetes_namespace']).to eq('flux-system') expect(json_response['flux_resource_path']).to eq('HelmRelease/flux-system') - expect(json_response['auto_stop_setting']).to eq('with_action') + expect(json_response['auto_stop_setting']).to eq('always') end end -- GitLab