Skip to content

Commit

Permalink
Make Regions Organization Scoped (#31)
Browse files Browse the repository at this point in the history
After playing with the UI, it semms quite apparent that mapping a region
ID to a name, when the region is itself project scoped is quite heavy
weight and unwieldy.  To remedy this we move regions back to the
organization scope so we need only a single lookup, relying on RBAC
information to do any filtering.  This also splits up regions and
instrastructure so readers can map to regions, but not create identities
etc.
  • Loading branch information
spjmurray committed Jul 15, 2024
1 parent e228e66 commit 347e802
Show file tree
Hide file tree
Showing 10 changed files with 440 additions and 547 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ require (
github.com/oapi-codegen/runtime v1.1.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
github.com/unikorn-cloud/core v0.1.59
github.com/unikorn-cloud/core v0.1.60
github.com/unikorn-cloud/identity v0.2.25
go.opentelemetry.io/otel v1.28.0
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.28.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,8 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/unikorn-cloud/core v0.1.59 h1:Fow+RmWADvIHcDGnKxeE+m7uJzq2ARJb1/nPA2tY6+o=
github.com/unikorn-cloud/core v0.1.59/go.mod h1:Cd0zU1LrKo+OwnnCwuTQ+QL3yibnkjDHtkujfDM4AdE=
github.com/unikorn-cloud/core v0.1.60 h1:N/4xkv3dNv8/ZM3VqyxsECm2Ji/gE3QBoLjGsEUQTg4=
github.com/unikorn-cloud/core v0.1.60/go.mod h1:Cd0zU1LrKo+OwnnCwuTQ+QL3yibnkjDHtkujfDM4AdE=
github.com/unikorn-cloud/identity v0.2.25 h1:nb45gnI8o/12idVodWtAVO5WRFW8cTg6PFQHYjLd3DM=
github.com/unikorn-cloud/identity v0.2.25/go.mod h1:8WxgWetyrCvLjRGAeEWy5hWXDJ8prVz+FNt9sG17lV8=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
Expand Down
71 changes: 33 additions & 38 deletions pkg/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import (
"github.com/unikorn-cloud/region/pkg/providers"
"github.com/unikorn-cloud/region/pkg/server/util"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/labels"

"sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -80,8 +80,8 @@ func (h *Handler) setUncacheable(w http.ResponseWriter) {
w.Header().Add("Cache-Control", "no-cache")
}

func (h *Handler) GetApiV1OrganizationsOrganizationIDProjectsProjectIDRegions(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter) {
if err := rbac.AllowProjectScope(r.Context(), "infrastructure", identityapi.Read, organizationID, projectID); err != nil {
func (h *Handler) GetApiV1OrganizationsOrganizationIDRegions(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter) {
if err := rbac.AllowOrganizationScope(r.Context(), "regions", identityapi.Read, organizationID); err != nil {
errors.HandleError(w, r, err)
return
}
Expand Down Expand Up @@ -133,8 +133,8 @@ func convertFlavor(in providers.Flavor) openapi.Flavor {
return out
}

func (h *Handler) GetApiV1OrganizationsOrganizationIDProjectsProjectIDRegionsRegionIDFlavors(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter, regionID openapi.RegionIDParameter) {
if err := rbac.AllowProjectScope(r.Context(), "infrastructure", identityapi.Read, organizationID, projectID); err != nil {
func (h *Handler) GetApiV1OrganizationsOrganizationIDRegionsRegionIDFlavors(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, regionID openapi.RegionIDParameter) {
if err := rbac.AllowOrganizationScope(r.Context(), "regions", identityapi.Read, organizationID); err != nil {
errors.HandleError(w, r, err)
return
}
Expand Down Expand Up @@ -194,8 +194,8 @@ func convertImage(in providers.Image) openapi.Image {
return out
}

func (h *Handler) GetApiV1OrganizationsOrganizationIDProjectsProjectIDRegionsRegionIDImages(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter, regionID openapi.RegionIDParameter) {
if err := rbac.AllowProjectScope(r.Context(), "infrastructure", identityapi.Read, organizationID, projectID); err != nil {
func (h *Handler) GetApiV1OrganizationsOrganizationIDRegionsRegionIDImages(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, regionID openapi.RegionIDParameter) {
if err := rbac.AllowOrganizationScope(r.Context(), "regions", identityapi.Read, organizationID); err != nil {
errors.HandleError(w, r, err)
return
}
Expand Down Expand Up @@ -250,29 +250,12 @@ func convertTags(in unikornv1.TagList) openapi.TagList {
return out
}

func regionScopedResourceReadMetadata(in metav1.Object, status coreapi.ResourceProvisioningStatus) coreapi.RegionScopedResourceMetadata {
labels := in.GetLabels()

temp := conversion.ProjectScopedResourceReadMetadata(in, status)

out := coreapi.RegionScopedResourceMetadata{
Id: temp.Id,
Name: temp.Name,
Description: temp.Description,
CreatedBy: temp.CreatedBy,
CreationTime: temp.CreationTime,
ProvisioningStatus: temp.ProvisioningStatus,
OrganizationId: temp.OrganizationId,
ProjectId: temp.ProjectId,
RegionId: labels[constants.RegionLabel],
}

return out
}

func convertIdentity(identity *unikornv1.Identity, in *providers.CloudConfig) *openapi.IdentityRead {
out := &openapi.IdentityRead{
Metadata: regionScopedResourceReadMetadata(identity, coreapi.ResourceProvisioningStatusProvisioned),
Metadata: conversion.ProjectScopedResourceReadMetadata(identity, coreapi.ResourceProvisioningStatusProvisioned),
Spec: openapi.IdentitySpec{
RegionId: identity.Labels[constants.RegionLabel],
},
}

if tags := convertTags(identity.Spec.Tags); tags != nil {
Expand Down Expand Up @@ -310,7 +293,7 @@ func convertIdentityList(in unikornv1.IdentityList) openapi.IdentitiesRead {
}

func (h *Handler) GetApiV1OrganizationsOrganizationIDIdentities(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter) {
if err := rbac.AllowOrganizationScope(r.Context(), "infrastructure", identityapi.Read, organizationID); err != nil {
if err := rbac.AllowOrganizationScope(r.Context(), "identities", identityapi.Read, organizationID); err != nil {
errors.HandleError(w, r, err)
return
}
Expand All @@ -331,8 +314,8 @@ func (h *Handler) GetApiV1OrganizationsOrganizationIDIdentities(w http.ResponseW
util.WriteJSONResponse(w, r, http.StatusOK, convertIdentityList(resources))
}

func (h *Handler) PostApiV1OrganizationsOrganizationIDProjectsProjectIDRegionsRegionIDIdentities(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter, regionID openapi.RegionIDParameter) {
if err := rbac.AllowProjectScope(r.Context(), "infrastructure", identityapi.Create, organizationID, projectID); err != nil {
func (h *Handler) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentities(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter) {
if err := rbac.AllowProjectScope(r.Context(), "identities", identityapi.Create, organizationID, projectID); err != nil {
errors.HandleError(w, r, err)
return
}
Expand All @@ -344,7 +327,7 @@ func (h *Handler) PostApiV1OrganizationsOrganizationIDProjectsProjectIDRegionsRe
return
}

provider, err := region.NewClient(h.client, h.namespace).Provider(r.Context(), regionID)
provider, err := region.NewClient(h.client, h.namespace).Provider(r.Context(), request.Spec.RegionId)
if err != nil {
errors.HandleError(w, r, err)
return
Expand Down Expand Up @@ -372,8 +355,8 @@ func convertPhysicalNetwork(in *unikornv1.PhysicalNetwork) *openapi.PhysicalNetw
return out
}

func (h *Handler) PostApiV1OrganizationsOrganizationIDProjectsProjectIDRegionsRegionIDIdentitiesIdentityIDPhysicalNetworks(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter, regionID openapi.RegionIDParameter, identityID openapi.IdentityIDParameter) {
if err := rbac.AllowProjectScope(r.Context(), "infrastructure", identityapi.Create, organizationID, projectID); err != nil {
func (h *Handler) PostApiV1OrganizationsOrganizationIDProjectsProjectIDIdentitiesIdentityIDPhysicalNetworks(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter, identityID openapi.IdentityIDParameter) {
if err := rbac.AllowProjectScope(r.Context(), "identities", identityapi.Create, organizationID, projectID); err != nil {
errors.HandleError(w, r, err)
return
}
Expand All @@ -385,13 +368,25 @@ func (h *Handler) PostApiV1OrganizationsOrganizationIDProjectsProjectIDRegionsRe
return
}

provider, err := region.NewClient(h.client, h.namespace).Provider(r.Context(), regionID)
identity := &unikornv1.Identity{}

if err := h.client.Get(r.Context(), client.ObjectKey{Namespace: h.namespace, Name: identityID}, identity); err != nil {
if kerrors.IsNotFound(err) {
errors.HandleError(w, r, errors.HTTPNotFound().WithError(err))
return
}

errors.HandleError(w, r, err)
return
}

provider, err := region.NewClient(h.client, h.namespace).Provider(r.Context(), identity.Labels[constants.RegionLabel])
if err != nil {
errors.HandleError(w, r, err)
return
}

network, err := provider.CreatePhysicalNetwork(r.Context(), organizationID, projectID, identityID, request)
network, err := provider.CreatePhysicalNetwork(r.Context(), identity, request)
if err != nil {
errors.HandleError(w, r, err)
return
Expand Down Expand Up @@ -419,8 +414,8 @@ func convertExternalNetworks(in providers.ExternalNetworks) openapi.ExternalNetw
return out
}

func (h *Handler) GetApiV1OrganizationsOrganizationIDProjectsProjectIDRegionsRegionIDExternalnetworks(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, projectID openapi.ProjectIDParameter, regionID openapi.RegionIDParameter) {
if err := rbac.AllowProjectScope(r.Context(), "infrastructure", identityapi.Read, organizationID, projectID); err != nil {
func (h *Handler) GetApiV1OrganizationsOrganizationIDRegionsRegionIDExternalnetworks(w http.ResponseWriter, r *http.Request, organizationID openapi.OrganizationIDParameter, regionID openapi.RegionIDParameter) {
if err := rbac.AllowOrganizationScope(r.Context(), "regions", identityapi.Read, organizationID); err != nil {
errors.HandleError(w, r, err)
return
}
Expand Down
Loading

0 comments on commit 347e802

Please sign in to comment.