From 3fed6cb583f1b67e1a29cee93d8448cce593acb3 Mon Sep 17 00:00:00 2001 From: olivier dubo Date: Thu, 9 Jul 2026 13:01:02 +0000 Subject: [PATCH] feat(cli): migrate cloud project list/get to API v2 Signed-off-by: olivier dubo --- internal/assets/api-schemas/cloud_v2.json | 99 ------------------- internal/cmd/cloud_project_test.go | 80 +++++++-------- internal/services/cloud/cloud_project.go | 6 +- .../cloud/templates/cloud_project.tmpl | 20 ++-- 4 files changed, 45 insertions(+), 160 deletions(-) diff --git a/internal/assets/api-schemas/cloud_v2.json b/internal/assets/api-schemas/cloud_v2.json index d03d70b5..21c93d63 100644 --- a/internal/assets/api-schemas/cloud_v2.json +++ b/internal/assets/api-schemas/cloud_v2.json @@ -1248,52 +1248,6 @@ } ], "x-expanded-response": "PublicCloudProjectProjectAsyncWithIAM" - }, - "post": { - "summary": "Create a new cloud project", - "security": [ - { - "oAuth2AuthCode": [] - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/publicCloud.project.ProjectCreation" - } - } - } - }, - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/publicCloud.project.ProjectAsync" - } - } - } - } - }, - "x-badges": [ - { - "color": "orange", - "label": "Internal use only" - } - ], - "x-iam-actions": [ - { - "name": "publicCloudProject:apiovh:create", - "required": true - }, - { - "name": "billingAccount:apiovh:subscription/publicCloudProject/create", - "required": true - } - ] } }, "/publicCloud/project/{projectId}": { @@ -1339,59 +1293,6 @@ "required": true } ] - }, - "put": { - "summary": "Update an existing cloud project", - "security": [ - { - "oAuth2AuthCode": [] - } - ], - "parameters": [ - { - "in": "path", - "name": "projectId", - "description": "Project ID", - "required": true, - "schema": { - "type": "string" - } - } - ], - "requestBody": { - "required": true, - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/publicCloud.project.ProjectCreation" - } - } - } - }, - "responses": { - "200": { - "description": "successful operation", - "content": { - "application/json": { - "schema": { - "$ref": "#/components/schemas/publicCloud.project.ProjectAsync" - } - } - } - } - }, - "x-badges": [ - { - "color": "orange", - "label": "Internal use only" - } - ], - "x-iam-actions": [ - { - "name": "publicCloudProject:apiovh:edit", - "required": true - } - ] } }, "/publicCloud/project/{projectId}/rancher": { diff --git a/internal/cmd/cloud_project_test.go b/internal/cmd/cloud_project_test.go index 41ed1ffb..281cce5f 100644 --- a/internal/cmd/cloud_project_test.go +++ b/internal/cmd/cloud_project_test.go @@ -12,50 +12,39 @@ import ( // TestCloudProjectListCmd tests the "cloud project list" command func (ms *MockSuite) TestCloudProjectListCmd(assert, require *td.T) { - httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v1/cloud/project", - httpmock.NewStringResponder(200, `["project-1", "project-2"]`).Once()) - - httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v1/cloud/project/project-1", - httpmock.NewStringResponder(200, `{ - "project_id": "project-1", - "projectName": "Test Project 1", - "status": "ok", - "description": "First test project" - }`).Once()) - - httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v1/cloud/project/project-2", - httpmock.NewStringResponder(200, `{ - "project_id": "project-2", - "projectName": "Test Project 2", - "status": "ok", - "description": "Second test project" - }`).Once()) + httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v2/publicCloud/project", + httpmock.NewStringResponder(200, `[ + { + "id": "project-1", + "resourceStatus": "READY", + "currentState": {"name": "Test Project 1", "mode": "standard"} + }, + { + "id": "project-2", + "resourceStatus": "READY", + "currentState": {"name": "Test Project 2", "mode": "discovery"} + } + ]`).Once()) out, err := cmd.Execute("cloud", "project", "list") require.CmpNoError(err) - assert.String(out, ` -┌────────────┬────────────────┬────────┬─────────────────────┐ -│ project_id │ projectName │ status │ description │ -├────────────┼────────────────┼────────┼─────────────────────┤ -│ project-1 │ Test Project 1 │ ok │ First test project │ -│ project-2 │ Test Project 2 │ ok │ Second test project │ -└────────────┴────────────────┴────────┴─────────────────────┘ -💡 Use option -o json or -o yaml to get the raw output with all information`[1:]) + assert.Cmp(out, td.Contains("project-1")) + assert.Cmp(out, td.Contains("Test Project 1")) + assert.Cmp(out, td.Contains("project-2")) + assert.Cmp(out, td.Contains("discovery")) } // TestCloudProjectListCmdAlias tests the "cloud project ls" command alias func (ms *MockSuite) TestCloudProjectListCmdAlias(assert, require *td.T) { - httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v1/cloud/project", - httpmock.NewStringResponder(200, `["project-1"]`).Once()) - - httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v1/cloud/project/project-1", - httpmock.NewStringResponder(200, `{ - "project_id": "project-1", - "projectName": "Test Project", - "status": "ok", - "description": "Test project" - }`).Once()) + httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v2/publicCloud/project", + httpmock.NewStringResponder(200, `[ + { + "id": "project-1", + "resourceStatus": "READY", + "currentState": {"name": "Test Project", "mode": "standard"} + } + ]`).Once()) out, err := cmd.Execute("cloud", "project", "ls") @@ -65,16 +54,15 @@ func (ms *MockSuite) TestCloudProjectListCmdAlias(assert, require *td.T) { // TestCloudProjectGetCmd tests the "cloud project get" command func (ms *MockSuite) TestCloudProjectGetCmd(assert, require *td.T) { - httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v1/cloud/project/project-123", + httpmock.RegisterResponder("GET", "https://eu.api.ovh.com/v2/publicCloud/project/project-123", httpmock.NewStringResponder(200, `{ - "project_id": "project-123", - "projectName": "My Cloud Project", - "status": "ok", - "description": "Production cloud project", - "access": "full", - "unleash": false, - "manualQuota": false, - "creationDate": "2023-01-15T10:30:00Z", + "id": "project-123", + "resourceStatus": "READY", + "createdAt": "2023-01-15T10:30:00Z", + "currentState": { + "name": "My Cloud Project", + "mode": "standard" + }, "iam": { "urn": "urn:v1:eu:resource:cloudProject:project-123" } @@ -85,7 +73,7 @@ func (ms *MockSuite) TestCloudProjectGetCmd(assert, require *td.T) { require.CmpNoError(err) assert.Cmp(out, td.Contains("project-123")) assert.Cmp(out, td.Contains("My Cloud Project")) - assert.Cmp(out, td.Contains("Production cloud project")) + assert.Cmp(out, td.Contains("standard")) } // TestCloudProjectEditCmd tests the "cloud project edit" command diff --git a/internal/services/cloud/cloud_project.go b/internal/services/cloud/cloud_project.go index 5bfc8781..951b4ce9 100644 --- a/internal/services/cloud/cloud_project.go +++ b/internal/services/cloud/cloud_project.go @@ -22,7 +22,7 @@ import ( ) var ( - cloudprojectColumnsToDisplay = []string{"project_id", "projectName", "status", "description"} + cloudprojectColumnsToDisplay = []string{"id", "currentState.name name", "currentState.mode mode", "resourceStatus"} // Cloud project set by CLI flags CloudProject string @@ -44,11 +44,11 @@ var ( ) func ListCloudProject(_ *cobra.Command, _ []string) { - common.ManageListRequest("/v1/cloud/project", "", cloudprojectColumnsToDisplay, flags.GenericFilters) + common.ManageListRequestNoExpand("/v2/publicCloud/project", cloudprojectColumnsToDisplay, flags.GenericFilters) } func GetCloudProject(_ *cobra.Command, args []string) { - common.ManageObjectRequest("/v1/cloud/project", args[0], cloudProjectTemplate) + common.ManageObjectRequest("/v2/publicCloud/project", args[0], cloudProjectTemplate) } func EditCloudProject(cmd *cobra.Command, args []string) { diff --git a/internal/services/cloud/templates/cloud_project.tmpl b/internal/services/cloud/templates/cloud_project.tmpl index 571ba7d7..648a4d62 100644 --- a/internal/services/cloud/templates/cloud_project.tmpl +++ b/internal/services/cloud/templates/cloud_project.tmpl @@ -1,19 +1,15 @@ 🚀 Cloud Project {{.ServiceName}} ======= -_{{index .Result "description"}}_ - ## General information -**Project name**: {{index .Result "projectName"}} -**Status**: {{index .Result "status"}} -**Access**: {{index .Result "access"}} -**Unleash**: {{index .Result "unleash"}} -**Manual quota**: {{index .Result "manualQuota"}} -**Creation date**: {{index .Result "creationDate"}} -{{if index .Result "expiration"}}**Expiration**: {{index .Result "expiration"}}{{end}} +**Name**: {{index .Result "currentState" "name"}} +**Mode**: {{index .Result "currentState" "mode"}} +**Status**: {{index .Result "resourceStatus"}} +**Creation date**: {{index .Result "createdAt"}} +**Update date**: {{index .Result "updatedAt"}} -## IAM information +{{if index .Result "iam"}}## IAM information **URN**: {{index .Result "iam" "urn"}} {{if index .Result "iam" "tags"}} @@ -22,6 +18,6 @@ _{{index .Result "description"}}_ | --- | --- | {{ range $key, $value := (index .Result "iam" "tags") }}| {{$key}} | {{$value}} | {{end}} -{{end}} +{{end}}{{end}} -💡 Use option -o json or -o yaml to get the raw output with all information \ No newline at end of file +💡 Use option -o json or -o yaml to get the raw output with all information