Skip to content

Commit

Permalink
Implement IPAMs reserve-specific address endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
Mario Schäfer committed Nov 3, 2023
1 parent e381700 commit 7d9711e
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 3 deletions.
56 changes: 53 additions & 3 deletions pkg/ipam/address/address.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ import (
)

const (
pathAddressPrefix = "/api/ipam/v1/address.json"
pathReserveAddressPrefix = "/api/ipam/v1/address/reserve/ip/count.json"
pathFilteredAddressPrefix = "/api/ipam/v1/address/filtered.json"
pathAddressPrefix = "/api/ipam/v1/address.json"
pathReserveAddressPrefix = "/api/ipam/v1/address/reserve/ip/count.json"
pathReserveSpecificAddressPrefix = "/api/ipam/v1/address/reserve/ip/specific.json"
pathFilteredAddressPrefix = "/api/ipam/v1/address/filtered.json"
)

// Filters that can be applied to the GetFiltered request
Expand Down Expand Up @@ -92,6 +93,15 @@ type ReservedIP struct {
Prefix string `json:"prefix"`
}

type ReserveSpecific struct {
LocationID string `json:"location_identifier"`
VlanID string `json:"vlan_identifier"`
IPs []string `json:"ips"`
ReservationPeriod int `json:"reservation_period,omitempty"`
}

type ReserveSpecificSummary ReserveRandomSummary

type listResponse struct {
Data struct {
Data []Summary `json:"data"`
Expand Down Expand Up @@ -310,6 +320,46 @@ func (a api) ReserveRandom(ctx context.Context, reserve ReserveRandom) (ReserveR
return summary, nil
}

func (a api) ReserveSpecific(ctx context.Context, reserve ReserveSpecific) (ReserveSpecificSummary, error) {
url := fmt.Sprintf(
"%s%s",
a.client.BaseURL(),
pathReserveSpecificAddressPrefix,
)

requestData := bytes.Buffer{}
if err := json.NewEncoder(&requestData).Encode(reserve); err != nil {
panic(fmt.Sprintf("could not create request data for IP address reservation: %v", err))
}

req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, &requestData)
if err != nil {
return ReserveSpecificSummary{}, fmt.Errorf("could not create IP address reserve specific post request: %w", err)
}

// Workaround to avoid race-conditions on IP reservations for the same VLAN
randomDelay := time.Duration(rand.Intn(1000))
time.Sleep(randomDelay * time.Millisecond)

httpResponse, err := a.client.Do(req)
if err != nil {
return ReserveSpecificSummary{}, fmt.Errorf("could not execute IP address reserve specific post request: %w", err)
}
defer httpResponse.Body.Close()

if httpResponse.StatusCode >= 500 && httpResponse.StatusCode < 600 {
return ReserveSpecificSummary{}, fmt.Errorf("could not execute IP address reserve specific post request, got response %s", httpResponse.Status)
}

var summary ReserveSpecificSummary
err = json.NewDecoder(httpResponse.Body).Decode(&summary)
if err != nil {
return ReserveSpecificSummary{}, fmt.Errorf("could not decode IP address reserve specific post response: %w", err)
}

return summary, nil
}

func (a api) GetFiltered(ctx context.Context, page, limit int, filters ...param.Parameter) ([]Summary, error) {
endpoint, err := url.Parse(a.client.BaseURL())
if err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/ipam/address/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type API interface {
Create(ctx context.Context, create Create) (Summary, error)
Update(ctx context.Context, id string, update Update) (Summary, error)
ReserveRandom(ctx context.Context, reserve ReserveRandom) (ReserveRandomSummary, error)
ReserveSpecific(ctx context.Context, reserve ReserveSpecific) (ReserveSpecificSummary, error)
}

type api struct {
Expand Down

0 comments on commit 7d9711e

Please sign in to comment.