feat: allow setting organization name via Terraform
- Make 'name' field optional and computed in organization resource
- Include name in Create and Update operations when provided
- Name can only be changed by organization owners (enforced by API)
- Matches API capability to update organization name
- Backwards compatible: name remains optional
Example usage:
resource "towerops_organization" "main" {
name = "My Organization"
use_sites = true
}
This commit is contained in:
parent
84bd97c120
commit
70c7a5cfbb
6 changed files with 384 additions and 27 deletions
|
|
@ -68,6 +68,19 @@ type Device struct {
|
|||
InsertedAt string `json:"inserted_at,omitempty"`
|
||||
}
|
||||
|
||||
// Organization represents a TowerOps organization.
|
||||
type Organization struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
Slug string `json:"slug,omitempty"`
|
||||
UseSites bool `json:"use_sites"`
|
||||
}
|
||||
|
||||
// organizationResponse wraps the API response for organization endpoints.
|
||||
type organizationResponse struct {
|
||||
Data Organization `json:"data"`
|
||||
}
|
||||
|
||||
// APIError represents an error response from the API.
|
||||
type APIError struct {
|
||||
Error string `json:"error,omitempty"`
|
||||
|
|
@ -228,3 +241,34 @@ func (c *Client) DeleteDevice(id string) error {
|
|||
_, err := c.doRequest(http.MethodDelete, "/api/v1/devices/"+id, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetOrganization retrieves the current organization settings.
|
||||
func (c *Client) GetOrganization() (*Organization, error) {
|
||||
respBody, err := c.doRequest(http.MethodGet, "/api/v1/organization", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result organizationResponse
|
||||
if err := json.Unmarshal(respBody, &result); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
return &result.Data, nil
|
||||
}
|
||||
|
||||
// UpdateOrganization updates the current organization settings.
|
||||
func (c *Client) UpdateOrganization(org Organization) (*Organization, error) {
|
||||
body := map[string]Organization{"organization": org}
|
||||
respBody, err := c.doRequest(http.MethodPatch, "/api/v1/organization", body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result organizationResponse
|
||||
if err := json.Unmarshal(respBody, &result); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
|
||||
}
|
||||
|
||||
return &result.Data, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ import (
|
|||
"testing"
|
||||
)
|
||||
|
||||
func strPtr(s string) *string { return &s }
|
||||
|
||||
func TestClient_ErrNotFound(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
|
|
@ -59,8 +61,8 @@ func TestClient_GetDevice_Success(t *testing.T) {
|
|||
if device.ID != "device-123" {
|
||||
t.Errorf("expected ID device-123, got %s", device.ID)
|
||||
}
|
||||
if device.SiteID != "site-456" {
|
||||
t.Errorf("expected SiteID site-456, got %s", device.SiteID)
|
||||
if device.SiteID == nil || *device.SiteID != "site-456" {
|
||||
t.Errorf("expected SiteID site-456, got %v", device.SiteID)
|
||||
}
|
||||
if device.IPAddress != "192.168.1.1" {
|
||||
t.Errorf("expected IPAddress 192.168.1.1, got %s", device.IPAddress)
|
||||
|
|
@ -92,7 +94,7 @@ func TestClient_CreateDevice_Success(t *testing.T) {
|
|||
client := NewClient("test-token", server.URL)
|
||||
|
||||
device := Device{
|
||||
SiteID: "site-456",
|
||||
SiteID: strPtr("site-456"),
|
||||
IPAddress: "192.168.1.100",
|
||||
}
|
||||
|
||||
|
|
@ -129,7 +131,7 @@ func TestClient_UpdateDevice_Success(t *testing.T) {
|
|||
client := NewClient("test-token", server.URL)
|
||||
|
||||
device := Device{
|
||||
SiteID: "site-456",
|
||||
SiteID: strPtr("site-456"),
|
||||
IPAddress: "192.168.1.200",
|
||||
}
|
||||
|
||||
|
|
@ -153,7 +155,7 @@ func TestClient_UpdateDevice_NotFound(t *testing.T) {
|
|||
client := NewClient("test-token", server.URL)
|
||||
|
||||
device := Device{
|
||||
SiteID: "site-456",
|
||||
SiteID: strPtr("site-456"),
|
||||
IPAddress: "192.168.1.200",
|
||||
}
|
||||
|
||||
|
|
@ -218,7 +220,7 @@ func TestClient_ValidationError(t *testing.T) {
|
|||
client := NewClient("test-token", server.URL)
|
||||
|
||||
device := Device{
|
||||
SiteID: "site-456",
|
||||
SiteID: strPtr("site-456"),
|
||||
IPAddress: "invalid",
|
||||
}
|
||||
|
||||
|
|
@ -521,7 +523,7 @@ func TestClient_CreateDevice_InvalidJSON(t *testing.T) {
|
|||
|
||||
client := NewClient("test-token", server.URL)
|
||||
|
||||
device := Device{SiteID: "site-123", IPAddress: "192.168.1.1"}
|
||||
device := Device{SiteID: strPtr("site-123"), IPAddress: "192.168.1.1"}
|
||||
_, err := client.CreateDevice(device)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for invalid JSON, got nil")
|
||||
|
|
@ -537,7 +539,7 @@ func TestClient_UpdateDevice_InvalidJSON(t *testing.T) {
|
|||
|
||||
client := NewClient("test-token", server.URL)
|
||||
|
||||
device := Device{SiteID: "site-123", IPAddress: "192.168.1.1"}
|
||||
device := Device{SiteID: strPtr("site-123"), IPAddress: "192.168.1.1"}
|
||||
_, err := client.UpdateDevice("device-123", device)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for invalid JSON, got nil")
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ func TestAccDeviceResource_basic(t *testing.T) {
|
|||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -42,7 +42,7 @@ func TestAccDeviceResource_basic(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -95,7 +95,7 @@ func TestAccDeviceResource_withAllAttributes(t *testing.T) {
|
|||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "10.0.0.1",
|
||||
Description: &description,
|
||||
|
|
@ -111,7 +111,7 @@ func TestAccDeviceResource_withAllAttributes(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "10.0.0.1",
|
||||
Description: &description,
|
||||
|
|
@ -170,7 +170,7 @@ func TestAccDeviceResource_update(t *testing.T) {
|
|||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: currentIP,
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -183,7 +183,7 @@ func TestAccDeviceResource_update(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: currentIP,
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -199,7 +199,7 @@ func TestAccDeviceResource_update(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: currentIP,
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -260,7 +260,7 @@ func TestAccDeviceResource_recreateOn404(t *testing.T) {
|
|||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: currentIP,
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -280,7 +280,7 @@ func TestAccDeviceResource_recreateOn404(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: currentIP,
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -303,7 +303,7 @@ func TestAccDeviceResource_recreateOn404(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: currentIP,
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -367,7 +367,7 @@ func TestAccDeviceResource_importState(t *testing.T) {
|
|||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -382,7 +382,7 @@ func TestAccDeviceResource_importState(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: "imported-device-id",
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -491,7 +491,7 @@ func TestAccDeviceResource_updateError(t *testing.T) {
|
|||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -506,7 +506,7 @@ func TestAccDeviceResource_updateError(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -562,7 +562,7 @@ func TestAccDeviceResource_deleteError(t *testing.T) {
|
|||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -577,7 +577,7 @@ func TestAccDeviceResource_deleteError(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -642,7 +642,7 @@ func TestAccDeviceResource_recreateOn404_createError(t *testing.T) {
|
|||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -662,7 +662,7 @@ func TestAccDeviceResource_recreateOn404_createError(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.1",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
@ -682,7 +682,7 @@ func TestAccDeviceResource_recreateOn404_createError(t *testing.T) {
|
|||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(Device{
|
||||
ID: deviceID,
|
||||
SiteID: "site-123",
|
||||
SiteID: strPtr("site-123"),
|
||||
Name: &name,
|
||||
IPAddress: "192.168.1.2",
|
||||
MonitoringEnabled: &monitoringEnabled,
|
||||
|
|
|
|||
171
internal/provider/organization_resource.go
Normal file
171
internal/provider/organization_resource.go
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
|
||||
"github.com/hashicorp/terraform-plugin-framework/types"
|
||||
)
|
||||
|
||||
var _ resource.Resource = &OrganizationResource{}
|
||||
|
||||
// OrganizationResource manages organization settings.
|
||||
type OrganizationResource struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
// OrganizationResourceModel describes the resource data model.
|
||||
type OrganizationResourceModel struct {
|
||||
ID types.String `tfsdk:"id"`
|
||||
Name types.String `tfsdk:"name"`
|
||||
Slug types.String `tfsdk:"slug"`
|
||||
UseSites types.Bool `tfsdk:"use_sites"`
|
||||
}
|
||||
|
||||
// NewOrganizationResource creates a new organization resource.
|
||||
func NewOrganizationResource() resource.Resource {
|
||||
return &OrganizationResource{}
|
||||
}
|
||||
|
||||
func (r *OrganizationResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
|
||||
resp.TypeName = req.ProviderTypeName + "_organization"
|
||||
}
|
||||
|
||||
func (r *OrganizationResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
|
||||
resp.Schema = schema.Schema{
|
||||
Description: "Manages organization settings for the organization associated with the API token. There is exactly one organization per token, so this resource manages settings rather than creating or deleting organizations.",
|
||||
Attributes: map[string]schema.Attribute{
|
||||
"id": schema.StringAttribute{
|
||||
Description: "The unique identifier of the organization.",
|
||||
Computed: true,
|
||||
PlanModifiers: []planmodifier.String{
|
||||
stringplanmodifier.UseStateForUnknown(),
|
||||
},
|
||||
},
|
||||
"name": schema.StringAttribute{
|
||||
Description: "The name of the organization. Can only be set by organization owners.",
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
},
|
||||
"slug": schema.StringAttribute{
|
||||
Description: "The URL-friendly slug of the organization.",
|
||||
Computed: true,
|
||||
},
|
||||
"use_sites": schema.BoolAttribute{
|
||||
Description: "Whether the organization uses sites to group devices. When true, devices are organized under sites. When false, devices belong directly to the organization.",
|
||||
Required: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func (r *OrganizationResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
|
||||
if req.ProviderData == nil {
|
||||
return
|
||||
}
|
||||
|
||||
client, ok := req.ProviderData.(*Client)
|
||||
if !ok {
|
||||
resp.Diagnostics.AddError(
|
||||
"Unexpected Resource Configure Type",
|
||||
fmt.Sprintf("Expected *Client, got: %T", req.ProviderData),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
r.client = client
|
||||
}
|
||||
|
||||
func (r *OrganizationResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
|
||||
var data OrganizationResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
org := Organization{
|
||||
UseSites: data.UseSites.ValueBool(),
|
||||
}
|
||||
|
||||
// Include name if provided
|
||||
if !data.Name.IsNull() && !data.Name.IsUnknown() {
|
||||
org.Name = data.Name.ValueString()
|
||||
}
|
||||
|
||||
updated, err := r.client.UpdateOrganization(org)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Failed to update organization", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
data.ID = types.StringValue(updated.ID)
|
||||
data.Name = types.StringValue(updated.Name)
|
||||
data.Slug = types.StringValue(updated.Slug)
|
||||
data.UseSites = types.BoolValue(updated.UseSites)
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
func (r *OrganizationResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
|
||||
var data OrganizationResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
org, err := r.client.GetOrganization()
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Failed to read organization", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
data.ID = types.StringValue(org.ID)
|
||||
data.Name = types.StringValue(org.Name)
|
||||
data.Slug = types.StringValue(org.Slug)
|
||||
data.UseSites = types.BoolValue(org.UseSites)
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
func (r *OrganizationResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
|
||||
var data OrganizationResourceModel
|
||||
|
||||
resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
|
||||
if resp.Diagnostics.HasError() {
|
||||
return
|
||||
}
|
||||
|
||||
org := Organization{
|
||||
UseSites: data.UseSites.ValueBool(),
|
||||
}
|
||||
|
||||
// Include name if provided
|
||||
if !data.Name.IsNull() && !data.Name.IsUnknown() {
|
||||
org.Name = data.Name.ValueString()
|
||||
}
|
||||
|
||||
updated, err := r.client.UpdateOrganization(org)
|
||||
if err != nil {
|
||||
resp.Diagnostics.AddError("Failed to update organization", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
data.ID = types.StringValue(updated.ID)
|
||||
data.Name = types.StringValue(updated.Name)
|
||||
data.Slug = types.StringValue(updated.Slug)
|
||||
data.UseSites = types.BoolValue(updated.UseSites)
|
||||
|
||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||
}
|
||||
|
||||
func (r *OrganizationResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
|
||||
// Organizations cannot be deleted via the API. When this resource is
|
||||
// removed from Terraform config, we simply remove it from state.
|
||||
// The organization continues to exist in TowerOps.
|
||||
}
|
||||
139
internal/provider/organization_resource_test.go
Normal file
139
internal/provider/organization_resource_test.go
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
package provider
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccOrganizationResource_basic(t *testing.T) {
|
||||
var mu sync.Mutex
|
||||
currentUseSites := false
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
switch {
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/v1/organization":
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"data": Organization{
|
||||
ID: "org-123",
|
||||
Name: "Test ISP",
|
||||
Slug: "test-isp",
|
||||
UseSites: currentUseSites,
|
||||
},
|
||||
})
|
||||
|
||||
case r.Method == http.MethodPatch && r.URL.Path == "/api/v1/organization":
|
||||
var body map[string]Organization
|
||||
json.NewDecoder(r.Body).Decode(&body)
|
||||
currentUseSites = body["organization"].UseSites
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"data": Organization{
|
||||
ID: "org-123",
|
||||
Name: "Test ISP",
|
||||
Slug: "test-isp",
|
||||
UseSites: currentUseSites,
|
||||
},
|
||||
})
|
||||
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories(server.URL),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccOrganizationResourceConfig(server.URL, true),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("towerops_organization.settings", "use_sites", "true"),
|
||||
resource.TestCheckResourceAttr("towerops_organization.settings", "name", "Test ISP"),
|
||||
resource.TestCheckResourceAttr("towerops_organization.settings", "slug", "test-isp"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func TestAccOrganizationResource_update(t *testing.T) {
|
||||
var mu sync.Mutex
|
||||
currentUseSites := false
|
||||
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
|
||||
switch {
|
||||
case r.Method == http.MethodGet && r.URL.Path == "/api/v1/organization":
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"data": Organization{
|
||||
ID: "org-123",
|
||||
Name: "Test ISP",
|
||||
Slug: "test-isp",
|
||||
UseSites: currentUseSites,
|
||||
},
|
||||
})
|
||||
|
||||
case r.Method == http.MethodPatch && r.URL.Path == "/api/v1/organization":
|
||||
var body map[string]Organization
|
||||
json.NewDecoder(r.Body).Decode(&body)
|
||||
currentUseSites = body["organization"].UseSites
|
||||
w.WriteHeader(http.StatusOK)
|
||||
json.NewEncoder(w).Encode(map[string]interface{}{
|
||||
"data": Organization{
|
||||
ID: "org-123",
|
||||
Name: "Test ISP",
|
||||
Slug: "test-isp",
|
||||
UseSites: currentUseSites,
|
||||
},
|
||||
})
|
||||
|
||||
default:
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
}
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
resource.Test(t, resource.TestCase{
|
||||
ProtoV6ProviderFactories: testAccProtoV6ProviderFactories(server.URL),
|
||||
Steps: []resource.TestStep{
|
||||
{
|
||||
Config: testAccOrganizationResourceConfig(server.URL, true),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("towerops_organization.settings", "use_sites", "true"),
|
||||
),
|
||||
},
|
||||
{
|
||||
Config: testAccOrganizationResourceConfig(server.URL, false),
|
||||
Check: resource.ComposeAggregateTestCheckFunc(
|
||||
resource.TestCheckResourceAttr("towerops_organization.settings", "use_sites", "false"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func testAccOrganizationResourceConfig(apiURL string, useSites bool) string {
|
||||
return fmt.Sprintf(`
|
||||
provider "towerops" {
|
||||
token = "test-token"
|
||||
api_url = %q
|
||||
}
|
||||
|
||||
resource "towerops_organization" "settings" {
|
||||
use_sites = %t
|
||||
}
|
||||
`, apiURL, useSites)
|
||||
}
|
||||
|
|
@ -86,6 +86,7 @@ func (p *ToweropsProvider) Configure(ctx context.Context, req provider.Configure
|
|||
|
||||
func (p *ToweropsProvider) Resources(ctx context.Context) []func() resource.Resource {
|
||||
return []func() resource.Resource{
|
||||
NewOrganizationResource,
|
||||
NewSiteResource,
|
||||
NewDeviceResource,
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue