add address, latitude, longitude to site resource
Support geographic coordinates and street address in towerops_site. All three fields are optional; server validates lat/long ranges.
This commit is contained in:
parent
bbe1babdf7
commit
4960adaf37
4 changed files with 117 additions and 72 deletions
|
|
@ -31,8 +31,11 @@ provider "towerops" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "towerops_site" "example" {
|
resource "towerops_site" "example" {
|
||||||
name = "Main Office"
|
name = "Main Office"
|
||||||
location = "New York, NY"
|
location = "New York, NY"
|
||||||
|
address = "350 5th Ave, New York, NY 10118"
|
||||||
|
latitude = 40.7484
|
||||||
|
longitude = -73.9857
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "towerops_device" "router" {
|
resource "towerops_device" "router" {
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ Manages a TowerOps site. Sites represent physical locations that contain devices
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
|
### Basic
|
||||||
|
|
||||||
```terraform
|
```terraform
|
||||||
resource "towerops_site" "example" {
|
resource "towerops_site" "example" {
|
||||||
name = "Main Office"
|
name = "Main Office"
|
||||||
|
|
@ -18,6 +20,18 @@ resource "towerops_site" "example" {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### With Geographic Coordinates
|
||||||
|
|
||||||
|
```terraform
|
||||||
|
resource "towerops_site" "tower_site" {
|
||||||
|
name = "Verona Tower"
|
||||||
|
location = "Verona, TX"
|
||||||
|
address = "123 Main St, Verona, TX 75482"
|
||||||
|
latitude = 33.4356
|
||||||
|
longitude = -96.0028
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Schema
|
## Schema
|
||||||
|
|
||||||
### Required
|
### Required
|
||||||
|
|
@ -26,7 +40,10 @@ resource "towerops_site" "example" {
|
||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
- `location` (String) - The physical location or address of the site.
|
- `location` (String) - A short description of the physical location.
|
||||||
|
- `address` (String) - The street address of the site. Maximum 500 characters.
|
||||||
|
- `latitude` (Float) - The latitude of the site. Must be between -90 and 90.
|
||||||
|
- `longitude` (Float) - The longitude of the site. Must be between -180 and 180.
|
||||||
- `snmp_community` (String, Sensitive) - The default SNMP community string for devices at this site.
|
- `snmp_community` (String, Sensitive) - The default SNMP community string for devices at this site.
|
||||||
|
|
||||||
### Read-Only
|
### Read-Only
|
||||||
|
|
|
||||||
|
|
@ -38,11 +38,14 @@ func NewClient(token, baseURL string) *Client {
|
||||||
|
|
||||||
// Site represents a TowerOps site.
|
// Site represents a TowerOps site.
|
||||||
type Site struct {
|
type Site struct {
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Location *string `json:"location,omitempty"`
|
Location *string `json:"location,omitempty"`
|
||||||
SNMPCommunity *string `json:"snmp_community,omitempty"`
|
Address *string `json:"address,omitempty"`
|
||||||
InsertedAt string `json:"inserted_at,omitempty"`
|
Latitude *float64 `json:"latitude,omitempty"`
|
||||||
|
Longitude *float64 `json:"longitude,omitempty"`
|
||||||
|
SNMPCommunity *string `json:"snmp_community,omitempty"`
|
||||||
|
InsertedAt string `json:"inserted_at,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Device represents a TowerOps device.
|
// Device represents a TowerOps device.
|
||||||
|
|
|
||||||
|
|
@ -23,11 +23,14 @@ type SiteResource struct {
|
||||||
|
|
||||||
// SiteResourceModel describes the resource data model.
|
// SiteResourceModel describes the resource data model.
|
||||||
type SiteResourceModel struct {
|
type SiteResourceModel struct {
|
||||||
ID types.String `tfsdk:"id"`
|
ID types.String `tfsdk:"id"`
|
||||||
Name types.String `tfsdk:"name"`
|
Name types.String `tfsdk:"name"`
|
||||||
Location types.String `tfsdk:"location"`
|
Location types.String `tfsdk:"location"`
|
||||||
SNMPCommunity types.String `tfsdk:"snmp_community"`
|
Address types.String `tfsdk:"address"`
|
||||||
InsertedAt types.String `tfsdk:"inserted_at"`
|
Latitude types.Float64 `tfsdk:"latitude"`
|
||||||
|
Longitude types.Float64 `tfsdk:"longitude"`
|
||||||
|
SNMPCommunity types.String `tfsdk:"snmp_community"`
|
||||||
|
InsertedAt types.String `tfsdk:"inserted_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSiteResource creates a new site resource.
|
// NewSiteResource creates a new site resource.
|
||||||
|
|
@ -55,7 +58,19 @@ func (r *SiteResource) Schema(ctx context.Context, req resource.SchemaRequest, r
|
||||||
Required: true,
|
Required: true,
|
||||||
},
|
},
|
||||||
"location": schema.StringAttribute{
|
"location": schema.StringAttribute{
|
||||||
Description: "The physical location or address of the site.",
|
Description: "A short description of the physical location.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"address": schema.StringAttribute{
|
||||||
|
Description: "The street address of the site.",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"latitude": schema.Float64Attribute{
|
||||||
|
Description: "The latitude of the site (-90 to 90).",
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"longitude": schema.Float64Attribute{
|
||||||
|
Description: "The longitude of the site (-180 to 180).",
|
||||||
Optional: true,
|
Optional: true,
|
||||||
},
|
},
|
||||||
"snmp_community": schema.StringAttribute{
|
"snmp_community": schema.StringAttribute{
|
||||||
|
|
@ -99,19 +114,7 @@ func (r *SiteResource) Create(ctx context.Context, req resource.CreateRequest, r
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
site := Site{
|
site := buildSiteFromModel(&data)
|
||||||
Name: data.Name.ValueString(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if !data.Location.IsNull() {
|
|
||||||
location := data.Location.ValueString()
|
|
||||||
site.Location = &location
|
|
||||||
}
|
|
||||||
|
|
||||||
if !data.SNMPCommunity.IsNull() {
|
|
||||||
community := data.SNMPCommunity.ValueString()
|
|
||||||
site.SNMPCommunity = &community
|
|
||||||
}
|
|
||||||
|
|
||||||
created, err := r.client.CreateSite(site)
|
created, err := r.client.CreateSite(site)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -121,13 +124,7 @@ func (r *SiteResource) Create(ctx context.Context, req resource.CreateRequest, r
|
||||||
|
|
||||||
data.ID = types.StringValue(created.ID)
|
data.ID = types.StringValue(created.ID)
|
||||||
data.InsertedAt = types.StringValue(created.InsertedAt)
|
data.InsertedAt = types.StringValue(created.InsertedAt)
|
||||||
|
setSiteOptionalFields(&data, created)
|
||||||
if created.Location != nil {
|
|
||||||
data.Location = types.StringValue(*created.Location)
|
|
||||||
}
|
|
||||||
if created.SNMPCommunity != nil {
|
|
||||||
data.SNMPCommunity = types.StringValue(*created.SNMPCommunity)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||||
}
|
}
|
||||||
|
|
@ -153,18 +150,7 @@ func (r *SiteResource) Read(ctx context.Context, req resource.ReadRequest, resp
|
||||||
|
|
||||||
data.Name = types.StringValue(site.Name)
|
data.Name = types.StringValue(site.Name)
|
||||||
data.InsertedAt = types.StringValue(site.InsertedAt)
|
data.InsertedAt = types.StringValue(site.InsertedAt)
|
||||||
|
setSiteOptionalFields(&data, site)
|
||||||
if site.Location != nil {
|
|
||||||
data.Location = types.StringValue(*site.Location)
|
|
||||||
} else {
|
|
||||||
data.Location = types.StringNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
if site.SNMPCommunity != nil {
|
|
||||||
data.SNMPCommunity = types.StringValue(*site.SNMPCommunity)
|
|
||||||
} else {
|
|
||||||
data.SNMPCommunity = types.StringNull()
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||||
}
|
}
|
||||||
|
|
@ -177,19 +163,7 @@ func (r *SiteResource) Update(ctx context.Context, req resource.UpdateRequest, r
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
site := Site{
|
site := buildSiteFromModel(&data)
|
||||||
Name: data.Name.ValueString(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if !data.Location.IsNull() {
|
|
||||||
location := data.Location.ValueString()
|
|
||||||
site.Location = &location
|
|
||||||
}
|
|
||||||
|
|
||||||
if !data.SNMPCommunity.IsNull() {
|
|
||||||
community := data.SNMPCommunity.ValueString()
|
|
||||||
site.SNMPCommunity = &community
|
|
||||||
}
|
|
||||||
|
|
||||||
updated, err := r.client.UpdateSite(data.ID.ValueString(), site)
|
updated, err := r.client.UpdateSite(data.ID.ValueString(), site)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -203,12 +177,7 @@ func (r *SiteResource) Update(ctx context.Context, req resource.UpdateRequest, r
|
||||||
data.ID = types.StringValue(created.ID)
|
data.ID = types.StringValue(created.ID)
|
||||||
data.InsertedAt = types.StringValue(created.InsertedAt)
|
data.InsertedAt = types.StringValue(created.InsertedAt)
|
||||||
data.Name = types.StringValue(created.Name)
|
data.Name = types.StringValue(created.Name)
|
||||||
if created.Location != nil {
|
setSiteOptionalFields(&data, created)
|
||||||
data.Location = types.StringValue(*created.Location)
|
|
||||||
}
|
|
||||||
if created.SNMPCommunity != nil {
|
|
||||||
data.SNMPCommunity = types.StringValue(*created.SNMPCommunity)
|
|
||||||
}
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -217,13 +186,7 @@ func (r *SiteResource) Update(ctx context.Context, req resource.UpdateRequest, r
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Name = types.StringValue(updated.Name)
|
data.Name = types.StringValue(updated.Name)
|
||||||
|
setSiteOptionalFields(&data, updated)
|
||||||
if updated.Location != nil {
|
|
||||||
data.Location = types.StringValue(*updated.Location)
|
|
||||||
}
|
|
||||||
if updated.SNMPCommunity != nil {
|
|
||||||
data.SNMPCommunity = types.StringValue(*updated.SNMPCommunity)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
|
||||||
}
|
}
|
||||||
|
|
@ -246,3 +209,62 @@ func (r *SiteResource) Delete(ctx context.Context, req resource.DeleteRequest, r
|
||||||
func (r *SiteResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
func (r *SiteResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
|
||||||
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
|
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// buildSiteFromModel converts the Terraform model to an API Site struct.
|
||||||
|
func buildSiteFromModel(data *SiteResourceModel) Site {
|
||||||
|
site := Site{
|
||||||
|
Name: data.Name.ValueString(),
|
||||||
|
}
|
||||||
|
|
||||||
|
if !data.Location.IsNull() {
|
||||||
|
v := data.Location.ValueString()
|
||||||
|
site.Location = &v
|
||||||
|
}
|
||||||
|
if !data.Address.IsNull() {
|
||||||
|
v := data.Address.ValueString()
|
||||||
|
site.Address = &v
|
||||||
|
}
|
||||||
|
if !data.Latitude.IsNull() {
|
||||||
|
v := data.Latitude.ValueFloat64()
|
||||||
|
site.Latitude = &v
|
||||||
|
}
|
||||||
|
if !data.Longitude.IsNull() {
|
||||||
|
v := data.Longitude.ValueFloat64()
|
||||||
|
site.Longitude = &v
|
||||||
|
}
|
||||||
|
if !data.SNMPCommunity.IsNull() {
|
||||||
|
v := data.SNMPCommunity.ValueString()
|
||||||
|
site.SNMPCommunity = &v
|
||||||
|
}
|
||||||
|
|
||||||
|
return site
|
||||||
|
}
|
||||||
|
|
||||||
|
// setSiteOptionalFields maps API response optional fields back to the Terraform model.
|
||||||
|
func setSiteOptionalFields(data *SiteResourceModel, site *Site) {
|
||||||
|
if site.Location != nil {
|
||||||
|
data.Location = types.StringValue(*site.Location)
|
||||||
|
} else {
|
||||||
|
data.Location = types.StringNull()
|
||||||
|
}
|
||||||
|
if site.Address != nil {
|
||||||
|
data.Address = types.StringValue(*site.Address)
|
||||||
|
} else {
|
||||||
|
data.Address = types.StringNull()
|
||||||
|
}
|
||||||
|
if site.Latitude != nil {
|
||||||
|
data.Latitude = types.Float64Value(*site.Latitude)
|
||||||
|
} else {
|
||||||
|
data.Latitude = types.Float64Null()
|
||||||
|
}
|
||||||
|
if site.Longitude != nil {
|
||||||
|
data.Longitude = types.Float64Value(*site.Longitude)
|
||||||
|
} else {
|
||||||
|
data.Longitude = types.Float64Null()
|
||||||
|
}
|
||||||
|
if site.SNMPCommunity != nil {
|
||||||
|
data.SNMPCommunity = types.StringValue(*site.SNMPCommunity)
|
||||||
|
} else {
|
||||||
|
data.SNMPCommunity = types.StringNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue