Skip to content

Commit

Permalink
Merge pull request #74 from ExternalReality/add_domain_request
Browse files Browse the repository at this point in the history
#74

This PR adds `MAAS 2.0`'s `Domains` endpoint. The only thing one can do with a `Domain` right now is query its name since this is all `Juju` wants from it thus far.
  • Loading branch information
jujubot authored May 21, 2018
2 parents 613dc12 + b765a87 commit abe1190
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 0 deletions.
17 changes: 17 additions & 0 deletions controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,23 @@ func (c *controller) Zones() ([]Zone, error) {
return result, nil
}

// Domains implements Controller
func (c *controller) Domains() ([]Domain, error) {
source, err := c.get("domains")
if err != nil {
return nil, NewUnexpectedError(err)
}
domains, err := readDomains(c.apiVersion, source)
if err != nil {
return nil, errors.Trace(err)
}
var result []Domain
for _, domain := range domains {
result = append(result, domain)
}
return result, nil
}

// DevicesArgs is a argument struct for selecting Devices.
// Only devices that match the specified criteria are returned.
type DevicesArgs struct {
Expand Down
85 changes: 85 additions & 0 deletions domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.

package gomaasapi

import (
"github.com/juju/errors"
"github.com/juju/schema"
"github.com/juju/version"
)

type domain struct {
authoritative bool
resourceRecordCount int
ttl *int
resourceURI string
id int
name string
}

// Name implements Domain interface
func (domain *domain) Name() string {
return domain.name
}

func readDomains(controllerVersion version.Number, source interface{}) ([]*domain, error) {
checker := schema.List(schema.StringMap(schema.Any()))
coerced, err := checker.Coerce(source, nil)
if err != nil {
return nil, errors.Annotatef(err, "domain base schema check failed")
}
valid := coerced.([]interface{})
return readDomainList(valid)
}

func domain_(source map[string]interface{}) (*domain, error) {
fields := schema.Fields{
"authoritative": schema.Bool(),
"resource_record_count": schema.ForceInt(),
"ttl": schema.OneOf(schema.Nil("null"), schema.ForceInt()),
"resource_uri": schema.String(),
"id": schema.ForceInt(),
"name": schema.String(),
}
checker := schema.FieldMap(fields, nil) // no defaults
coerced, err := checker.Coerce(source, nil)
if err != nil {
return nil, errors.Annotatef(err, "domain schema check failed")
}
valid := coerced.(map[string]interface{})

var ttl *int = nil
if valid["ttl"] != nil {
i := valid["ttl"].(int)
ttl = &i
}

result := &domain{
authoritative: valid["authoritative"].(bool),
id: valid["id"].(int),
name: valid["name"].(string),
resourceRecordCount: valid["resource_record_count"].(int),
resourceURI: valid["resource_uri"].(string),
ttl: ttl,
}

return result, nil
}

// readDomainList expects the values of the sourceList to be string maps.
func readDomainList(sourceList []interface{}) ([]*domain, error) {
result := make([]*domain, 0, len(sourceList))
for i, value := range sourceList {
source, ok := value.(map[string]interface{})
if !ok {
return nil, errors.Errorf("unexpected value for domain %d, %T", i, value)
}
domain, err := domain_(source)
if err != nil {
return nil, errors.Annotatef(err, "domain %d", i)
}
result = append(result, domain)
}
return result, nil
}
46 changes: 46 additions & 0 deletions domain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2018 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.

package gomaasapi

import (
jc "github.com/juju/testing/checkers"
gc "gopkg.in/check.v1"
)

type domainSuite struct{}

var _ = gc.Suite(&domainSuite{})

func (*domainSuite) TestReadDomainsBadSchema(c *gc.C) {
_, err := readDomains(twoDotOh, "something")
c.Assert(err.Error(), gc.Equals, `domain base schema check failed: expected list, got string("something")`)
}

func (*domainSuite) TestReadDomains(c *gc.C) {
domains, err := readDomains(twoDotOh, parseJSON(c, domainResponse))
c.Assert(err, jc.ErrorIsNil)
c.Assert(domains, gc.HasLen, 2)
c.Assert(domains[0].Name(), gc.Equals, "maas")
c.Assert(domains[1].Name(), gc.Equals, "anotherDomain.com")
}

var domainResponse = `
[
{
"authoritative": "true",
"resource_uri": "/MAAS/api/2.0/domains/0/",
"name": "maas",
"id": 0,
"ttl": null,
"resource_record_count": 3
}, {
"authoritative": "true",
"resource_uri": "/MAAS/api/2.0/domains/1/",
"name": "anotherDomain.com",
"id": 1,
"ttl": 10,
"resource_record_count": 3
}
]
`
8 changes: 8 additions & 0 deletions interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ type Controller interface {
// file without sending the content of the file, we can return a File
// instance here too.
AddFile(AddFileArgs) error

// Returns the DNS Domain Managed By MAAS
Domains() ([]Domain, error)
}

// File represents a file stored in the MAAS controller.
Expand Down Expand Up @@ -142,6 +145,11 @@ type Zone interface {
Description() string
}

type Domain interface {
// The name of the Domain
Name() string
}

// BootResource is the bomb... find something to say here.
type BootResource interface {
ID() int
Expand Down

0 comments on commit abe1190

Please sign in to comment.