Skip to content

Commit

Permalink
Add user management
Browse files Browse the repository at this point in the history
With this commit the provider is able to manage users as well. The
users can't yet do anything as a user without any policy has no
permissions at all.
  • Loading branch information
Kidswiss committed Aug 30, 2023
1 parent 1fbe956 commit 1a4399d
Show file tree
Hide file tree
Showing 28 changed files with 1,371 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
/package/*.xpkg
/package/crossplane.yaml
/kubeconfig
__debug*

# Docs
/.cache/
Expand Down
19 changes: 9 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -125,13 +125,12 @@ webhook_service_name = host.docker.internal

webhook-debug: $(webhook_cert) ## Creates certificates, patches the webhook registrations and applies everything to the given kube cluster
webhook-debug:
#
# kubectl -n syn-appcat scale deployment appcat-controller --replicas 0
# cabundle=$$(cat .work/webhook/tls.crt | base64) && \
# HOSTIP=$(webhook_service_name) && \
# kubectl annotate validatingwebhookconfigurations.admissionregistration.k8s.io appcat-pg-validation cert-manager.io/inject-ca-from- && \
# kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io appcat-pg-validation -oyaml | \
# yq e "del(.webhooks[0].clientConfig.service) | .webhooks[0].clientConfig.caBundle |= \"$$cabundle\" | .webhooks[0].clientConfig.url |= \"https://$$HOSTIP:9443/validate-vshn-appcat-vshn-io-v1-vshnpostgresql\"" - | \
# kubectl apply -f - && \
# kubectl annotate validatingwebhookconfigurations.admissionregistration.k8s.io appcat-redis-validation cert-manager.io/inject-ca-from- && \
# kubectl annotate validatingwebhookconfigurations.admissionregistration.k8s.io appcat-pg-validation kubectl.kubernetes.io/last-applied-configuration- && \
kubectl apply -f package/webhook
cabundle=$$(cat .work/webhook/tls.crt | base64) && \
HOSTIP=$(webhook_service_name) && \
kubectl annotate validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration cert-manager.io/inject-ca-from- && \
kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration -oyaml | \
yq e "del(.webhooks[0].clientConfig.service) | .webhooks[0].clientConfig.caBundle |= \"$$cabundle\" | .webhooks[0].clientConfig.url |= \"https://$$HOSTIP:9443//validate-minio-crossplane-io-v1-bucket\"" - | \
yq e "del(.webhooks[1].clientConfig.service) | .webhooks[1].clientConfig.caBundle |= \"$$cabundle\" | .webhooks[1].clientConfig.url |= \"https://$$HOSTIP:9443//validate-minio-crossplane-io-v1-user\"" - | \
kubectl apply -f - && \
kubectl annotate validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration kubectl.kubernetes.io/last-applied-configuration-
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,6 @@ To execute tests, run `make test-e2e` from the root dir.
If a test fails, kuttl leaves the resources in the kind-cluster intact, so you can inspect the resources and events if necessary.
Please note that Kubernetes Events from cluster-scoped resources appear in the `default` namespace only, but `kubectl describe ...` should show you the events.

If tests succeed, the relevant resources are deleted to not use up costs on the cloud providers.

### Cleaning up e2e tests

`make clean`
78 changes: 78 additions & 0 deletions apis/minio/v1/user_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package v1

import (
"reflect"

xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
)

func init() {
SchemeBuilder.Register(&User{}, &UserList{})
}

// +kubebuilder:object:root=true
// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status"
// +kubebuilder:printcolumn:name="Synced",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status"
// +kubebuilder:printcolumn:name="External Name",type="string",JSONPath=".metadata.annotations.crossplane\\.io/external-name"
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Cluster,categories={crossplane,minio}
// +kubebuilder:webhook:verbs=create;update,path=/validate-minio-crossplane-io-v1-user,mutating=false,failurePolicy=fail,groups=minio.crossplane.io,resources=users,versions=v1,name=users.minio.crossplane.io,sideEffects=None,admissionReviewVersions=v1

type User struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

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

type UserSpec struct {
xpv1.ResourceSpec `json:",inline"`
ForProvider UserParameters `json:"forProvider,omitempty"`
}

type UserStatus struct {
xpv1.ResourceStatus `json:",inline"`
AtProvider UserProviderStatus `json:"atProvider,omitempty"`
}

type UserProviderStatus struct {
// UserName is populated it the user actually exists in minio during observe.
UserName string `json:"userName,omitempty"`
// Status indicates the user's status on the minio instance.
Status string `json:"status,omitempty"`
}

type UserParameters struct {
// UserName is the name of the user to create.
// Defaults to `metadata.name` if unset.
// Cannot be changed after user is created.
UserName string `json:"userName,omitempty"`
}

// +kubebuilder:object:root=true

type UserList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []User `json:"items"`
}

// GetUserName returns the spec.forProvider.userName if given, otherwise defaults to metadata.name.
func (in *User) GetUserName() string {
if in.Spec.ForProvider.UserName == "" {
return in.Name
}
return in.Spec.ForProvider.UserName
}

// Dummy type metadata.
var (
UserKind = reflect.TypeOf(User{}).Name()
UserGroupKind = schema.GroupKind{Group: Group, Kind: UserKind}.String()
UserKindAPIVersion = UserKind + "." + SchemeGroupVersion.String()
UserGroupVersionKind = SchemeGroupVersion.WithKind(UserKind)
)
123 changes: 123 additions & 0 deletions apis/minio/v1/zz_generated.deepcopy.go

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

76 changes: 76 additions & 0 deletions apis/minio/v1/zz_generated.managed.go

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

9 changes: 9 additions & 0 deletions apis/minio/v1/zz_generated.managedlist.go

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

27 changes: 27 additions & 0 deletions generate_sample.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func main() {
generateBucketSample()
generateProviderConfigSample()
generateSecretSample()
generateUserSample()
}

func generateBucketSample() {
Expand Down Expand Up @@ -110,6 +111,32 @@ func newSecretSample() *corev1.Secret {
}
}

func generateUserSample() {
spec := newUserSample()
serialize(spec, true)
}

func newUserSample() *miniov1.User {
return &miniov1.User{
TypeMeta: metav1.TypeMeta{
APIVersion: miniov1.UserGroupVersionKind.GroupVersion().String(),
Kind: miniov1.UserKind,
},
ObjectMeta: metav1.ObjectMeta{
Name: "devuser",
},
Spec: miniov1.UserSpec{
ResourceSpec: xpv1.ResourceSpec{
ProviderConfigReference: &xpv1.Reference{Name: "provider-config"},
WriteConnectionSecretToReference: &xpv1.SecretReference{
Name: "devuser",
Namespace: "default",
},
},
},
}
}

func failIfError(err error) {
if err != nil {
log.Fatal(err)
Expand Down
Loading

0 comments on commit 1a4399d

Please sign in to comment.