Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for new tenant variables endpoints with environment scoping #301

Open
wants to merge 14 commits into
base: main
Choose a base branch
from

Conversation

bec-callow-oct
Copy link
Contributor

@bec-callow-oct bec-callow-oct commented Feb 7, 2025

[SC-93476] [SC-101710]

New tenant variables endpoints have been added to Octopus Server to allow multi-environment scoping for Common and Project Tenant Variables. This PR adds support for the new endpoints, and for the feature toggles endpoint to allow verification of whether the endpoints are available:

  • /api/{SpaceId}/tenants/{TenantId}/commonvariables (GET/PUT/POST)
  • /api/{SpaceId}/tenants/{TenantId}/projectvariables (GET/PUT/POST)

Feature toggles can be queried by name - both of the above endpoints are under CommonVariableScopingFeatureToggle.

Copy link
Contributor

@tothegills tothegills left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed that getting feature toggles, tenant project variables and tenant common variables are all working as expected.

I'm struggling to use the update commands, have an example?

	var vars []variables.TenantCommonVariableCommand
	modify := variables.ModifyTenantCommonVariablesCommand{TenantID: tenantID, CommonVariables: vars}
	modified, err := tenants.UpdateCommonVariables(client, "Spaces-1", tenantID, &modify)
	if err != nil {
		_ = fmt.Errorf("error creating API client: %v", err)
		return
	}
	fmt.Println(modified)

SpaceID string `json:"SpaceId"`
}

type TenantProjectVariablesResource struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think our naming needs a bit of work. Resource has been superseded. TenantProjectVariable is a read type, whereas TenantProjectVariableCommand is the write type. Love to establish a convention so it's easy to understand what the types mean and when to use them without having to reason through where and how they are used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than TenantProjectVariablesResource, how about TenantProjectVariableResponse? This would help to make it a bit clearer what the object is intended to be used for. Within that, we currently have TenantProjectVariable, which could be renamed to something similar to TenantProjectVariableValueResponse or TenantProjectVariableDetailsResponse

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Names updated based on the team discussion

pkg/tenants/tenant_service.go Outdated Show resolved Hide resolved
@bec-callow-oct
Copy link
Contributor Author

bec-callow-oct commented Feb 10, 2025

Confirmed that getting feature toggles, tenant project variables and tenant common variables are all working as expected.

I'm struggling to use the update commands, have an example?

	var vars []variables.TenantCommonVariableCommand
	modify := variables.ModifyTenantCommonVariablesCommand{TenantID: tenantID, CommonVariables: vars}
	modified, err := tenants.UpdateCommonVariables(client, "Spaces-1", tenantID, &modify)
	if err != nil {
		_ = fmt.Errorf("error creating API client: %v", err)
		return
	}
	fmt.Println(modified)

Looks like I'd left some naming issues after a refactor. I've made a few changes and verified that update is now working. Just one tweak for the test code - it looks like var vars []variables.TenantCommonVariableCommand attempts to send null instead of an empty list, which fails required field validation on the server. Here's an updated version of the test code:

// Uncomment to test empty list of vars
// var vars []variables.TenantCommonVariableCommand

vars := []variables.TenantCommonVariableCommand{
		{
		        Id: "<Variable ID (optional)>"
			LibraryVariableSetId: "<LibraryVariableSet ID>",
			TemplateID:           "<Template ID>",
			Value: core.PropertyValue{
				IsSensitive: false,
				Value:       "New value from Go client",
			},
			Scope: variables.TenantVariableScope{
				EnvironmentIds: []string{
					"<Environment ID>",
				},
			},
		},
		}

		modify := variables.ModifyTenantCommonVariablesCommand{Variables: vars}
		modified, err := tenants.UpdateCommonVariables(client, "Spaces-1", tenant.ID, &modify)

		fmt.Println(modified)
		fmt.Println(err)

@tothegills
Copy link
Contributor

Ran into an issue because I used TenantProjectVariableCommand.ID instead of TenantProjectVariableCommand.Id. Why are there both?

Copy link
Contributor

@tothegills tothegills left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some naming to address, leaving Resource in the past.
The methods all work as expected.
I'm wondering about Id vs ID and the resource properties on the structs (resources.Resource), do we need those?

const tenantCommonVariableTemplate = "/api/{spaceId}/tenants/{id}/commonvariables"

// GetProjectVariables returns all tenant project variables. If an error occurs, it returns nil.
func GetProjectVariables(client newclient.Client, spaceID string, tenantID string) (*variables.TenantProjectVariablesResource, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

}

// GetCommonVariables returns all tenant common variables. If an error occurs, it returns nil.
func GetCommonVariables(client newclient.Client, spaceID string, tenantID string) (*variables.TenantCommonVariablesResource, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

}

// UpdateCommonVariables modifies tenant common variables based on the ones provided as input.
func UpdateCommonVariables(client newclient.Client, spaceID string, tenantID string, commonVariables *variables.ModifyTenantCommonVariablesCommand) (*variables.TenantCommonVariablesResource, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

}

// UpdateProjectVariables modifies tenant project variables based on the ones provided as input.
func UpdateProjectVariables(client newclient.Client, spaceID string, tenantID string, projectVariables *variables.ModifyTenantProjectVariablesCommand) (*variables.TenantProjectVariablesResource, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

@bec-callow-oct
Copy link
Contributor Author

Some naming to address, leaving Resource in the past. The methods all work as expected. I'm wondering about Id vs ID and the resource properties on the structs (resources.Resource), do we need those?

I've removed the extra IDs and updated the naming

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants