Skip to content

Commit

Permalink
Merge pull request #8 from RackHD/reservations
Browse files Browse the repository at this point in the history
add intial reservations routes, models, and business logic
  • Loading branch information
jfrey authored Aug 23, 2016
2 parents 58fae4d + 94ac333 commit 17c3c21
Show file tree
Hide file tree
Showing 14 changed files with 900 additions and 27 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,8 @@ run directly using the Makefile as a guide for their format.
### Reservation Routes

* GET /subnets/{id}/reservations
* GET /pools/{id}/reservations
* GET /reservations/{id}
* POST /subnets/{id}/reservations
* POST /pools/{id}/reservations
* DELETE /reservations/{id}
* PATCH /reservations/{id}

Expand Down
77 changes: 71 additions & 6 deletions controllers/controllers_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ func Do(req *http.Request) *http.Response {
}

type MockIpam struct {
Err error
Err error

Pools []models.Pool
PoolCreated models.Pool
PoolUpdated models.Pool
Expand All @@ -43,6 +44,11 @@ type MockIpam struct {
SubnetCreated models.Subnet
SubnetUpdated models.Subnet
SubnetDeleted string

Reservations []models.Reservation
ReservationCreated models.Reservation
ReservationUpdated models.Reservation
ReservationDeleted string
}

func NewMockIpam() *MockIpam {
Expand All @@ -63,6 +69,14 @@ func NewMockIpam() *MockIpam {
Pool: bson.ObjectIdHex("578af30bbc63780007d99195"),
},
},
Reservations: []models.Reservation{
{
ID: bson.ObjectIdHex("578af30bbc63780007d99195"),
Name: "Mock Subnet",
Tags: []string{"mock"},
Subnet: bson.ObjectIdHex("578af30bbc63780007d99195"),
},
},
}
}

Expand Down Expand Up @@ -118,7 +132,7 @@ func (mock *MockIpam) DeletePool(id string) error {
}

// GetSubnets ...
func (mock *MockIpam) GetSubnets() ([]models.Subnet, error) {
func (mock *MockIpam) GetSubnets(string) ([]models.Subnet, error) {
if mock.Err != nil {
return []models.Subnet{}, mock.Err
}
Expand Down Expand Up @@ -168,11 +182,62 @@ func (mock *MockIpam) DeleteSubnet(id string) error {
return mock.Err
}

// GetPoolSubnets ...
func (mock *MockIpam) GetPoolSubnets(string) ([]models.Subnet, error) {
// GetReservations ...
func (mock *MockIpam) GetReservations(string) ([]models.Reservation, error) {
if mock.Err != nil {
return []models.Subnet{}, mock.Err
return []models.Reservation{}, mock.Err
}

return mock.Subnets, mock.Err
return mock.Reservations, mock.Err
}

// GetReservation ...
func (mock *MockIpam) GetReservation(string) (models.Reservation, error) {
if mock.Err != nil {
return models.Reservation{}, mock.Err
}

return mock.Reservations[0], mock.Err
}

// CreateReservation ...
func (mock *MockIpam) CreateReservation(reservation models.Reservation) error {
if mock.Err != nil {
return mock.Err
}

mock.ReservationCreated = reservation

return mock.Err
}

// UpdateReservation ...
func (mock *MockIpam) UpdateReservation(reservation models.Reservation) error {
if mock.Err != nil {
return mock.Err
}

mock.ReservationUpdated = reservation

return mock.Err
}

// DeleteReservation ...
func (mock *MockIpam) DeleteReservation(id string) error {
if mock.Err != nil {
return mock.Err
}

mock.ReservationDeleted = id

return mock.Err
}

// GetPoolReservations ...
func (mock *MockIpam) GetPoolReservations(string) ([]models.Reservation, error) {
if mock.Err != nil {
return []models.Reservation{}, mock.Err
}

return mock.Reservations, mock.Err
}
116 changes: 116 additions & 0 deletions controllers/reservations.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package controllers

import (
"fmt"
"net/http"

"gopkg.in/mgo.v2/bson"

"github.com/RackHD/ipam/controllers/helpers"
"github.com/RackHD/ipam/interfaces"
"github.com/RackHD/ipam/models"
"github.com/RackHD/ipam/resources"
"github.com/gorilla/mux"
)

// ReservationsController provides methods for handling requests to the Reservations API.
type ReservationsController struct {
ipam interfaces.Ipam
}

// NewReservationsController returns a newly configured ReservationsController.
func NewReservationsController(router *mux.Router, ipam interfaces.Ipam) (*ReservationsController, error) {
c := ReservationsController{
ipam: ipam,
}

router.Handle("/subnets/{id}/reservations", helpers.ErrorHandler(c.Index)).Methods(http.MethodGet)
router.Handle("/subnets/{id}/reservations", helpers.ErrorHandler(c.Create)).Methods(http.MethodPost)
router.Handle("/reservations/{id}", helpers.ErrorHandler(c.Show)).Methods(http.MethodGet)
router.Handle("/reservations/{id}", helpers.ErrorHandler(c.Update)).Methods(http.MethodPut, http.MethodPatch)
router.Handle("/reservations/{id}", helpers.ErrorHandler(c.Delete)).Methods(http.MethodDelete)

return &c, nil
}

// Index returns a list of Reservations.
func (c *ReservationsController) Index(w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)

reservations, err := c.ipam.GetReservations(vars["id"])
if err != nil {
return err
}

return helpers.RenderResource(w, r, resources.ReservationsResourceType, http.StatusOK, reservations)
}

// Create creates a Reservation.
func (c *ReservationsController) Create(w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)

resource, err := helpers.AcceptResource(r, resources.ReservationResourceType)
if err != nil {
return err
}

if reservation, ok := resource.(models.Reservation); ok {
reservation.Subnet = bson.ObjectIdHex(vars["id"])

err = c.ipam.CreateReservation(reservation)
if err != nil {
return err
}

return helpers.RenderLocation(w, r, http.StatusCreated, fmt.Sprintf("/reservations/%s", reservation.ID.Hex()))
}

return fmt.Errorf("Invalid Resource Type")
}

// Show returns the requested Reservation.
func (c *ReservationsController) Show(w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)

reservation, err := c.ipam.GetReservation(vars["id"])
if err != nil {
return err
}

return helpers.RenderResource(w, r, resources.ReservationResourceType, http.StatusOK, reservation)
}

// Update updates the requested Reservation.
func (c *ReservationsController) Update(w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)

resource, err := helpers.AcceptResource(r, resources.ReservationResourceType)
if err != nil {
return err
}

if reservation, ok := resource.(models.Reservation); ok {
reservation.ID = bson.ObjectIdHex(vars["id"])

err = c.ipam.UpdateReservation(reservation)
if err != nil {
return err
}

return helpers.RenderLocation(w, r, http.StatusNoContent, fmt.Sprintf("/reservations/%s", reservation.ID.Hex()))
}

return fmt.Errorf("Invalid Resource Type")
}

// Delete removes the requested Reservation.
func (c *ReservationsController) Delete(w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)

err := c.ipam.DeleteReservation(vars["id"])
if err != nil {
return err
}

return helpers.RenderLocation(w, r, http.StatusOK, fmt.Sprintf("/reservations"))
}
Loading

0 comments on commit 17c3c21

Please sign in to comment.