diff --git a/pkg/handler/handler.go b/pkg/handler/handler.go index 8a02272..75ff9fa 100644 --- a/pkg/handler/handler.go +++ b/pkg/handler/handler.go @@ -26,6 +26,7 @@ import ( "slices" "time" + coreconstants "github.com/unikorn-cloud/core/pkg/constants" coreapi "github.com/unikorn-cloud/core/pkg/openapi" "github.com/unikorn-cloud/core/pkg/server/conversion" "github.com/unikorn-cloud/core/pkg/server/errors" @@ -41,6 +42,7 @@ import ( "github.com/unikorn-cloud/region/pkg/server/util" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -277,23 +279,56 @@ func convertIdentity(identity *unikornv1.Identity, in *providers.CloudConfig) *o out.Spec.Tags = &tags } - switch in.Type { - case providers.ProviderTypeOpenStack: - out.Spec = openapi.IdentitySpec{ - Type: openapi.Openstack, - Openstack: &openapi.IdentitySpecOpenStack{ - Cloud: in.OpenStack.Credentials.Cloud, - CloudConfig: base64.URLEncoding.EncodeToString(in.OpenStack.Credentials.CloudConfig), - UserId: in.OpenStack.State.UserID, - ProjectId: in.OpenStack.State.ProjectID, - }, + switch identity.Spec.Provider { + case unikornv1.ProviderOpenstack: + out.Spec.Type = openapi.Openstack + + out.Spec.Openstack = &openapi.IdentitySpecOpenStack{ + UserId: identity.Spec.OpenStack.UserID, + ProjectId: identity.Spec.OpenStack.ProjectID, } + + if in != nil { + cloudConfig := base64.URLEncoding.EncodeToString(in.OpenStack.Credentials.CloudConfig) + + out.Spec.Openstack.Cloud = &in.OpenStack.Credentials.Cloud + out.Spec.Openstack.CloudConfig = &cloudConfig + } + } + + return out +} + +func convertIdentityList(in unikornv1.IdentityList) openapi.IdentitiesRead { + out := make(openapi.IdentitiesRead, len(in.Items)) + + for i := range in.Items { + out[i] = *convertIdentity(&in.Items[i], nil) } return out } 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 { + errors.HandleError(w, r, err) + return + } + + var resources unikornv1.IdentityList + + options := &client.ListOptions{ + LabelSelector: labels.SelectorFromSet(map[string]string{ + coreconstants.OrganizationLabel: organizationID, + }), + } + + if err := h.client.List(r.Context(), &resources, options); err != nil { + errors.HandleError(w, r, errors.OAuth2ServerError("unable to list identities").WithError(err)) + return + } + + 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) { diff --git a/pkg/openapi/schema.go b/pkg/openapi/schema.go index 3e6dd1f..fd72ea2 100644 --- a/pkg/openapi/schema.go +++ b/pkg/openapi/schema.go @@ -63,45 +63,45 @@ var swaggerSpec = []string{ "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", - "/02JOzZaXQAA", + "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", + "RF0AAA==", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/pkg/openapi/server.spec.yaml b/pkg/openapi/server.spec.yaml index a899c28..5e78638 100644 --- a/pkg/openapi/server.spec.yaml +++ b/pkg/openapi/server.spec.yaml @@ -381,8 +381,6 @@ components: description: Everything an OpenStack client needs to function. type: object required: - - cloud - - cloudConfig - userId - projectId properties: diff --git a/pkg/openapi/types.go b/pkg/openapi/types.go index 565e033..8008a2a 100644 --- a/pkg/openapi/types.go +++ b/pkg/openapi/types.go @@ -123,10 +123,10 @@ type IdentitySpec struct { // IdentitySpecOpenStack Everything an OpenStack client needs to function. type IdentitySpecOpenStack struct { // Cloud The name of the cloud in the cloud config. - Cloud string `json:"cloud"` + Cloud *string `json:"cloud,omitempty"` // CloudConfig A base64 encoded cloud config file. - CloudConfig string `json:"cloudConfig"` + CloudConfig *string `json:"cloudConfig,omitempty"` // ProjectId Project identifier allocated for the infrastructure. ProjectId string `json:"projectId"`