Skip to content
Snippets Groups Projects
Commit fc9cc55d authored by Matt Layher's avatar Matt Layher Committed by GitHub
Browse files

Merge pull request #13 from chrigl/v2-tenancy

Created generate scripts for basic functions and tests
parents d7212af9 7329fbc3
No related branches found
No related tags found
No related merge requests found
......@@ -35,6 +35,9 @@ type Client struct {
// IPAM provides access to methods in NetBox's IPAM API.
IPAM *IPAMService
// Tenancy provides access to methods in NetBox's Tenancy API.
Tenancy *TenancyService
u *url.URL
client *http.Client
}
......@@ -68,6 +71,7 @@ func NewClient(addr string, client *http.Client) (*Client, error) {
c.DCIM = &DCIMService{c: c}
c.IPAM = &IPAMService{c: c}
c.Tenancy = NewTenancyService(c)
return c, nil
}
......
......@@ -223,6 +223,10 @@ func testClient(t *testing.T, fn func(w http.ResponseWriter, r *http.Request)) (
}
func testHandler(t *testing.T, method string, path string, v interface{}) http.HandlerFunc {
return testStatusHandler(t, method, path, v, 0)
}
func testStatusHandler(t *testing.T, method string, path string, v interface{}, statusCode int) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
if want, got := method, r.Method; want != got {
t.Fatalf("unexpected HTTP method:\n- want: %v\n- got: %v", want, got)
......@@ -232,8 +236,56 @@ func testHandler(t *testing.T, method string, path string, v interface{}) http.H
t.Fatalf("unexpected URL path:\n- want: %v\n- got: %v", want, got)
}
if statusCode > 0 {
w.WriteHeader(statusCode)
}
if err := json.NewEncoder(w).Encode(v); err != nil {
t.Fatalf("error while encoding JSON: %v", err)
}
}
}
func testTenantGroupCreate(n int) *TenantGroup {
return &TenantGroup{
Name: fmt.Sprintf("Tenant Group %d", n),
Slug: fmt.Sprintf("tenant-group-%d", n),
}
}
func testTenantGroup(n int) *TenantGroup {
return &TenantGroup{
ID: n,
Name: fmt.Sprintf("Tenant Group %d", n),
Slug: fmt.Sprintf("tenant-group-%d", n),
}
}
func testTenant(n int) *Tenant {
return testTenantWithGroup(n, testTenantGroup(n))
}
func testTenantCreate(n int) *Tenant {
return testTenantWithGroupCreate(n, testTenantGroup(n))
}
func testTenantWithGroupCreate(n int, t *TenantGroup) *Tenant {
return &Tenant{
Name: fmt.Sprintf("Tenant %d", n),
Slug: fmt.Sprintf("tenant-%d", n),
Description: fmt.Sprintf("Tenant %d Description", n),
Comments: fmt.Sprintf("Tenant %d Comments", n),
Group: t,
}
}
func testTenantWithGroup(n int, t *TenantGroup) *Tenant {
return &Tenant{
ID: n,
Name: fmt.Sprintf("Tenant %d", n),
Slug: fmt.Sprintf("tenant-%d", n),
Description: fmt.Sprintf("Tenant %d Description", n),
Comments: fmt.Sprintf("Tenant %d Comments", n),
Group: t,
}
}
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//+build ignore
package main
import (
"bytes"
"flag"
"fmt"
"go/format"
"log"
"os"
"text/template"
"time"
)
func main() {
typeName := flag.String("type-name", "Example", "Name of the type to use (e.g. TenantGroup).")
serviceName := flag.String("service-name", "ExampleService", "Name of the service to create (e.g. TenantGroupsService).")
endpoint := flag.String("endpoint", "tenancy", "Name of the endpoint (e.g. dcim, ipam, tenancy).")
service := flag.String("service", "example", "Name of the service below endpoint (e.g. tenant-groups).")
clientEndpoint := flag.String("client-endpoint", "Tenancy", "Name of the client endpoint (e.g. DCIM, IPAM, Tenancy).")
clientService := flag.String("client-service", "TenantGroups", "Name of the client service (e.g. TenantGroups, Tenants).")
withoutListOpts := flag.Bool("without-list-opts", false, "Disable list options for this endpoint.")
flag.Parse()
b := &bytes.Buffer{}
functionsTemplate.Execute(b, struct {
Timestamp time.Time
TypeName string
ServiceName string
Endpoint string
Service string
ClientEndpoint string
ClientService string
ListOpts bool
JSONTag func(string) string
}{
Timestamp: time.Now(),
TypeName: *typeName,
ServiceName: *serviceName,
Endpoint: *endpoint,
Service: *service,
ClientEndpoint: *clientEndpoint,
ClientService: *clientService,
ListOpts: !*withoutListOpts,
JSONTag: func(name string) string { return "`json:\"" + name + "\"`" },
})
// go fmt
res, err := format.Source(b.Bytes())
if err != nil {
log.Fatal(err)
}
f, err := os.Create(fmt.Sprintf("%s_%s_basic_test.go", *endpoint, *service))
if err != nil {
log.Fatal(err)
}
defer f.Close()
_, err = f.Write(res)
if err != nil {
log.Fatal(err)
}
}
var functionsTemplate = template.Must(template.New("").Parse(`// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by generate_basic_tests.go. DO NOT EDIT.
package netbox
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"reflect"
"testing"
)
// Using this to override MarshalJSON
// In all cases when posting data to netbox-API, the {{ .TypeName }}.MarshalJSON is what you want,
// but not here as a return in testHandler
type serverData{{ .TypeName }} {{ .TypeName }}
func convertToServerData{{ .TypeName }}(data []*{{ .TypeName }}) []*serverData{{ .TypeName }} {
dataWant := make([]*serverData{{ .TypeName }}, len(data))
for i := range data {
tmp := serverData{{ .TypeName }}(*data[i])
dataWant[i] = &tmp
}
return dataWant
}
func TestBasic{{ .TypeName }}Get(t *testing.T) {
var tests = []struct {
desc string
want *{{ .TypeName }}
}{
{
desc: "Simple {{ .TypeName }}",
want: test{{ .TypeName }}(1),
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
serverData := serverData{{ .TypeName }}(*tt.want)
c, done := testClient(t, testHandler(t, http.MethodGet, "/api/{{ .Endpoint }}/{{ .Service }}/1/", &serverData))
defer done()
res, err := c.{{ .ClientEndpoint }}.{{ .ClientService }}.Get(1)
if err != nil {
t.Fatalf("unexpected error from Client.{{ .ClientEndpoint }}.{{ .ClientService }}.Get: %v", err)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected {{ .TypeName }}:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasic{{ .TypeName }}Get404(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodGet, "/api/{{ .Endpoint }}/{{ .Service }}/1/", &struct {
Detail string {{ call .JSONTag "detail" }}
}{
Detail: "Not found.",
},
http.StatusNotFound))
defer done()
res, err := c.{{ .ClientEndpoint }}.{{ .ClientService }}.Get(1)
errstr := "404 - Not found."
if want, got := errors.New(errstr), err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error from Client.{{ .ClientEndpoint }}.{{ .ClientService }}.Get:\n- want: %v\n- got: %v", want, got)
}
if res != nil {
t.Fatalf("unexpected result:\n- want: %v\n- got: %v", nil, res)
}
}
func TestBasicListExtract{{ .TypeName }}(t *testing.T) {
want := []*{{ .TypeName }}{
test{{ .TypeName }}(1),
test{{ .TypeName }}(2),
}
serverWant := convertToServerData{{ .TypeName }}(want)
serverData, _ := json.Marshal(serverWant)
c, done := testClient(t, testHandler(t, http.MethodGet, "/api/{{ .Endpoint }}/{{ .Service }}/", &pageData{
Count: 2,
NextURL: "",
PreviousURL: "",
Results: serverData,
}))
defer done()
{{ if .ListOpts -}}
page := c.{{ .ClientEndpoint }}.{{ .ClientService }}.List(nil)
{{ else }}
page := c.{{ .ClientEndpoint }}.{{ .ClientService }}.List()
{{ end }}
if page == nil {
t.Fatalf("unexpexted result from c.{{ .ClientEndpoint }}.{{ .ClientService }}.List.")
}
got := []*{{ .TypeName }}{}
counter := 0
for page.Next() {
var err error
got, err = c.{{ .ClientEndpoint }}.{{ .ClientService }}.Extract(page)
if err != nil {
t.Fatalf("unexpected error from c.{{ .ClientEndpoint }}.{{ .ClientService }}.Extract: %v", err)
}
counter = counter + 1
if counter > 2 { // Safe guard
break
}
}
if counter != 1 {
t.Fatalf("unexpected page count:\n- want: 1\n- got: %d", counter)
}
if !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected result:\n- want: %v\n- got: %v", want, got)
}
if page.Err() != nil {
t.Fatalf("unexpected error from page:\n- want: %v\n- got: %v", want, got)
}
}
func TestBasicCreate{{ .TypeName }}(t *testing.T) {
var tests = []struct {
desc string
data *{{ .TypeName }}
want int
serverData interface{}
status int
errstr string
}{
{
desc: "Create with ID 0",
data: test{{ .TypeName }}Create(1),
want: 1,
status: 0,
errstr: "",
serverData: test{{ .TypeName }}(1),
},
{
desc: "Create duplicate",
data: test{{ .TypeName }}Create(1),
want: 0,
status: http.StatusBadRequest,
errstr: "400 - {\"name\":[\"{{ .ServiceName }} with this name already exists.\"]}\n",
serverData: &struct {
Name []string {{ call .JSONTag "name" }}
}{
Name: []string{"{{ .ServiceName }} with this name already exists."},
},
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodPost, "/api/{{ .Endpoint }}/{{ .Service }}/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
res, err := c.{{ .ClientEndpoint }}.{{ .ClientService }}.Create(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected {{ .TypeName }}:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasicUpdate{{ .TypeName }}(t *testing.T) {
var tests = []struct {
desc string
data *{{ .TypeName }}
want int
serverData interface{}
status int
errstr string
}{
{
desc: "Update with ID 1",
data: test{{ .TypeName }}(1),
want: 1,
serverData: test{{ .TypeName }}(1),
status: 0,
errstr: "",
},
{
desc: "Update not found",
data: test{{ .TypeName }}(1),
want: 0,
serverData: &struct {
Detail string
}{
Detail: "Not found.",
},
status: http.StatusNotFound,
errstr: "404 - Not found.",
},
{
desc: "Update to duplicate",
data: test{{ .TypeName }}(1),
want: 0,
serverData: &struct {
Name []string {{ call .JSONTag "name" }}
}{
Name: []string{"{{ .ServiceName }} with this name already exists."},
},
status: http.StatusBadRequest,
errstr: "400 - {\"name\":[\"{{ .ServiceName }} with this name already exists.\"]}\n",
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodPatch, "/api/{{ .Endpoint }}/{{ .Service }}/1/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
res, err := c.{{ .ClientEndpoint }}.{{ .ClientService }}.Update(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected {{ .TypeName }}:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasicDelete{{ .TypeName }}(t *testing.T) {
var tests = []struct {
desc string
data *{{ .TypeName }}
serverData interface{}
status int
errstr string
}{
{
desc: "Delete ID 1",
data: test{{ .TypeName }}(1),
serverData: test{{ .TypeName }}(1),
status: 0,
errstr: "",
},
{
desc: "Delete not Found",
data: test{{ .TypeName }}(1),
serverData: &struct {
Detail string {{ call .JSONTag "detail" }}
}{
Detail: "Not found.",
},
status: http.StatusNotFound,
errstr: "404 - Not found.",
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodDelete, "/api/{{ .Endpoint }}/{{ .Service }}/1/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
err := c.{{ .ClientEndpoint }}.{{ .ClientService }}.Delete(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
})
}
}
`))
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//+build ignore
package main
import (
"bytes"
"flag"
"fmt"
"go/format"
"log"
"os"
"text/template"
"time"
)
func main() {
typeName := flag.String("type-name", "Example", "Name of the type to use (e.g. TenantGroup).")
serviceName := flag.String("service-name", "ExampleService", "Name of the service to create (e.g. TenantGroupsService).")
endpoint := flag.String("endpoint", "tenancy", "Name of the endpoint (e.g. dcim, ipam, tenancy).")
service := flag.String("service", "example", "Name of the service below endpoint (e.g. tenant-groups).")
updateTypeName := flag.String("update-type-name", "", "Name of the type to use for creates and updates, to change the marshal behavior. Default typeName.")
withoutListOpts := flag.Bool("without-list-opts", false, "Disable list options for this endpoint.")
flag.Parse()
if *updateTypeName == "" {
*updateTypeName = *typeName
}
b := &bytes.Buffer{}
functionsTemplate.Execute(b, struct {
Timestamp time.Time
TypeName string
UpdateTypeName string
ServiceName string
Endpoint string
Service string
ListOpts bool
}{
Timestamp: time.Now(),
TypeName: *typeName,
UpdateTypeName: *updateTypeName,
ServiceName: *serviceName,
Endpoint: *endpoint,
Service: *service,
ListOpts: !*withoutListOpts,
})
// go fmt
res, err := format.Source(b.Bytes())
if err != nil {
log.Fatal(err)
}
f, err := os.Create(fmt.Sprintf("%s_%s.go", *endpoint, *service))
if err != nil {
log.Fatal(err)
}
defer f.Close()
_, err = f.Write(res)
if err != nil {
log.Fatal(err)
}
}
var functionsTemplate = template.Must(template.New("").Parse(`// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by generate_functions.go. DO NOT EDIT.
package netbox
import (
"encoding/json"
"fmt"
"net/http"
)
// {{ .ServiceName }} is used in a Client to access NetBox's {{ .Endpoint }}/{{ .Service }} API methods.
type {{ .ServiceName }} struct {
c *Client
}
// Get retrieves an {{ .TypeName }} object from NetBox by its ID.
func (s *{{ .ServiceName }}) Get(id int) (*{{ .TypeName }}, error) {
req, err := s.c.NewRequest(
http.MethodGet,
fmt.Sprintf("api/{{ .Endpoint }}/{{ .Service }}/%d/", id),
nil,
)
if err != nil {
return nil, err
}
t := new({{ .TypeName }})
err = s.c.Do(req, t)
if err != nil {
return nil, err
}
return t, nil
}
// List returns a Page associated with an NetBox API Endpoint.
{{ if .ListOpts -}}
func (s *{{ .ServiceName }}) List(options *List{{ .TypeName }}Options) *Page {
return NewPage(s.c, "api/{{ .Endpoint }}/{{ .Service }}/", options)
}
{{ else -}}
func (s *{{ .ServiceName }}) List() *Page {
return NewPage(s.c, "api/{{ .Endpoint }}/{{ .Service }}/", nil)
}
{{ end }}
// Extract retrives a list of {{ .TypeName }} objects from page.
func (s *{{ .ServiceName }}) Extract(page *Page) ([]*{{ .TypeName }}, error) {
if err := page.Err(); err != nil {
return nil, err
}
var groups []*{{ .TypeName }}
if err := json.Unmarshal(page.data.Results, &groups); err != nil {
return nil, err
}
return groups, nil
}
// Create creates a new {{ .TypeName }} object in NetBox and returns the ID of the new object.
func (s *{{ .ServiceName }}) Create(data *{{ .TypeName }}) (int, error) {
req, err := s.c.NewJSONRequest(http.MethodPost, "api/{{ .Endpoint }}/{{ .Service }}/", nil, data)
if err != nil {
return 0, err
}
g := new({{ .UpdateTypeName }})
err = s.c.Do(req, g)
if err != nil {
return 0, err
}
return g.ID, nil
}
// Update changes an existing {{ .TypeName }} object in NetBox, and returns the ID of the new object.
func (s *{{ .ServiceName }}) Update(data *{{ .TypeName }}) (int, error) {
req, err := s.c.NewJSONRequest(
http.MethodPatch,
fmt.Sprintf("api/{{ .Endpoint }}/{{ .Service }}/%d/", data.ID),
nil,
data,
)
if err != nil {
return 0, err
}
// g is just used to verify correct api result.
// data is not changed, because the g is not the full representation that one would
// get with Get. But if the response was unmarshaled into {{ .UpdateTypeName }} correctly,
// everything went fine, and we do not need to update data.
g := new({{ .UpdateTypeName }})
err = s.c.Do(req, g)
if err != nil {
return 0, err
}
return g.ID, nil
}
// Delete deletes an existing {{ .TypeName }} object from NetBox.
func (s *{{ .ServiceName }}) Delete(data *{{ .TypeName }}) error {
req, err := s.c.NewRequest(
http.MethodDelete,
fmt.Sprintf("api/{{ .Endpoint }}/{{ .Service }}/%d/", data.ID),
nil,
)
if err != nil {
return err
}
return s.c.Do(req, nil)
}
`))
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package netbox
// A TenancyService is udes in a Client to access NetBox's Tenancy API methods.
type TenancyService struct {
c *Client
TenantGroups *TenantGroupsService
Tenants *TenantsService
}
// NewTenancyService returns a TenancyService initialized with all sub-services.
func NewTenancyService(client *Client) *TenancyService {
return &TenancyService{
c: client,
TenantGroups: &TenantGroupsService{
c: client,
},
Tenants: &TenantsService{
c: client,
},
}
}
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by generate_functions.go. DO NOT EDIT.
package netbox
import (
"encoding/json"
"fmt"
"net/http"
)
// TenantGroupsService is used in a Client to access NetBox's tenancy/tenant-groups API methods.
type TenantGroupsService struct {
c *Client
}
// Get retrieves an TenantGroup object from NetBox by its ID.
func (s *TenantGroupsService) Get(id int) (*TenantGroup, error) {
req, err := s.c.NewRequest(
http.MethodGet,
fmt.Sprintf("api/tenancy/tenant-groups/%d/", id),
nil,
)
if err != nil {
return nil, err
}
t := new(TenantGroup)
err = s.c.Do(req, t)
if err != nil {
return nil, err
}
return t, nil
}
// List returns a Page associated with an NetBox API Endpoint.
func (s *TenantGroupsService) List() *Page {
return NewPage(s.c, "api/tenancy/tenant-groups/", nil)
}
// Extract retrives a list of TenantGroup objects from page.
func (s *TenantGroupsService) Extract(page *Page) ([]*TenantGroup, error) {
if err := page.Err(); err != nil {
return nil, err
}
var groups []*TenantGroup
if err := json.Unmarshal(page.data.Results, &groups); err != nil {
return nil, err
}
return groups, nil
}
// Create creates a new TenantGroup object in NetBox and returns the ID of the new object.
func (s *TenantGroupsService) Create(data *TenantGroup) (int, error) {
req, err := s.c.NewJSONRequest(http.MethodPost, "api/tenancy/tenant-groups/", nil, data)
if err != nil {
return 0, err
}
g := new(TenantGroup)
err = s.c.Do(req, g)
if err != nil {
return 0, err
}
return g.ID, nil
}
// Update changes an existing TenantGroup object in NetBox, and returns the ID of the new object.
func (s *TenantGroupsService) Update(data *TenantGroup) (int, error) {
req, err := s.c.NewJSONRequest(
http.MethodPatch,
fmt.Sprintf("api/tenancy/tenant-groups/%d/", data.ID),
nil,
data,
)
if err != nil {
return 0, err
}
// g is just used to verify correct api result.
// data is not changed, because the g is not the full representation that one would
// get with Get. But if the response was unmarshaled into TenantGroup correctly,
// everything went fine, and we do not need to update data.
g := new(TenantGroup)
err = s.c.Do(req, g)
if err != nil {
return 0, err
}
return g.ID, nil
}
// Delete deletes an existing TenantGroup object from NetBox.
func (s *TenantGroupsService) Delete(data *TenantGroup) error {
req, err := s.c.NewRequest(
http.MethodDelete,
fmt.Sprintf("api/tenancy/tenant-groups/%d/", data.ID),
nil,
)
if err != nil {
return err
}
return s.c.Do(req, nil)
}
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by generate_functions.go. DO NOT EDIT.
package netbox
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"reflect"
"testing"
)
// Using this to override MarshalJSON
// In all cases when posting data to netbox-API, the TenantGroup.MarshalJSON is what you want,
// but not here as a return in testHandler
type serverDataTenantGroup TenantGroup
func convertToServerDataTenantGroup(data []*TenantGroup) []*serverDataTenantGroup {
dataWant := make([]*serverDataTenantGroup, len(data))
for i := range data {
tmp := serverDataTenantGroup(*data[i])
dataWant[i] = &tmp
}
return dataWant
}
func TestBasicTenantGroupGet(t *testing.T) {
var tests = []struct {
desc string
want *TenantGroup
}{
{
desc: "Simple TenantGroup",
want: testTenantGroup(1),
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
serverData := serverDataTenantGroup(*tt.want)
c, done := testClient(t, testHandler(t, http.MethodGet, "/api/tenancy/tenant-groups/1/", &serverData))
defer done()
res, err := c.Tenancy.TenantGroups.Get(1)
if err != nil {
t.Fatalf("unexpected error from Client.Tenancy.TenantGroups.Get: %v", err)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected TenantGroup:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasicTenantGroupGet404(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodGet, "/api/tenancy/tenant-groups/1/", &struct {
Detail string `json:"detail"`
}{
Detail: "Not found.",
},
http.StatusNotFound))
defer done()
res, err := c.Tenancy.TenantGroups.Get(1)
errstr := "404 - Not found."
if want, got := errors.New(errstr), err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error from Client.Tenancy.TenantGroups.Get:\n- want: %v\n- got: %v", want, got)
}
if res != nil {
t.Fatalf("unexpected result:\n- want: %v\n- got: %v", nil, res)
}
}
func TestBasicListExtractTenantGroup(t *testing.T) {
want := []*TenantGroup{
testTenantGroup(1),
testTenantGroup(2),
}
serverWant := convertToServerDataTenantGroup(want)
serverData, _ := json.Marshal(serverWant)
c, done := testClient(t, testHandler(t, http.MethodGet, "/api/tenancy/tenant-groups/", &pageData{
Count: 2,
NextURL: "",
PreviousURL: "",
Results: serverData,
}))
defer done()
page := c.Tenancy.TenantGroups.List()
if page == nil {
t.Fatalf("unexpexted result from c.Tenancy.TenantGroups.List.")
}
got := []*TenantGroup{}
counter := 0
for page.Next() {
var err error
got, err = c.Tenancy.TenantGroups.Extract(page)
if err != nil {
t.Fatalf("unexpected error from c.Tenancy.TenantGroups.Extract: %v", err)
}
counter = counter + 1
if counter > 2 { // Safe guard
break
}
}
if counter != 1 {
t.Fatalf("unexpected page count:\n- want: 1\n- got: %d", counter)
}
if !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected result:\n- want: %v\n- got: %v", want, got)
}
if page.Err() != nil {
t.Fatalf("unexpected error from page:\n- want: %v\n- got: %v", want, got)
}
}
func TestBasicCreateTenantGroup(t *testing.T) {
var tests = []struct {
desc string
data *TenantGroup
want int
serverData interface{}
status int
errstr string
}{
{
desc: "Create with ID 0",
data: testTenantGroupCreate(1),
want: 1,
status: 0,
errstr: "",
serverData: testTenantGroup(1),
},
{
desc: "Create duplicate",
data: testTenantGroupCreate(1),
want: 0,
status: http.StatusBadRequest,
errstr: "400 - {\"name\":[\"TenantGroupsService with this name already exists.\"]}\n",
serverData: &struct {
Name []string `json:"name"`
}{
Name: []string{"TenantGroupsService with this name already exists."},
},
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodPost, "/api/tenancy/tenant-groups/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
res, err := c.Tenancy.TenantGroups.Create(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected TenantGroup:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasicUpdateTenantGroup(t *testing.T) {
var tests = []struct {
desc string
data *TenantGroup
want int
serverData interface{}
status int
errstr string
}{
{
desc: "Update with ID 1",
data: testTenantGroup(1),
want: 1,
serverData: testTenantGroup(1),
status: 0,
errstr: "",
},
{
desc: "Update not found",
data: testTenantGroup(1),
want: 0,
serverData: &struct {
Detail string
}{
Detail: "Not found.",
},
status: http.StatusNotFound,
errstr: "404 - Not found.",
},
{
desc: "Update to duplicate",
data: testTenantGroup(1),
want: 0,
serverData: &struct {
Name []string `json:"name"`
}{
Name: []string{"TenantGroupsService with this name already exists."},
},
status: http.StatusBadRequest,
errstr: "400 - {\"name\":[\"TenantGroupsService with this name already exists.\"]}\n",
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodPatch, "/api/tenancy/tenant-groups/1/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
res, err := c.Tenancy.TenantGroups.Update(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected TenantGroup:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasicDeleteTenantGroup(t *testing.T) {
var tests = []struct {
desc string
data *TenantGroup
serverData interface{}
status int
errstr string
}{
{
desc: "Delete ID 1",
data: testTenantGroup(1),
serverData: testTenantGroup(1),
status: 0,
errstr: "",
},
{
desc: "Delete not Found",
data: testTenantGroup(1),
serverData: &struct {
Detail string `json:"detail"`
}{
Detail: "Not found.",
},
status: http.StatusNotFound,
errstr: "404 - Not found.",
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodDelete, "/api/tenancy/tenant-groups/1/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
err := c.Tenancy.TenantGroups.Delete(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
})
}
}
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package netbox
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"testing"
)
func TestTenantGroupUnmarshalJSON(t *testing.T) {
var tests = []struct {
desc string
data []byte
want *TenantGroup
}{
{
desc: "full",
data: []byte(`{ "id": 1, "name": "Tenant Group 1", "slug": "tenant-group-1", "custom_fields": {} }`),
want: testTenantGroup(1),
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
result := new(TenantGroup)
err := json.Unmarshal(tt.data, result)
if err != nil {
t.Fatalf("unexpected error from TenantGroup.UnmarshalJSON: %v", err)
}
if want, got := tt.want, result; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected TenantGroup:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestTenantGroupMarshalJSON(t *testing.T) {
var tests = []struct {
desc string
data *TenantGroup
want []byte
}{
{
desc: "With TenantGroup.ID",
data: testTenantGroup(1),
want: []byte(`{"id":1,"name":"Tenant Group 1","slug":"tenant-group-1"}`),
},
{
desc: "No TenantGroup.ID",
data: testTenantGroup(0),
want: []byte(`{"name":"Tenant Group 0","slug":"tenant-group-0"}`),
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
result, err := json.Marshal(tt.data)
if err != nil {
t.Fatalf("unexpected error from TenantGroup.MarshalJSON: %v", err)
}
if want, got := tt.want, result; bytes.Compare(want, got) != 0 {
t.Fatalf("unexpected TenantGroup:\n- want: %s\n- got: %s", want, got)
}
})
}
}
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package netbox
// A TenantGroup is a representation of netbox tenant-groups
type TenantGroup struct {
ID int `json:"id,omitempty"`
Name string `json:"name"`
Slug string `json:"slug"`
}
//go:generate go run generate_functions.go -type-name TenantGroup -service-name TenantGroupsService -endpoint tenancy -service tenant-groups -without-list-opts
//go:generate go run generate_basic_tests.go -type-name TenantGroup -service-name TenantGroupsService -endpoint tenancy -service tenant-groups -client-endpoint Tenancy -client-service TenantGroups -without-list-opts
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by generate_functions.go. DO NOT EDIT.
package netbox
import (
"encoding/json"
"fmt"
"net/http"
)
// TenantsService is used in a Client to access NetBox's tenancy/tenants API methods.
type TenantsService struct {
c *Client
}
// Get retrieves an Tenant object from NetBox by its ID.
func (s *TenantsService) Get(id int) (*Tenant, error) {
req, err := s.c.NewRequest(
http.MethodGet,
fmt.Sprintf("api/tenancy/tenants/%d/", id),
nil,
)
if err != nil {
return nil, err
}
t := new(Tenant)
err = s.c.Do(req, t)
if err != nil {
return nil, err
}
return t, nil
}
// List returns a Page associated with an NetBox API Endpoint.
func (s *TenantsService) List(options *ListTenantOptions) *Page {
return NewPage(s.c, "api/tenancy/tenants/", options)
}
// Extract retrives a list of Tenant objects from page.
func (s *TenantsService) Extract(page *Page) ([]*Tenant, error) {
if err := page.Err(); err != nil {
return nil, err
}
var groups []*Tenant
if err := json.Unmarshal(page.data.Results, &groups); err != nil {
return nil, err
}
return groups, nil
}
// Create creates a new Tenant object in NetBox and returns the ID of the new object.
func (s *TenantsService) Create(data *Tenant) (int, error) {
req, err := s.c.NewJSONRequest(http.MethodPost, "api/tenancy/tenants/", nil, data)
if err != nil {
return 0, err
}
g := new(updateTenant)
err = s.c.Do(req, g)
if err != nil {
return 0, err
}
return g.ID, nil
}
// Update changes an existing Tenant object in NetBox, and returns the ID of the new object.
func (s *TenantsService) Update(data *Tenant) (int, error) {
req, err := s.c.NewJSONRequest(
http.MethodPatch,
fmt.Sprintf("api/tenancy/tenants/%d/", data.ID),
nil,
data,
)
if err != nil {
return 0, err
}
// g is just used to verify correct api result.
// data is not changed, because the g is not the full representation that one would
// get with Get. But if the response was unmarshaled into updateTenant correctly,
// everything went fine, and we do not need to update data.
g := new(updateTenant)
err = s.c.Do(req, g)
if err != nil {
return 0, err
}
return g.ID, nil
}
// Delete deletes an existing Tenant object from NetBox.
func (s *TenantsService) Delete(data *Tenant) error {
req, err := s.c.NewRequest(
http.MethodDelete,
fmt.Sprintf("api/tenancy/tenants/%d/", data.ID),
nil,
)
if err != nil {
return err
}
return s.c.Do(req, nil)
}
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by generate_functions.go. DO NOT EDIT.
package netbox
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"reflect"
"testing"
)
// Using this to override MarshalJSON
// In all cases when posting data to netbox-API, the Tenant.MarshalJSON is what you want,
// but not here as a return in testHandler
type serverDataTenant Tenant
func convertToServerDataTenant(data []*Tenant) []*serverDataTenant {
dataWant := make([]*serverDataTenant, len(data))
for i := range data {
tmp := serverDataTenant(*data[i])
dataWant[i] = &tmp
}
return dataWant
}
func TestBasicTenantGet(t *testing.T) {
var tests = []struct {
desc string
want *Tenant
}{
{
desc: "Simple Tenant",
want: testTenant(1),
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
serverData := serverDataTenant(*tt.want)
c, done := testClient(t, testHandler(t, http.MethodGet, "/api/tenancy/tenants/1/", &serverData))
defer done()
res, err := c.Tenancy.Tenants.Get(1)
if err != nil {
t.Fatalf("unexpected error from Client.Tenancy.Tenants.Get: %v", err)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected Tenant:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasicTenantGet404(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodGet, "/api/tenancy/tenants/1/", &struct {
Detail string `json:"detail"`
}{
Detail: "Not found.",
},
http.StatusNotFound))
defer done()
res, err := c.Tenancy.Tenants.Get(1)
errstr := "404 - Not found."
if want, got := errors.New(errstr), err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error from Client.Tenancy.Tenants.Get:\n- want: %v\n- got: %v", want, got)
}
if res != nil {
t.Fatalf("unexpected result:\n- want: %v\n- got: %v", nil, res)
}
}
func TestBasicListExtractTenant(t *testing.T) {
want := []*Tenant{
testTenant(1),
testTenant(2),
}
serverWant := convertToServerDataTenant(want)
serverData, _ := json.Marshal(serverWant)
c, done := testClient(t, testHandler(t, http.MethodGet, "/api/tenancy/tenants/", &pageData{
Count: 2,
NextURL: "",
PreviousURL: "",
Results: serverData,
}))
defer done()
page := c.Tenancy.Tenants.List(nil)
if page == nil {
t.Fatalf("unexpexted result from c.Tenancy.Tenants.List.")
}
got := []*Tenant{}
counter := 0
for page.Next() {
var err error
got, err = c.Tenancy.Tenants.Extract(page)
if err != nil {
t.Fatalf("unexpected error from c.Tenancy.Tenants.Extract: %v", err)
}
counter = counter + 1
if counter > 2 { // Safe guard
break
}
}
if counter != 1 {
t.Fatalf("unexpected page count:\n- want: 1\n- got: %d", counter)
}
if !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected result:\n- want: %v\n- got: %v", want, got)
}
if page.Err() != nil {
t.Fatalf("unexpected error from page:\n- want: %v\n- got: %v", want, got)
}
}
func TestBasicCreateTenant(t *testing.T) {
var tests = []struct {
desc string
data *Tenant
want int
serverData interface{}
status int
errstr string
}{
{
desc: "Create with ID 0",
data: testTenantCreate(1),
want: 1,
status: 0,
errstr: "",
serverData: testTenant(1),
},
{
desc: "Create duplicate",
data: testTenantCreate(1),
want: 0,
status: http.StatusBadRequest,
errstr: "400 - {\"name\":[\"TenantsService with this name already exists.\"]}\n",
serverData: &struct {
Name []string `json:"name"`
}{
Name: []string{"TenantsService with this name already exists."},
},
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodPost, "/api/tenancy/tenants/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
res, err := c.Tenancy.Tenants.Create(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected Tenant:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasicUpdateTenant(t *testing.T) {
var tests = []struct {
desc string
data *Tenant
want int
serverData interface{}
status int
errstr string
}{
{
desc: "Update with ID 1",
data: testTenant(1),
want: 1,
serverData: testTenant(1),
status: 0,
errstr: "",
},
{
desc: "Update not found",
data: testTenant(1),
want: 0,
serverData: &struct {
Detail string
}{
Detail: "Not found.",
},
status: http.StatusNotFound,
errstr: "404 - Not found.",
},
{
desc: "Update to duplicate",
data: testTenant(1),
want: 0,
serverData: &struct {
Name []string `json:"name"`
}{
Name: []string{"TenantsService with this name already exists."},
},
status: http.StatusBadRequest,
errstr: "400 - {\"name\":[\"TenantsService with this name already exists.\"]}\n",
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodPatch, "/api/tenancy/tenants/1/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
res, err := c.Tenancy.Tenants.Update(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected Tenant:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestBasicDeleteTenant(t *testing.T) {
var tests = []struct {
desc string
data *Tenant
serverData interface{}
status int
errstr string
}{
{
desc: "Delete ID 1",
data: testTenant(1),
serverData: testTenant(1),
status: 0,
errstr: "",
},
{
desc: "Delete not Found",
data: testTenant(1),
serverData: &struct {
Detail string `json:"detail"`
}{
Detail: "Not found.",
},
status: http.StatusNotFound,
errstr: "404 - Not found.",
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
c, done := testClient(t, testStatusHandler(t, http.MethodDelete, "/api/tenancy/tenants/1/", tt.serverData, tt.status))
defer done()
var terr error
if tt.errstr != "" {
terr = errors.New(tt.errstr) // Using errstr and initialize real err here, to satisfy golint
}
err := c.Tenancy.Tenants.Delete(tt.data)
if want, got := terr, err; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected error:\n- want: %v\n- got: %v", want, got)
}
})
}
}
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package netbox
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"net/url"
"reflect"
"testing"
)
func TestTenantGet(t *testing.T) {
var tests = []struct {
desc string
want *Tenant
wantGroup *TenantGroup
}{
{
desc: "Without TenantGroup",
want: testTenantWithGroup(1, nil),
wantGroup: nil,
},
{
desc: "With TenantGroup",
want: testTenantWithGroup(1, testTenantGroup(1)),
wantGroup: testTenantGroup(1),
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
serverData := serverDataTenant(*tt.want)
c, done := testClient(t, testHandler(t, http.MethodGet, "/api/tenancy/tenants/1/", &serverData))
defer done()
res, err := c.Tenancy.Tenants.Get(1)
if err != nil {
t.Fatalf("unexpected error from Client.Tenancy.Tenants.Get: %v", err)
}
if want, got := tt.want, res; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected Tenant:\n- want: %v\n- got: %v", want, got)
}
if want, got := tt.wantGroup, res.Group; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected TenantGroup:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestTenantUnmarshalJSON(t *testing.T) {
var tests = []struct {
desc string
data []byte
want *Tenant
}{
{
desc: "Nil Group",
data: []byte(`{ "id": 1, "name": "Tenant 1", "slug": "tenant-1", "group": null, "description": "Tenant 1 Description", "comments": "Tenant 1 Comments", "custom_fields": {} }`),
want: testTenantWithGroup(1, nil),
},
{
desc: "With Group",
data: []byte(`{ "id": 1, "name": "Tenant 1", "slug": "tenant-1", "group": {"id": 1, "name": "Tenant Group 1", "slug": "tenant-group-1"}, "description": "Tenant 1 Description", "comments": "Tenant 1 Comments", "custom_fields": {} }`),
want: testTenant(1),
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
result := new(Tenant)
err := json.Unmarshal(tt.data, result)
if err != nil {
t.Fatalf("unexpected error from Tenant.UnmarshalJSON: %v", err)
}
if want, got := tt.want, result; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected Tenant:\n- want: %v\n- got: %v", want, got)
}
})
}
}
func TestTenantMarshalJSON(t *testing.T) {
var tests = []struct {
desc string
data *Tenant
want []byte
}{
{
desc: "Nil Group",
data: testTenantWithGroup(1, nil),
want: []byte(`{"id":1,"name":"Tenant 1","slug":"tenant-1","description":"Tenant 1 Description","comments":"Tenant 1 Comments"}`),
},
{
desc: "With Group",
data: testTenant(1),
want: []byte(`{"id":1,"name":"Tenant 1","slug":"tenant-1","description":"Tenant 1 Description","comments":"Tenant 1 Comments","group":1}`),
},
{
desc: "No Tenant.ID",
data: testTenantWithGroup(0, nil),
want: []byte(`{"name":"Tenant 0","slug":"tenant-0","description":"Tenant 0 Description","comments":"Tenant 0 Comments"}`),
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
result, err := json.Marshal(tt.data)
if err != nil {
t.Fatalf("unexpected error from Tenant.MarshalJSON: %v", err)
}
if want, got := tt.want, result; bytes.Compare(want, got) != 0 {
t.Fatalf("unexpected Tenant:\n- want: %s\n- got: %s", want, got)
}
})
}
}
func TestListTenantOptions(t *testing.T) {
var tests = []struct {
desc string
o *ListTenantOptions
v url.Values
}{
{
desc: "empty options",
},
{
desc: "full options",
o: &ListTenantOptions{
Name: "Hello",
IDIn: "1,2,3",
GroupID: 1,
Query: "World",
},
v: url.Values{
"name": []string{"Hello"},
"id__in": []string{"1,2,3"},
"group_id": []string{"1"},
"q": []string{"World"},
},
},
{
desc: "group vs group_id",
o: &ListTenantOptions{
GroupID: 1,
Group: "Group1",
},
v: url.Values{
"group_id": []string{"1"},
},
},
{
desc: "group name",
o: &ListTenantOptions{
Group: "Group 1",
},
v: url.Values{
"group": []string{"Group 1"},
},
},
}
for i, tt := range tests {
t.Run(fmt.Sprintf("[%d] %s", i, tt.desc), func(t *testing.T) {
v, err := tt.o.Values()
if err != nil {
t.Fatalf("unexpected Values error: %v", err)
}
if want, got := tt.v, v; !reflect.DeepEqual(want, got) {
t.Fatalf("unexpected url.Values map:\n- want: %v\n- got: %v", want, got)
}
})
}
}
// Copyright 2017 The go-netbox Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package netbox
import (
"encoding/json"
"net/url"
"strconv"
)
// A Tenant is a representation of netbox tenants
type Tenant struct {
ID int `json:"id,omitempty"`
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Comments string `json:"comments"`
Group *TenantGroup `json:"Group"`
}
// A updateTenant is the internal representation of tenants
// needed to POST/PUT/PATCH to Netbox API
type updateTenant struct {
ID int `json:"id,omitempty"`
Name string `json:"name"`
Slug string `json:"slug"`
Description string `json:"description"`
Comments string `json:"comments"`
Group int `json:"group,omitempty"`
}
// MarshalJSON marshals an Tenant into JSON bytes.
func (t *Tenant) MarshalJSON() ([]byte, error) {
group := 0
if t.Group != nil {
group = t.Group.ID
}
return json.Marshal(updateTenant{
ID: t.ID,
Name: t.Name,
Slug: t.Slug,
Description: t.Description,
Comments: t.Comments,
Group: group,
})
}
// ListTenantOptions is used as an argument for Client.Tenancy.Tenant.List.
// Integer fields with an *ID suffix are preferred over their string
// counterparts, and if both are set, only the *ID field will be used.
type ListTenantOptions struct {
Name string
IDIn string
GroupID int
Group string
Query string
}
// Values generates a url.Values map from the data in ListTenantOptions.
func (o *ListTenantOptions) Values() (url.Values, error) {
if o == nil {
return nil, nil
}
v := url.Values{}
switch {
case o.GroupID != 0:
v.Set("group_id", strconv.Itoa(o.GroupID))
case o.Group != "":
v.Set("group", o.Group)
}
if o.Name != "" {
v.Set("name", o.Name)
}
if o.IDIn != "" {
v.Set("id__in", o.IDIn)
}
if o.Query != "" {
v.Set("q", o.Query)
}
return v, nil
}
//go:generate go run generate_functions.go -type-name Tenant -update-type-name updateTenant -service-name TenantsService -endpoint tenancy -service tenants
//go:generate go run generate_basic_tests.go -type-name Tenant -service-name TenantsService -endpoint tenancy -service tenants -client-endpoint Tenancy -client-service Tenants
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment