Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## [3.2.0] - 2025-10-23
### Added
- Multi-organization support.

## [3.1.5] - 2025-10-23
### Fixed
- prevent start/stop operations on serverless-standalone services.
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,9 @@ See the examples in `/docs` in this repository for usage examples.
```shell
go install
```

## Documentation

See the [documentation](docs/) for usage examples and detailed guides, including:

- [Multi-Organization Support](docs/guides/multi-organization-support.md) - Managing services across multiple SkySQL organizations
1 change: 1 addition & 0 deletions docs/resources/skysql_service.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ resource "skysql_service" "default" {
- `maxscale_size` (String) The size of the MaxScale nodes. Valid values are: sky-2x4, sky-2x8 etc
- `nodes` (Number) The number of nodes
- `nosql_enabled` (Boolean) Whether to enable NoSQL. Valid values are: true or false
- `org_id` (String) The organization ID to use for this service. When specified, all API requests will include the X-MDB-Org header to operate in this organization's context. This allows managing services across multiple organizations.
- `primary_host` (String) The primary host of the service
- `project_id` (String) The ID of the project to create the service in
- `replication_enabled` (Boolean) Whether to enable global replication. Valid values are: true or false. Works for xpand-direct topology only
Expand Down
35 changes: 22 additions & 13 deletions internal/provider/service_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type ServiceResourceModel struct {
FQDN types.String `tfsdk:"fqdn"`
AvailabilityZone types.String `tfsdk:"availability_zone"`
Tags types.Map `tfsdk:"tags"`
OrgID types.String `tfsdk:"org_id"`
}

// ServiceResourceNamedPortModel is an endpoint port
Expand Down Expand Up @@ -410,6 +411,13 @@ var serviceResourceSchemaV0 = schema.Schema{
&tagsNamePlanModifier{},
},
},
"org_id": schema.StringAttribute{
Optional: true,
Description: "The organization ID to use for this service. When specified, all API requests will include the X-MDB-Org header to operate in this organization's context. This allows managing services across multiple organizations.",
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
},
Blocks: map[string]schema.Block{
"timeouts": timeouts.Block(context.Background(), timeouts.Opts{
Expand Down Expand Up @@ -532,7 +540,7 @@ func (r *ServiceResource) Create(ctx context.Context, req resource.CreateRequest
}
}

service, err := r.client.CreateService(ctx, createServiceRequest)
service, err := r.client.CreateService(ctx, createServiceRequest, skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
resp.Diagnostics.AddError("Error creating service", err.Error())
return
Expand Down Expand Up @@ -595,7 +603,7 @@ func (r *ServiceResource) Create(ctx context.Context, req resource.CreateRequest
}

err = sdkresource.RetryContext(ctx, createTimeout, func() *sdkresource.RetryError {
service, err := r.client.GetServiceByID(ctx, service.ID)
service, err := r.client.GetServiceByID(ctx, service.ID, skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
return sdkresource.NonRetryableError(fmt.Errorf("error retrieving service details: %v", err))
}
Expand Down Expand Up @@ -688,7 +696,7 @@ func (r *ServiceResource) Read(ctx context.Context, req resource.ReadRequest, re
}

func (r *ServiceResource) readServiceState(ctx context.Context, data *ServiceResourceModel) error {
service, err := r.client.GetServiceByID(ctx, data.ID.ValueString())
service, err := r.client.GetServiceByID(ctx, data.ID.ValueString(), skysql.WithOrgID(data.OrgID.ValueString()))
if err != nil {
return err
}
Expand Down Expand Up @@ -863,7 +871,7 @@ func (r *ServiceResource) updateServiceStorage(ctx context.Context, plan *Servic
"throughput_to": plan.VolumeThroughput.ValueInt64(),
})

err := r.client.ModifyServiceStorage(ctx, state.ID.ValueString(), plan.Storage.ValueInt64(), plan.VolumeIOPS.ValueInt64(), plan.VolumeThroughput.ValueInt64())
err := r.client.ModifyServiceStorage(ctx, state.ID.ValueString(), plan.Storage.ValueInt64(), plan.VolumeIOPS.ValueInt64(), plan.VolumeThroughput.ValueInt64(), skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
resp.Diagnostics.AddError("Error updating a storage for the service",
fmt.Sprintf("Unable to update a storage size for the service, got error: %s", err))
Expand All @@ -888,7 +896,7 @@ func (r *ServiceResource) updateNumberOfNodeForService(ctx context.Context, plan
"to": plan.Nodes.ValueInt64(),
})

err := r.client.ModifyServiceNodeNumber(ctx, state.ID.ValueString(), plan.Nodes.ValueInt64())
err := r.client.ModifyServiceNodeNumber(ctx, state.ID.ValueString(), plan.Nodes.ValueInt64(), skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
resp.Diagnostics.AddError("Error updating a number of nodes for the service", fmt.Sprintf("Unable to update a nodes number for the service, got error: %s", err))
return
Expand All @@ -911,7 +919,7 @@ func (r *ServiceResource) updateServiceSize(ctx context.Context, plan *ServiceRe
"to": plan.Size.ValueString(),
})

err := r.client.ModifyServiceSize(ctx, state.ID.ValueString(), plan.Size.ValueString())
err := r.client.ModifyServiceSize(ctx, state.ID.ValueString(), plan.Size.ValueString(), skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
resp.Diagnostics.AddError("Error updating service size", fmt.Sprintf("Unable to update service size, got error: %s", err))
return
Expand Down Expand Up @@ -963,7 +971,8 @@ func (r *ServiceResource) updateServiceEndpoints(ctx context.Context, plan *Serv
state.ID.ValueString(),
plan.Mechanism.ValueString(),
planAllowedAccounts,
visibility)
visibility,
skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
resp.Diagnostics.AddError("Can not update service", err.Error())
return
Expand Down Expand Up @@ -1010,7 +1019,7 @@ func (r *ServiceResource) updateAllowList(ctx context.Context, plan *ServiceReso
})
}

allowListResp, err := r.client.UpdateServiceAllowListByID(ctx, plan.ID.ValueString(), allowListUpdateRequest)
allowListResp, err := r.client.UpdateServiceAllowListByID(ctx, plan.ID.ValueString(), allowListUpdateRequest, skysql.WithOrgID(plan.OrgID.ValueString()))
if err != nil {
if errors.Is(err, skysql.ErrorServiceNotFound) {
tflog.Warn(ctx, "SkySQL service not found, removing from state", map[string]interface{}{
Expand Down Expand Up @@ -1048,7 +1057,7 @@ func (r *ServiceResource) updateServicePowerState(ctx context.Context, plan *Ser
"id": state.ID.ValueString(),
"is_active": plan.IsActive.ValueBool(),
})
err := r.client.SetServicePowerState(ctx, state.ID.ValueString(), plan.IsActive.ValueBool())
err := r.client.SetServicePowerState(ctx, state.ID.ValueString(), plan.IsActive.ValueBool(), skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
resp.Diagnostics.AddError("Can not update service", err.Error())
return
Expand Down Expand Up @@ -1093,7 +1102,7 @@ func (r *ServiceResource) updateServiceTags(ctx context.Context, plan *ServiceRe
"id": state.ID.ValueString(),
})

err := r.client.UpdateServiceTags(ctx, state.ID.ValueString(), planTags)
err := r.client.UpdateServiceTags(ctx, state.ID.ValueString(), planTags, skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
if errors.Is(err, skysql.ErrorServiceNotFound) {
tflog.Warn(ctx, "SkySQL service not found, removing from state", map[string]interface{}{
Expand Down Expand Up @@ -1125,7 +1134,7 @@ var serviceUpdateWaitStates = []string{"ready", "failed", "stopped"}
func (r *ServiceResource) waitForUpdate(ctx context.Context, state *ServiceResourceModel, resp *resource.UpdateResponse) {
if state.WaitForUpdate.ValueBool() {
err := sdkresource.RetryContext(ctx, defaultUpdateTimeout, func() *sdkresource.RetryError {
service, err := r.client.GetServiceByID(ctx, state.ID.ValueString())
service, err := r.client.GetServiceByID(ctx, state.ID.ValueString(), skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
return sdkresource.NonRetryableError(fmt.Errorf("error retrieving service details: %v", err))
}
Expand Down Expand Up @@ -1162,7 +1171,7 @@ func (r *ServiceResource) Delete(ctx context.Context, req resource.DeleteRequest
return
}

err := r.client.DeleteServiceByID(ctx, state.ID.ValueString())
err := r.client.DeleteServiceByID(ctx, state.ID.ValueString(), skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
if errors.Is(err, skysql.ErrorServiceNotFound) {
tflog.Warn(ctx, "SkySQL service not found, removing from state", map[string]interface{}{
Expand All @@ -1183,7 +1192,7 @@ func (r *ServiceResource) Delete(ctx context.Context, req resource.DeleteRequest
}

err = sdkresource.RetryContext(ctx, deleteTimeout, func() *sdkresource.RetryError {
service, err := r.client.GetServiceByID(ctx, state.ID.ValueString())
service, err := r.client.GetServiceByID(ctx, state.ID.ValueString(), skysql.WithOrgID(state.OrgID.ValueString()))
if err != nil {
if errors.Is(err, skysql.ErrorServiceNotFound) {
return nil
Expand Down
Loading
Loading