Skip to content

Commit

Permalink
Merge pull request #19 from appuio/feat/users
Browse files Browse the repository at this point in the history
Add User and OrganizationMembers Resources
  • Loading branch information
glrf authored Jan 24, 2022
2 parents 9033637 + ec6e44b commit 616cac5
Show file tree
Hide file tree
Showing 12 changed files with 695 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ clean: ## Cleans up the generated resources
.PHONY: run
KUBECONFIG ?= ~/.kube/config
run: build ## Starts control api against the configured kuberentes cluster
$(BIN_FILENAME) --secure-port 9443 --kubeconfig $(KUBECONFIG) --authentication-kubeconfig $(KUBECONFIG) --authorization-kubeconfig $(KUBECONFIG) --cluster-roles appuio-organization-viewer,appuio-organization-admin
$(BIN_FILENAME) --secure-port 9443 --kubeconfig $(KUBECONFIG) --authentication-kubeconfig $(KUBECONFIG) --authorization-kubeconfig $(KUBECONFIG) --cluster-roles appuio-organization-viewer,appuio-organization-admin --username-prefix "appuio#"

.PHONY: local-env
local-env-setup: ## Setup local kind-based dev environment
Expand Down
47 changes: 47 additions & 0 deletions apis/v1/organizationmembers_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package v1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status

// OrganizationMembers is the collection of members of an organization
type OrganizationMembers struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec OrganizationMembersSpec `json:"spec,omitempty"`
Status OrganizationMembersStatus `json:"status,omitempty"`
}

// OrganizationMembersSpec contains the desired members of the organization
type OrganizationMembersSpec struct {
UserRefs []UserRef `json:"userRefs,omitempty"`
}

// OrganizationMembersStatus contains the actual members of the organization
type OrganizationMembersStatus struct {
ResolvedUserRefs []UserRef `json:"resolvedUserRefs,omitempty"`
}

// UserRef points to a user
type UserRef struct {
ID string `json:"id,omitempty"`
Username string `json:"username,omitempty"`
}

// +kubebuilder:object:root=true

// OrganizationMembersList contains a list of OrganizationMembers resources
type OrganizationMembersList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`

Items []OrganizationMembers `json:"items"`
}

func init() {
SchemeBuilder.Register(&OrganizationMembers{}, &OrganizationMembersList{})
}
50 changes: 50 additions & 0 deletions apis/v1/user_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package v1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// +kubebuilder:object:root=true
// +kubebuilder:resource:scope=Cluster
// +kubebuilder:subresource:status

// User is a representation of a APPUiO Cloud user
type User struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec UserSpec `json:"spec,omitempty"`
Status UserStatus `json:"status,omitempty"`
}

// UserSpec contains the desired state of the user
type UserSpec struct {
Preferences UserPreferences `json:"preferences,omitempty"`
}

// UserPreferences contains the Preferences of the user
type UserPreferences struct {
DefaultOrganizationRef string `json:"defaultOrganizationRef,omitempty"`
}

// UserStatus contains the acutal state of the user
type UserStatus struct {
DefaultOrganizationRef string `json:"defaultOrganization,omitempty"`
DisplayName string `json:"displayName,omitempty"`
Username string `json:"username,omitempty"`
Email string `json:"email,omitempty"`
}

// +kubebuilder:object:root=true

// UserList contains a list of Users.
type UserList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`

Items []User `json:"items"`
}

func init() {
SchemeBuilder.Register(&User{}, &UserList{})
}
219 changes: 219 additions & 0 deletions apis/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions apiserver/organization/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package organization
import (
"context"
"fmt"
"strings"

orgv1 "github.com/appuio/control-api/apis/organization/v1"
controlv1 "github.com/appuio/control-api/apis/v1"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
)

Expand Down Expand Up @@ -45,5 +48,37 @@ func (s *organizationStorage) create(ctx context.Context, org *orgv1.Organizatio
return nil, fmt.Errorf("failed to create organization: %w", err)
}

orgMembers := newOrganizationMembers(ctx, org.Name, s.usernamePrefix)

if err := s.members.CreateMembers(ctx, orgMembers); err != nil {
// rollback
_, deleteErr := s.namepaces.DeleteNamespace(ctx, org.Name, nil)
if deleteErr != nil {
err = fmt.Errorf("%w and failed to clean up namespace: %s", err, deleteErr.Error())
}
return nil, fmt.Errorf("failed to create organization: %w", err)

}

return org, nil
}

func newOrganizationMembers(ctx context.Context, organization, usernamePrefix string) *controlv1.OrganizationMembers {
userRefs := []controlv1.UserRef{}
user, ok := request.UserFrom(ctx)
if ok {
userRefs = append(userRefs, controlv1.UserRef{
ID: strings.TrimPrefix(user.GetName(), usernamePrefix),
})
}

return &controlv1.OrganizationMembers{
ObjectMeta: metav1.ObjectMeta{
Name: "members",
Namespace: organization,
},
Spec: controlv1.OrganizationMembersSpec{
UserRefs: userRefs,
},
}
}
Loading

0 comments on commit 616cac5

Please sign in to comment.