Skip to content

Commit

Permalink
Merge pull request #14 from mbarnes/api-updates
Browse files Browse the repository at this point in the history
Create the API Definitions as Structs in the API Component
  • Loading branch information
s-amann authored Apr 4, 2024
2 parents 0aad68c + 7f0f522 commit 56bafb4
Show file tree
Hide file tree
Showing 14 changed files with 1,012 additions and 107 deletions.
8 changes: 4 additions & 4 deletions frontend/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,22 @@ package main
import "github.com/Azure/ARO-HCP/internal/api"

type cache struct {
cluster map[string]api.HCPOpenShiftCluster
cluster map[string]*api.HCPOpenShiftCluster
}

// NewCache returns a new cache.
func NewCache() *cache {
return &cache{
cluster: make(map[string]api.HCPOpenShiftCluster),
cluster: make(map[string]*api.HCPOpenShiftCluster),
}
}

func (c *cache) GetCluster(id string) (api.HCPOpenShiftCluster, bool) {
func (c *cache) GetCluster(id string) (*api.HCPOpenShiftCluster, bool) {
cluster, found := c.cluster[id]
return cluster, found
}

func (c *cache) SetCluster(id string, cluster api.HCPOpenShiftCluster) {
func (c *cache) SetCluster(id string, cluster *api.HCPOpenShiftCluster) {
c.cluster[id] = cluster
}

Expand Down
38 changes: 20 additions & 18 deletions frontend/frontend.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,16 +180,18 @@ func (f *Frontend) ArmResourceListByResourceGroup(writer http.ResponseWriter, re
func (f *Frontend) ArmResourceRead(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()
logger := ctx.Value(ContextKeyLogger).(*slog.Logger)
versionedInterface, _ := ctx.Value(ContextKeyVersion).(api.Version)
versionedInterface := ctx.Value(ContextKeyVersion).(api.Version)
logger.Info(fmt.Sprintf("%s: ArmResourceRead", versionedInterface))

resourceID := strings.ToLower(request.URL.Path)
// URL path is already lowercased by middleware.
resourceID := request.URL.Path
cluster, found := f.cache.GetCluster(resourceID)
if !found {
writer.WriteHeader(http.StatusNotFound)
return
}
resp, err := json.Marshal(cluster)
versionedResource := versionedInterface.NewHCPOpenShiftCluster(cluster)
resp, err := json.Marshal(versionedResource)
if err != nil {
f.logger.Error(err.Error())
writer.WriteHeader(http.StatusInternalServerError)
Expand All @@ -205,18 +207,26 @@ func (f *Frontend) ArmResourceRead(writer http.ResponseWriter, request *http.Req
func (f *Frontend) ArmResourceCreateOrUpdate(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()
logger := ctx.Value(ContextKeyLogger).(*slog.Logger)
versionedInterface, _ := ctx.Value(ContextKeyVersion).(api.Version)
versionedInterface := ctx.Value(ContextKeyVersion).(api.Version)

logger.Info(fmt.Sprintf("%s: ArmResourceCreateOrUpdate", versionedInterface))
resourceID := strings.ToLower(request.URL.Path)
cluster, err := clusterFromRequest(ctx.Value(ContextKeyBody).([]byte))

// URL path is already lowercased by middleware.
resourceID := request.URL.Path
cluster, updating := f.cache.GetCluster(resourceID)
if !updating {
cluster = api.NewDefaultHCPOpenShiftCluster()
}
body := ctx.Value(ContextKeyBody).([]byte)
err := versionedInterface.UnmarshalHCPOpenShiftCluster(body, updating, cluster)
if err != nil {
f.logger.Error(err.Error())
writer.WriteHeader(http.StatusBadRequest)
}
f.cache.SetCluster(resourceID, cluster)

resp, err := json.Marshal(cluster)
versionedResource := versionedInterface.NewHCPOpenShiftCluster(cluster)
resp, err := json.Marshal(versionedResource)
if err != nil {
f.logger.Error(err.Error())
writer.WriteHeader(http.StatusInternalServerError)
Expand All @@ -242,10 +252,11 @@ func (f *Frontend) ArmResourcePatch(writer http.ResponseWriter, request *http.Re
func (f *Frontend) ArmResourceDelete(writer http.ResponseWriter, request *http.Request) {
ctx := request.Context()
logger := ctx.Value(ContextKeyLogger).(*slog.Logger)
versionedInterface, _ := ctx.Value(ContextKeyVersion).(api.Version)
versionedInterface := ctx.Value(ContextKeyVersion).(api.Version)
logger.Info(fmt.Sprintf("%s: ArmResourceDelete", versionedInterface))

resourceID := strings.ToLower(request.URL.Path)
// URL path is already lowercased by middleware.
resourceID := request.URL.Path
_, found := f.cache.GetCluster(resourceID)
if !found {
writer.WriteHeader(http.StatusNotFound)
Expand All @@ -265,12 +276,3 @@ func (f *Frontend) ArmResourceAction(writer http.ResponseWriter, request *http.R

writer.WriteHeader(http.StatusOK)
}

func clusterFromRequest(body []byte) (api.HCPOpenShiftCluster, error) {
var cluster api.HCPOpenShiftCluster
err := json.Unmarshal(body, &cluster)
if err != nil {
return api.HCPOpenShiftCluster{}, err
}
return cluster, nil
}
4 changes: 0 additions & 4 deletions frontend/middleware_validateapi.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package main
import (
"context"
"net/http"
"strings"

"github.com/Azure/ARO-HCP/internal/api"
"github.com/Azure/ARO-HCP/internal/api/arm"
Expand All @@ -20,9 +19,6 @@ func MiddlewareValidateAPIVersion(w http.ResponseWriter, r *http.Request, next h
arm.CloudErrorCodeInvalidParameter, "",
"The request is missing required parameter '%s'.",
APIVersionKey)
} else if strings.EqualFold(apiVersion, "cache") {
r = r.WithContext(context.WithValue(r.Context(), ContextKeyVersion, "cache"))
next(w, r)
} else if version, ok := api.Lookup(apiVersion); !ok {
arm.WriteError(
w, http.StatusBadRequest,
Expand Down
19 changes: 19 additions & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
40 changes: 40 additions & 0 deletions internal/api/enums.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,46 @@ package api

import "fmt"

// NetworkType represents an OpenShift cluster network plugin.
type NetworkType int

const (
NetworkTypeOpenShiftSDN NetworkType = iota
NetworkTypeOVNKubernetes

NetworkTypeOther // catch-all, must be last
)

func (v NetworkType) String() string {
switch v {
case NetworkTypeOpenShiftSDN:
return "OpenShiftSDN"
case NetworkTypeOVNKubernetes:
return "OVNKubernetes"
default:
return "Other"
}
}

func (v NetworkType) MarshalText() (text []byte, err error) {
// NetworkTypeOther is a catch-all value.
text = []byte(v.String())
return
}

func (v *NetworkType) UnmarshalText(text []byte) error {
for i := range NetworkTypeOther {
if i.String() == string(text) {
*v = i
return nil
}
}

// NetworkTypeOther is a catch-all value.
*v = NetworkTypeOther
return nil
}

// OutboundType represents a routing strategy to provide egress to the Internet.
type OutboundType int

Expand Down
65 changes: 65 additions & 0 deletions internal/api/enums_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,71 @@ import (
"testing"
)

func TestNetworkType(t *testing.T) {
// Ensure NetworkType implementes these interfaces
var i NetworkType
_ = fmt.Stringer(i)
_ = encoding.TextMarshaler(i)
_ = encoding.TextUnmarshaler(&i)

for _, tt := range []struct {
name string
val int
str string
skipMarshal bool
skipUnmarshal bool
}{
{
name: "NetworkTypeOpenShiftSDN",
val: int(NetworkTypeOpenShiftSDN),
str: fmt.Sprintf("%q", NetworkTypeOpenShiftSDN),
},
{
name: "NetworkTypeOVNKubernetes",
val: int(NetworkTypeOVNKubernetes),
str: fmt.Sprintf("%q", NetworkTypeOVNKubernetes),
},
{
name: "NetworkTypeOther",
val: int(NetworkTypeOther),
str: fmt.Sprintf("%q", NetworkTypeOther),
},
{
name: "Unknown NetworkType string",
val: int(NetworkTypeOther),
str: "\"unknown\"",
skipMarshal: true,
},
{
name: "Unknown NetworkType value",
val: -1,
str: fmt.Sprintf("%q", NetworkTypeOther),
skipUnmarshal: true,
},
} {
if !tt.skipMarshal {
t.Logf("Marshaling %d", tt.val)
data, err := json.Marshal(NetworkType(tt.val))
if err != nil {
t.Fatalf("Marshal: Unexpected error: %s", err)
} else if string(data) != tt.str {
t.Fatalf("Marshal: Expected %s, got %s", tt.str, string(data))
}
}

if !tt.skipUnmarshal {
var val NetworkType
t.Logf("Unmarshaling %s", tt.str)
err := json.Unmarshal([]byte(tt.str), &val)
if err != nil {
t.Fatalf("Unmarshal: Unexpected error: %s", err)
} else if int(val) != tt.val {
t.Fatalf("Unmarshal: Expected %d, got %d", tt.val, val)
}
}
}
}

func TestOutboundType(t *testing.T) {
// Ensure OutboundType implements these interfaces
var i OutboundType
Expand Down
Loading

0 comments on commit 56bafb4

Please sign in to comment.