diff --git a/.github/workflows/build-and-publish.yml b/.github/workflows/build-and-publish.yml index c80fe2e..e1f3fc0 100644 --- a/.github/workflows/build-and-publish.yml +++ b/.github/workflows/build-and-publish.yml @@ -15,6 +15,11 @@ jobs: name: Build Docker image and push to repositories # run only when code is compiling and tests are passing runs-on: ubuntu-latest + + permissions: + contents: read + id-token: write + packages: write # steps to perform in job steps: @@ -51,7 +56,7 @@ jobs: uses: docker/build-push-action@v2 with: platforms: linux/amd64,linux/arm64 - tags: ghcr.io/syngit-org/syngit:${{ env.tag }} + tags: ghcr.io/${{ github.repository }}:${{ env.tag }} push: ${{ github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/') }} - name: Image digest diff --git a/PROJECT b/PROJECT index 0c71555..d182da6 100644 --- a/PROJECT +++ b/PROJECT @@ -71,4 +71,34 @@ resources: webhooks: validation: true webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: syngit.io + group: syngit + kind: RemoteSyncer + path: syngit.io/syngit/api/v3alpha3 + version: v3alpha3 + webhooks: + validation: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: syngit.io + group: syngit + kind: RemoteUser + path: syngit.io/syngit/api/v3alpha3 + version: v3alpha3 + webhooks: + validation: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: syngit.io + group: syngit + kind: RemoteUserBinding + path: syngit.io/syngit/api/v3alpha3 + version: v3alpha3 version: "3" diff --git a/README.md b/README.md index 8da0813..c773762 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ # syngit -syngit is a Kubernetes operator that allows you to push resources on a git repository. It leverage the gitops by unifying the source of truth between your cluster and your git repository. It acts as a proxy between your client tool (`kubectl` or any UI) and the cluster. +syngit is a Kubernetes operator that allows you to push resources on a git repository and manage their lifecycle. It leverage the gitops by unifying the source of truth between your cluster and your git repository. It acts as a proxy between your client tool (`kubectl` or any UI) and the cluster. ![syngit-proxy](./img/wiki/conception/commitonly-proxy.png) @@ -70,7 +70,7 @@ stringData: ``` ```yaml -apiVersion: syngit.syngit.io/v2alpha2 +apiVersion: syngit.syngit.io/v3alpha3 kind: RemoteUser metadata: name: remoteuser-sample @@ -108,7 +108,7 @@ The RemoteSyncer object contains the whole logic part of the operator. In this example, the RemoteSyncer will intercept all the *configmaps*. It will push them to *https://github.com/my_repo_path.git* in the branch *main* under the path `my_configmaps/`. Because the `commitProcess` is set to `CommitApply`, the changes will be pushed and then applied to the cluster. ```yaml -apiVersion: syngit.syngit.io/v2alpha2 +apiVersion: syngit.syngit.io/v3alpha3 kind: RemoteSyncer metadata: name: remotesyncer-sample @@ -118,8 +118,6 @@ spec: branch: main rootPath: "root-folder" commitProcess: CommitApply - authorizedUsers: - - name: owned-rub-kubernetes- defaultUnauthorizedUserMode: Block excludedFields: - metadata.managedFields @@ -159,7 +157,7 @@ Using the `CommitApply` mode, the automatic reconciliation will not have any eff **What if the connection with my git repository does not work?** -As explained [here](https://github.com/syngit-org/syngit/wiki/Contribute), by default, the webhook logic will first try to commit & push and then apply the changes to the cluster. If, for any reason, the resource has not been pushed, the resource will not be applied. Therefore, the GitOps philosophy is not broken. +As explained [here](https://github.com/syngit-org/syngit/wiki/Architecture), by default, the webhook logic will first try to commit & push and then apply the changes to the cluster. If, for any reason, the resource has not been pushed, the resource will not be applied. Therefore, the GitOps philosophy is not broken. ## Wiki diff --git a/api/v2alpha2/remotesyncer_types.go b/api/v2alpha2/remotesyncer_types.go index 4f5482c..5d21547 100644 --- a/api/v2alpha2/remotesyncer_types.go +++ b/api/v2alpha2/remotesyncer_types.go @@ -78,7 +78,6 @@ type RemoteSyncerStatus struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status -//+kubebuilder:storageversion // RemoteSyncer is the Schema for the remotesyncers API type RemoteSyncer struct { diff --git a/api/v2alpha2/remotesyncer_webhook.go b/api/v2alpha2/remotesyncer_webhook.go index fcb20a8..216fe6b 100644 --- a/api/v2alpha2/remotesyncer_webhook.go +++ b/api/v2alpha2/remotesyncer_webhook.go @@ -39,8 +39,6 @@ func (r *RemoteSyncer) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } -//+kubebuilder:webhook:path=/validate-syngit-syngit-io-v2alpha2-remotesyncer,mutating=false,failurePolicy=fail,sideEffects=None,groups=syngit.syngit.io,resources=remotesyncers,verbs=create;update,versions=v2alpha2,name=vremotesyncer.kb.io,admissionReviewVersions=v1 - var _ webhook.Validator = &RemoteSyncer{} // Validate validates the RemoteSyncerSpec diff --git a/api/v2alpha2/remoteuser_types.go b/api/v2alpha2/remoteuser_types.go index a5c9ace..3c406eb 100644 --- a/api/v2alpha2/remoteuser_types.go +++ b/api/v2alpha2/remoteuser_types.go @@ -67,7 +67,6 @@ type RemoteUserStatus struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status -//+kubebuilder:storageversion // RemoteUser is the Schema for the remoteusers API type RemoteUser struct { diff --git a/api/v2alpha2/remoteuser_webhook.go b/api/v2alpha2/remoteuser_webhook.go index 781b604..5c87b9f 100644 --- a/api/v2alpha2/remoteuser_webhook.go +++ b/api/v2alpha2/remoteuser_webhook.go @@ -36,9 +36,6 @@ func (r *RemoteUser) SetupWebhookWithManager(mgr ctrl.Manager) error { Complete() } -//+kubebuilder:webhook:path=/validate-syngit-syngit-io-v2alpha2-remoteuser,mutating=false,failurePolicy=fail,sideEffects=None,groups=syngit.syngit.io,resources=remoteusers,verbs=create;update,versions=v2alpha2,name=vremoteuser.kb.io,admissionReviewVersions=v1 -//+kubebuilder:webhook:path=/reconcile-syngit-remoteuser-owner,mutating=false,failurePolicy=fail,sideEffects=None,groups=syngit.syngit.io,resources=remoteusers,verbs=create;delete,versions=v2alpha2,admissionReviewVersions=v1,name=vremoteusers-owner.kb.io - var _ webhook.Validator = &RemoteUser{} // Validate validates the RemoteUserSpec diff --git a/api/v2alpha2/remoteuserbinding_types.go b/api/v2alpha2/remoteuserbinding_types.go index 1af6888..84d6b68 100644 --- a/api/v2alpha2/remoteuserbinding_types.go +++ b/api/v2alpha2/remoteuserbinding_types.go @@ -47,7 +47,6 @@ type RemoteUserBindingStatus struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status -//+kubebuilder:storageversion // RemoteUserBinding is the Schema for the remoteuserbindings API type RemoteUserBinding struct { diff --git a/api/v3alpha3/groupversion_info.go b/api/v3alpha3/groupversion_info.go new file mode 100644 index 0000000..eb95f72 --- /dev/null +++ b/api/v3alpha3/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v3alpha3 contains API Schema definitions for the syngit v3alpha3 API group +// +kubebuilder:object:generate=true +// +groupName=syngit.syngit.io +package v3alpha3 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "syngit.syngit.io", Version: "v3alpha3"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v3alpha3/remotesyncer_types.go b/api/v3alpha3/remotesyncer_types.go new file mode 100644 index 0000000..d3ba4c4 --- /dev/null +++ b/api/v3alpha3/remotesyncer_types.go @@ -0,0 +1,225 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3alpha3 + +import ( + admissionv1 "k8s.io/api/admissionregistration/v1" + authenticationv1 "k8s.io/api/authentication/v1" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +type RemoteSyncerSpec struct { + CommitProcess CommitProcess `json:"commitProcess"` + + // +optional + DefaultBlockAppliedMessage string `json:"defaultBlockAppliedMessage"` + + // +kubebuilder:validation:Format=uri + RemoteRepository string `json:"remoteRepository"` + + Branch string `json:"branch"` + + // +optional + BypassInterceptionSubjects []rbacv1.Subject `json:"bypassInterceptionSubjects,omitempty"` + + DefaultUnauthorizedUserMode DefaultUnauthorizedUserMode `json:"defaultUnauthorizedUserMode"` + + // +optional + DefaultUser *corev1.ObjectReference `json:"defaultUser,omitempty"` // Ref to a RemoteUser object + + // +optional + ScopedResources ScopedResources `json:"scopedResources,omitempty"` + + // +optional + RootPath string `json:"rootPath,omitempty"` + + // +optional + ExcludedFields []string `json:"excludedFields,omitempty"` + + // +optional + ExcludedFieldsConfig *corev1.ObjectReference `json:"excludedFieldsConfig,omitempty"` // Ref to a ConfigMap +} + +type RemoteSyncerStatus struct { + + // +listType=map + // +listMapKey=type + // +patchStrategy=merge + // +patchMergeKey=type + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` + + // +optional + LastBypassedObjectState LastBypassedObjectState `json:"lastBypassedObjectState,omitempty"` + + // +optional + LastObservedObjectState LastObservedObjectState `json:"lastObservedObjectState,omitempty"` + + // +optional + LastPushedObjectState LastPushedObjectState `json:"lastPushedObjectState,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:storageversion + +// RemoteSyncer is the Schema for the remotesyncers API +type RemoteSyncer struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RemoteSyncerSpec `json:"spec,omitempty"` + Status RemoteSyncerStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// RemoteSyncerList contains a list of RemoteSyncer +type RemoteSyncerList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []RemoteSyncer `json:"items"` +} + +func init() { + SchemeBuilder.Register(&RemoteSyncer{}, &RemoteSyncerList{}) +} + +/* + SPEC EXTENSION +*/ + +type CommitMode string + +const ( + Commit CommitMode = "Commit" + MergeRequest CommitMode = "MergeRequest" +) + +type CommitProcess string + +const ( + CommitOnly CommitProcess = "CommitOnly" + CommitApply CommitProcess = "CommitApply" +) + +type DefaultUnauthorizedUserMode string + +const ( + Block DefaultUnauthorizedUserMode = "Block" + UseDefaultUser DefaultUnauthorizedUserMode = "UseDefaultUser" +) + +type ScopedResources struct { + + // +optional + MatchPolicy *admissionv1.MatchPolicyType `json:"matchPolicy,omitempty" protobuf:"bytes,9,opt,name=matchPolicy,casttype=MatchPolicyType"` + + // +optional + ObjectSelector *metav1.LabelSelector `json:"objectSelector,omitempty" protobuf:"bytes,10,opt,name=objectSelector"` + + Rules []admissionv1.RuleWithOperations `json:"rules,omitempty" protobuf:"bytes,3,rep,name=rules"` +} + +type NamespaceScopedResources struct { + APIGroups []string `json:"apiGroups"` + APIVersions []string `json:"apiVersions"` + Resources []string `json:"resources"` + // +optional + Names []string `json:"names"` +} + +type NamespaceScopedKinds struct { + APIGroups []string `json:"apiGroups"` + APIVersions []string `json:"apiVersions"` + Kinds []string `json:"kinds"` + // +optional + Names []string `json:"names"` +} + +/* + SPEC CONVERTION EXTENSION +*/ + +type GroupVersionKindName struct { + *schema.GroupVersionKind + Name string +} + +type GroupVersionResourceName struct { + *schema.GroupVersionResource + Name string +} + +/* +STATUS EXTENSION +*/ + +type JsonGVRN struct { + Group string `json:"group"` + Version string `json:"version"` + Resource string `json:"resource"` + Name string `json:"name"` +} + +type LastBypassedObjectState struct { + // +optional + LastBypassedObjectTime metav1.Time `json:"lastBypassObjectTime,omitempty"` + + // +optional + LastBypassedObjectUserInfo authenticationv1.UserInfo `json:"lastBypassObjectUserInfo,omitempty"` + + // +optional + LastBypassedObject JsonGVRN `json:"lastBypassObject,omitempty"` +} + +type LastObservedObjectState struct { + // +optional + LastObservedObjectTime metav1.Time `json:"lastObservedObjectTime,omitempty"` + + // +optional + LastObservedObjectUserInfo authenticationv1.UserInfo `json:"lastObservedObjectUserInfo,omitempty"` + + // +optional + LastObservedObject JsonGVRN `json:"lastObservedObject,omitempty"` +} + +type LastPushedObjectState struct { + // +optional + LastPushedObjectTime metav1.Time `json:"lastPushedObjectTime,omitempty"` + + // +optional + LastPushedGitUser string `json:"lastPushedGitUser,omitempty"` + + // +optional + LastPushedObjectGitRepo string `json:"lastPushedObjectGitRepo,omitempty"` + + // +optional + LastPushedObjectGitPath string `json:"lastPushedObjectGitPath,omitempty"` + + // +optional + LastPushedObjectGitCommitHash string `json:"lastPushedObjectCommitHash,omitempty"` + + // +optional + LastPushedObject JsonGVRN `json:"lastPushedObject,omitempty"` + + // +optional + LastPushedObjectStatus string `json:"lastPushedObjectState,omitempty"` +} diff --git a/api/v3alpha3/remotesyncer_webhook.go b/api/v3alpha3/remotesyncer_webhook.go new file mode 100644 index 0000000..4374f30 --- /dev/null +++ b/api/v3alpha3/remotesyncer_webhook.go @@ -0,0 +1,138 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3alpha3 + +import ( + "regexp" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var remotesyncerlog = logf.Log.WithName("remotesyncer-resource") + +// SetupWebhookWithManager will setup the manager to manage the webhooks +func (r *RemoteSyncer) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-syngit-syngit-io-v3alpha3-remotesyncer,mutating=false,failurePolicy=fail,sideEffects=None,groups=syngit.syngit.io,resources=remotesyncers,verbs=create;update,versions=v3alpha3,name=vremotesyncer.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &RemoteSyncer{} + +// Validate validates the RemoteSyncerSpec +func (r *RemoteSyncerSpec) ValidateRemoteSyncerSpec() field.ErrorList { + var errors field.ErrorList + + // Validate DefaultUserBind based on DefaultUnauthorizedUserMode + if r.DefaultUnauthorizedUserMode == Block && r.DefaultUser != nil { + errors = append(errors, field.Invalid(field.NewPath("spec").Child("defaultUser"), r.DefaultUser, "should not be set when defaultUnauthorizedUserMode is set to \"Block\"")) + } else if r.DefaultUnauthorizedUserMode == UseDefaultUser && r.DefaultUser == nil { + errors = append(errors, field.Required(field.NewPath("spec").Child("defaultUser"), "should be set when defaultUnauthorizedUserMode is set to \"UseDefaultUser\"")) + } + + // Validate DefaultBlockAppliedMessage only exists if CommitProcess is set to ApplyCommit + if r.DefaultBlockAppliedMessage != "" && r.CommitProcess != "CommitApply" { + errors = append(errors, field.Forbidden(field.NewPath("spec").Child("defaultBlockAppliedMessage"), "should not be set if .spec.commitProcess is not set to \"CommitApply\"")) + } + + // Validate that CommitProcess is either CommitApply or CommitOnly + if r.CommitProcess != "CommitOnly" && r.CommitProcess != "CommitApply" { + errors = append(errors, field.Invalid(field.NewPath("spec").Child("commitProcess"), r.CommitProcess, "should be set to \"CommitApply\" or \"CommitOnly\"")) + } + + // Validate Git URI + gitURIPattern := regexp.MustCompile(`^(https?|git|ssh|ftps?|rsync)\://[^ ]+$`) + if !gitURIPattern.MatchString(r.RemoteRepository) { + errors = append(errors, field.Invalid(field.NewPath("spec").Child("remoteRepository"), r.RemoteRepository, "invalid Git URI")) + } + + // Validate the ExcludedFields to ensure that it is a YAML path + for _, fieldPath := range r.ExcludedFields { + if !isValidYAMLPath(fieldPath) { + errors = append(errors, field.Invalid(field.NewPath("spec").Child("excludedFields"), fieldPath, "must be a valid YAML path. Regex : "+`^([a-zA-Z0-9_./:-]*(\[[a-zA-Z0-9_*./:-]*\])?)*$`)) + } + } + + return errors +} + +// isValidYAMLPath checks if the given string is a valid YAML path +func isValidYAMLPath(path string) bool { + // Regular expression to match a valid YAML path + yamlPathRegex := regexp.MustCompile(`^([a-zA-Z0-9_./:-]*(\[[a-zA-Z0-9_*./:-]*\])?)*$`) + return yamlPathRegex.MatchString(path) +} + +func (r *RemoteSyncerSpec) searchForDuplicates(gvrns []GroupVersionResourceName) []*schema.GroupVersionResource { + seen := make(map[string]bool) + duplicates := make([]*schema.GroupVersionResource, 0) + + for _, item := range gvrns { + if _, ok := seen[item.GroupVersionResource.String()]; ok { + duplicates = append(duplicates, item.GroupVersionResource) + } + seen[item.GroupVersionResource.String()] = true + } + + return duplicates +} + +func (r *RemoteSyncer) ValidateRemoteSyncer() error { + var allErrs field.ErrorList + if err := r.Spec.ValidateRemoteSyncerSpec(); err != nil { + allErrs = append(allErrs, err...) + } + if len(allErrs) == 0 { + return nil + } + + return apierrors.NewInvalid( + r.GroupVersionKind().GroupKind(), + r.Name, allErrs) +} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *RemoteSyncer) ValidateCreate() (admission.Warnings, error) { + remotesyncerlog.Info("validate create", "name", r.Name) + + return nil, r.ValidateRemoteSyncer() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *RemoteSyncer) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + remotesyncerlog.Info("validate update", "name", r.Name) + + return nil, r.ValidateRemoteSyncer() +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *RemoteSyncer) ValidateDelete() (admission.Warnings, error) { + remotesyncerlog.Info("validate delete", "name", r.Name) + + // Nothing to validate + return nil, nil +} diff --git a/api/v3alpha3/remotesyncer_webhook_test.go b/api/v3alpha3/remotesyncer_webhook_test.go new file mode 100644 index 0000000..2b17c68 --- /dev/null +++ b/api/v3alpha3/remotesyncer_webhook_test.go @@ -0,0 +1,39 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3alpha3 + +import ( + . "github.com/onsi/ginkgo/v2" +) + +var _ = Describe("RemoteSyncer Webhook", func() { + + Context("When creating RemoteSyncer under Validating Webhook", func() { + It("Should deny if a required field is empty", func() { + + // TODO(user): Add your logic here + + }) + + It("Should admit if all required fields are provided", func() { + + // TODO(user): Add your logic here + + }) + }) + +}) diff --git a/api/v3alpha3/remoteuser_types.go b/api/v3alpha3/remoteuser_types.go new file mode 100644 index 0000000..fba163a --- /dev/null +++ b/api/v3alpha3/remoteuser_types.go @@ -0,0 +1,136 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3alpha3 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type RemoteUserSpec struct { + SecretRef corev1.SecretReference `json:"secretRef"` + + Email string `json:"email"` + + GitBaseDomainFQDN string `json:"gitBaseDomainFQDN"` + + OwnRemoteUserBinding bool `json:"ownRemoteUserBinding"` + + // +optional + CustomGitServerConfigRef corev1.ObjectReference `json:"customGitServerConfigRef,omitempty"` + + // +optional + TestAuthentication bool `json:"testAuthentication,omitempty"` + + // +optional + InsecureSkipTlsVerify bool `json:"insecureSkipTlsVerify,omitempty"` +} + +type RemoteUserStatus struct { + + // +listType=map + // +listMapKey=type + // +patchStrategy=merge + // +patchMergeKey=type + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` + + // +optional + ConnexionStatus RemoteUserConnexionStatus `json:"connexionStatus,omitempty"` + + // +optional + GitUser string `json:"gitUser,omitempty"` + + // +optional + LastAuthTime metav1.Time `json:"lastAuthTime,omitempty"` + + // +optional + SecretBoundStatus SecretBoundStatus `json:"secretBoundStatus,omitempty"` + + // +optional + GitServerConfiguration GitServerConfiguration `json:"gitServerConfiguration,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:storageversion + +// RemoteUser is the Schema for the remoteusers API +type RemoteUser struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RemoteUserSpec `json:"spec,omitempty"` + Status RemoteUserStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// RemoteUserList contains a list of RemoteUser +type RemoteUserList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []RemoteUser `json:"items"` +} + +func init() { + SchemeBuilder.Register(&RemoteUser{}, &RemoteUserList{}) +} + +/* + STATUS EXTENSION +*/ + +type GitServerConfiguration struct { + // +optional + Inherited bool `json:"inherited,omitempty" yaml:"inherited,omitempty"` + //+ optional + AuthenticationEndpoint string `json:"authenticationEndpoint,omitempty" yaml:"authenticationEndpoint,omitempty"` + // +optional + CaBundle string `json:"caBundle,omitempty" yaml:"caBundle,omitempty"` + // +optional + InsecureSkipTlsVerify bool `json:"insecureSkipTlsVerify,omitempty" yaml:"insecureSkipTlsVerify,omitempty"` +} + +type RemoteUserConnexionStatus struct { + Status RemoteUserConnexionStatusReason `json:"status,omitempty"` + // +optional + Details string `json:"details,omitempty"` +} + +type RemoteUserConnexionStatusReason string + +const ( + GitConnected RemoteUserConnexionStatusReason = "Connected" + GitUnauthorized RemoteUserConnexionStatusReason = "Unauthorized: bad credentials" + GitForbidden RemoteUserConnexionStatusReason = "Forbidden : Not enough permission" + GitNotFound RemoteUserConnexionStatusReason = "Not found: the git server is not found" + GitServerError RemoteUserConnexionStatusReason = "Server error: a server error happened" + GitUnexpectedStatus RemoteUserConnexionStatusReason = "Unexpected response status code" + GitNotConnected RemoteUserConnexionStatusReason = "Not Connected" + GitUnsupported RemoteUserConnexionStatusReason = "Unsupported Git provider" + GitConfigNotFound RemoteUserConnexionStatusReason = "Git provider ConfigMap not found" + GitConfigParseError RemoteUserConnexionStatusReason = "Failed to parse the git provider ConfigMap" +) + +type SecretBoundStatus string + +const ( + SecretBound SecretBoundStatus = "Secret bound" + SecretNotFound SecretBoundStatus = "Secret not found" + SecretWrongType SecretBoundStatus = "Secret type is not set to BasicAuth" +) diff --git a/api/v3alpha3/remoteuser_webhook.go b/api/v3alpha3/remoteuser_webhook.go new file mode 100644 index 0000000..4ebf8fc --- /dev/null +++ b/api/v3alpha3/remoteuser_webhook.go @@ -0,0 +1,85 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3alpha3 + +import ( + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var remoteuserlog = logf.Log.WithName("remoteuser-resource") + +// SetupWebhookWithManager will setup the manager to manage the webhooks +func (r *RemoteUser) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +//+kubebuilder:webhook:path=/validate-syngit-syngit-io-v3alpha3-remoteuser,mutating=false,failurePolicy=fail,sideEffects=None,groups=syngit.syngit.io,resources=remoteusers,verbs=create;update,versions=v3alpha3,name=vremoteuser.kb.io,admissionReviewVersions=v1 +//+kubebuilder:webhook:path=/reconcile-syngit-remoteuser-owner,mutating=false,failurePolicy=fail,sideEffects=None,groups=syngit.syngit.io,resources=remoteusers,verbs=create;delete,versions=v3alpha3,admissionReviewVersions=v1,name=vremoteusers-owner.kb.io + +var _ webhook.Validator = &RemoteUser{} + +// Validate validates the RemoteUserSpec +func (r *RemoteUserSpec) ValidateRemoteUserSpec() field.ErrorList { + var errors field.ErrorList + + return errors +} + +func (r *RemoteUser) ValidateRemoteUser() error { + var allErrs field.ErrorList + if err := r.Spec.ValidateRemoteUserSpec(); err != nil { + allErrs = append(allErrs, err...) + } + if len(allErrs) == 0 { + return nil + } + + return apierrors.NewInvalid( + r.GroupVersionKind().GroupKind(), + r.Name, allErrs) +} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *RemoteUser) ValidateCreate() (admission.Warnings, error) { + remoteuserlog.Info("validate create", "name", r.Name) + + return nil, r.ValidateRemoteUser() +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *RemoteUser) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + remoteuserlog.Info("validate update", "name", r.Name) + + return nil, r.ValidateRemoteUser() +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *RemoteUser) ValidateDelete() (admission.Warnings, error) { + remoteuserlog.Info("validate delete", "name", r.Name) + + // Nothing to validate + return nil, nil +} diff --git a/api/v3alpha3/remoteuser_webhook_test.go b/api/v3alpha3/remoteuser_webhook_test.go new file mode 100644 index 0000000..6a3eec0 --- /dev/null +++ b/api/v3alpha3/remoteuser_webhook_test.go @@ -0,0 +1,39 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3alpha3 + +import ( + . "github.com/onsi/ginkgo/v2" +) + +var _ = Describe("RemoteUser Webhook", func() { + + Context("When creating RemoteUser under Validating Webhook", func() { + It("Should deny if a required field is empty", func() { + + // TODO(user): Add your logic here + + }) + + It("Should admit if all required fields are provided", func() { + + // TODO(user): Add your logic here + + }) + }) + +}) diff --git a/api/v3alpha3/remoteuserbinding_types.go b/api/v3alpha3/remoteuserbinding_types.go new file mode 100644 index 0000000..e7b3e1b --- /dev/null +++ b/api/v3alpha3/remoteuserbinding_types.go @@ -0,0 +1,92 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3alpha3 + +import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + RubPrefix = "owned-rub-" +) + +type RemoteUserBindingSpec struct { + Subject rbacv1.Subject `json:"subject"` + RemoteRefs []corev1.ObjectReference `json:"remoteRefs"` // Ref to the listed RemoteUser objects +} + +type RemoteUserBindingStatus struct { + // +optional + GlobalState GitUserBindingState `json:"state,omitempty"` + + // +optional + GitUserHosts []GitUserHost `json:"gitUserHosts"` + + // +optional + UserKubernetesID string `json:"userKubernetesID,omitempty"` + + // +optional + LastUsedTime metav1.Time `json:"lastUsedTime,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:storageversion + +// RemoteUserBinding is the Schema for the remoteuserbindings API +type RemoteUserBinding struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec RemoteUserBindingSpec `json:"spec,omitempty"` + Status RemoteUserBindingStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// RemoteUserBindingList contains a list of RemoteUserBinding +type RemoteUserBindingList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []RemoteUserBinding `json:"items"` +} + +func init() { + SchemeBuilder.Register(&RemoteUserBinding{}, &RemoteUserBindingList{}) +} + +/* + STATUS EXTENSION +*/ + +type GitUserBindingState string + +const ( + Bound GitUserBindingState = "Bound" + PartiallyBound GitUserBindingState = "PartiallyBound" + NotBound GitUserBindingState = "NotBound" +) + +type GitUserHost struct { + RemoteUserUsed string `json:"remoteUserUsed,omitempty"` + SecretRef corev1.SecretReference `json:"secretRef"` + GitFQDN string `json:"gitFQDN,omitempty"` + State GitUserBindingState `json:"state,omitempty"` + LastUsedTime metav1.Time `json:"lastUsedTime,omitempty"` +} diff --git a/api/v3alpha3/webhook_suite_test.go b/api/v3alpha3/webhook_suite_test.go new file mode 100644 index 0000000..2ada688 --- /dev/null +++ b/api/v3alpha3/webhook_suite_test.go @@ -0,0 +1,148 @@ +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v3alpha3 + +import ( + "context" + "crypto/tls" + "fmt" + "net" + "path/filepath" + "runtime" + "testing" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + admissionv1 "k8s.io/api/admission/v1" + //+kubebuilder:scaffold:imports + apimachineryruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment +var ctx context.Context +var cancel context.CancelFunc + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Webhook Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + ctx, cancel = context.WithCancel(context.TODO()) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: false, + + // The BinaryAssetsDirectory is only required if you want to run the tests directly + // without call the makefile target test. If not informed it will look for the + // default path defined in controller-runtime which is /usr/local/kubebuilder/. + // Note that you must have the required binaries setup under the bin directory to perform + // the tests directly. When we run make test it will be setup and used automatically. + BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s", + fmt.Sprintf("1.29.0-%s-%s", runtime.GOOS, runtime.GOARCH)), + + WebhookInstallOptions: envtest.WebhookInstallOptions{ + Paths: []string{filepath.Join("..", "..", "config", "webhook")}, + }, + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + scheme := apimachineryruntime.NewScheme() + err = AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + err = admissionv1.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + + // start webhook server using Manager + webhookInstallOptions := &testEnv.WebhookInstallOptions + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: scheme, + WebhookServer: webhook.NewServer(webhook.Options{ + Host: webhookInstallOptions.LocalServingHost, + Port: webhookInstallOptions.LocalServingPort, + CertDir: webhookInstallOptions.LocalServingCertDir, + }), + LeaderElection: false, + Metrics: metricsserver.Options{BindAddress: "0"}, + }) + Expect(err).NotTo(HaveOccurred()) + + err = (&RemoteSyncer{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + + err = (&RemoteUser{}).SetupWebhookWithManager(mgr) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:webhook + + go func() { + defer GinkgoRecover() + err = mgr.Start(ctx) + Expect(err).NotTo(HaveOccurred()) + }() + + // wait for the webhook server to get ready + dialer := &net.Dialer{Timeout: time.Second} + addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort) + Eventually(func() error { + conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true}) + if err != nil { + return err + } + return conn.Close() + }).Should(Succeed()) + +}) + +var _ = AfterSuite(func() { + cancel() + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +}) diff --git a/api/v3alpha3/zz_generated.deepcopy.go b/api/v3alpha3/zz_generated.deepcopy.go new file mode 100644 index 0000000..4c087b6 --- /dev/null +++ b/api/v3alpha3/zz_generated.deepcopy.go @@ -0,0 +1,611 @@ +//go:build !ignore_autogenerated + +/* +Copyright 2024. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v3alpha3 + +import ( + admissionregistrationv1 "k8s.io/api/admissionregistration/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitServerConfiguration) DeepCopyInto(out *GitServerConfiguration) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitServerConfiguration. +func (in *GitServerConfiguration) DeepCopy() *GitServerConfiguration { + if in == nil { + return nil + } + out := new(GitServerConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GitUserHost) DeepCopyInto(out *GitUserHost) { + *out = *in + out.SecretRef = in.SecretRef + in.LastUsedTime.DeepCopyInto(&out.LastUsedTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GitUserHost. +func (in *GitUserHost) DeepCopy() *GitUserHost { + if in == nil { + return nil + } + out := new(GitUserHost) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GroupVersionKindName) DeepCopyInto(out *GroupVersionKindName) { + *out = *in + if in.GroupVersionKind != nil { + in, out := &in.GroupVersionKind, &out.GroupVersionKind + *out = new(schema.GroupVersionKind) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupVersionKindName. +func (in *GroupVersionKindName) DeepCopy() *GroupVersionKindName { + if in == nil { + return nil + } + out := new(GroupVersionKindName) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GroupVersionResourceName) DeepCopyInto(out *GroupVersionResourceName) { + *out = *in + if in.GroupVersionResource != nil { + in, out := &in.GroupVersionResource, &out.GroupVersionResource + *out = new(schema.GroupVersionResource) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GroupVersionResourceName. +func (in *GroupVersionResourceName) DeepCopy() *GroupVersionResourceName { + if in == nil { + return nil + } + out := new(GroupVersionResourceName) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JsonGVRN) DeepCopyInto(out *JsonGVRN) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JsonGVRN. +func (in *JsonGVRN) DeepCopy() *JsonGVRN { + if in == nil { + return nil + } + out := new(JsonGVRN) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LastBypassedObjectState) DeepCopyInto(out *LastBypassedObjectState) { + *out = *in + in.LastBypassedObjectTime.DeepCopyInto(&out.LastBypassedObjectTime) + in.LastBypassedObjectUserInfo.DeepCopyInto(&out.LastBypassedObjectUserInfo) + out.LastBypassedObject = in.LastBypassedObject +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LastBypassedObjectState. +func (in *LastBypassedObjectState) DeepCopy() *LastBypassedObjectState { + if in == nil { + return nil + } + out := new(LastBypassedObjectState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LastObservedObjectState) DeepCopyInto(out *LastObservedObjectState) { + *out = *in + in.LastObservedObjectTime.DeepCopyInto(&out.LastObservedObjectTime) + in.LastObservedObjectUserInfo.DeepCopyInto(&out.LastObservedObjectUserInfo) + out.LastObservedObject = in.LastObservedObject +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LastObservedObjectState. +func (in *LastObservedObjectState) DeepCopy() *LastObservedObjectState { + if in == nil { + return nil + } + out := new(LastObservedObjectState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LastPushedObjectState) DeepCopyInto(out *LastPushedObjectState) { + *out = *in + in.LastPushedObjectTime.DeepCopyInto(&out.LastPushedObjectTime) + out.LastPushedObject = in.LastPushedObject +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LastPushedObjectState. +func (in *LastPushedObjectState) DeepCopy() *LastPushedObjectState { + if in == nil { + return nil + } + out := new(LastPushedObjectState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespaceScopedKinds) DeepCopyInto(out *NamespaceScopedKinds) { + *out = *in + if in.APIGroups != nil { + in, out := &in.APIGroups, &out.APIGroups + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.APIVersions != nil { + in, out := &in.APIVersions, &out.APIVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Kinds != nil { + in, out := &in.Kinds, &out.Kinds + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Names != nil { + in, out := &in.Names, &out.Names + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceScopedKinds. +func (in *NamespaceScopedKinds) DeepCopy() *NamespaceScopedKinds { + if in == nil { + return nil + } + out := new(NamespaceScopedKinds) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NamespaceScopedResources) DeepCopyInto(out *NamespaceScopedResources) { + *out = *in + if in.APIGroups != nil { + in, out := &in.APIGroups, &out.APIGroups + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.APIVersions != nil { + in, out := &in.APIVersions, &out.APIVersions + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Names != nil { + in, out := &in.Names, &out.Names + *out = make([]string, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NamespaceScopedResources. +func (in *NamespaceScopedResources) DeepCopy() *NamespaceScopedResources { + if in == nil { + return nil + } + out := new(NamespaceScopedResources) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteSyncer) DeepCopyInto(out *RemoteSyncer) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteSyncer. +func (in *RemoteSyncer) DeepCopy() *RemoteSyncer { + if in == nil { + return nil + } + out := new(RemoteSyncer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RemoteSyncer) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteSyncerList) DeepCopyInto(out *RemoteSyncerList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RemoteSyncer, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteSyncerList. +func (in *RemoteSyncerList) DeepCopy() *RemoteSyncerList { + if in == nil { + return nil + } + out := new(RemoteSyncerList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RemoteSyncerList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteSyncerSpec) DeepCopyInto(out *RemoteSyncerSpec) { + *out = *in + if in.BypassInterceptionSubjects != nil { + in, out := &in.BypassInterceptionSubjects, &out.BypassInterceptionSubjects + *out = make([]v1.Subject, len(*in)) + copy(*out, *in) + } + if in.DefaultUser != nil { + in, out := &in.DefaultUser, &out.DefaultUser + *out = new(corev1.ObjectReference) + **out = **in + } + in.ScopedResources.DeepCopyInto(&out.ScopedResources) + if in.ExcludedFields != nil { + in, out := &in.ExcludedFields, &out.ExcludedFields + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.ExcludedFieldsConfig != nil { + in, out := &in.ExcludedFieldsConfig, &out.ExcludedFieldsConfig + *out = new(corev1.ObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteSyncerSpec. +func (in *RemoteSyncerSpec) DeepCopy() *RemoteSyncerSpec { + if in == nil { + return nil + } + out := new(RemoteSyncerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteSyncerStatus) DeepCopyInto(out *RemoteSyncerStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.LastBypassedObjectState.DeepCopyInto(&out.LastBypassedObjectState) + in.LastObservedObjectState.DeepCopyInto(&out.LastObservedObjectState) + in.LastPushedObjectState.DeepCopyInto(&out.LastPushedObjectState) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteSyncerStatus. +func (in *RemoteSyncerStatus) DeepCopy() *RemoteSyncerStatus { + if in == nil { + return nil + } + out := new(RemoteSyncerStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUser) DeepCopyInto(out *RemoteUser) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUser. +func (in *RemoteUser) DeepCopy() *RemoteUser { + if in == nil { + return nil + } + out := new(RemoteUser) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RemoteUser) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUserBinding) DeepCopyInto(out *RemoteUserBinding) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUserBinding. +func (in *RemoteUserBinding) DeepCopy() *RemoteUserBinding { + if in == nil { + return nil + } + out := new(RemoteUserBinding) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RemoteUserBinding) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUserBindingList) DeepCopyInto(out *RemoteUserBindingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RemoteUserBinding, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUserBindingList. +func (in *RemoteUserBindingList) DeepCopy() *RemoteUserBindingList { + if in == nil { + return nil + } + out := new(RemoteUserBindingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RemoteUserBindingList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUserBindingSpec) DeepCopyInto(out *RemoteUserBindingSpec) { + *out = *in + out.Subject = in.Subject + if in.RemoteRefs != nil { + in, out := &in.RemoteRefs, &out.RemoteRefs + *out = make([]corev1.ObjectReference, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUserBindingSpec. +func (in *RemoteUserBindingSpec) DeepCopy() *RemoteUserBindingSpec { + if in == nil { + return nil + } + out := new(RemoteUserBindingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUserBindingStatus) DeepCopyInto(out *RemoteUserBindingStatus) { + *out = *in + if in.GitUserHosts != nil { + in, out := &in.GitUserHosts, &out.GitUserHosts + *out = make([]GitUserHost, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.LastUsedTime.DeepCopyInto(&out.LastUsedTime) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUserBindingStatus. +func (in *RemoteUserBindingStatus) DeepCopy() *RemoteUserBindingStatus { + if in == nil { + return nil + } + out := new(RemoteUserBindingStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUserConnexionStatus) DeepCopyInto(out *RemoteUserConnexionStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUserConnexionStatus. +func (in *RemoteUserConnexionStatus) DeepCopy() *RemoteUserConnexionStatus { + if in == nil { + return nil + } + out := new(RemoteUserConnexionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUserList) DeepCopyInto(out *RemoteUserList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RemoteUser, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUserList. +func (in *RemoteUserList) DeepCopy() *RemoteUserList { + if in == nil { + return nil + } + out := new(RemoteUserList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RemoteUserList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUserSpec) DeepCopyInto(out *RemoteUserSpec) { + *out = *in + out.SecretRef = in.SecretRef + out.CustomGitServerConfigRef = in.CustomGitServerConfigRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUserSpec. +func (in *RemoteUserSpec) DeepCopy() *RemoteUserSpec { + if in == nil { + return nil + } + out := new(RemoteUserSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RemoteUserStatus) DeepCopyInto(out *RemoteUserStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + out.ConnexionStatus = in.ConnexionStatus + in.LastAuthTime.DeepCopyInto(&out.LastAuthTime) + out.GitServerConfiguration = in.GitServerConfiguration +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RemoteUserStatus. +func (in *RemoteUserStatus) DeepCopy() *RemoteUserStatus { + if in == nil { + return nil + } + out := new(RemoteUserStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ScopedResources) DeepCopyInto(out *ScopedResources) { + *out = *in + if in.MatchPolicy != nil { + in, out := &in.MatchPolicy, &out.MatchPolicy + *out = new(admissionregistrationv1.MatchPolicyType) + **out = **in + } + if in.ObjectSelector != nil { + in, out := &in.ObjectSelector, &out.ObjectSelector + *out = new(metav1.LabelSelector) + (*in).DeepCopyInto(*out) + } + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]admissionregistrationv1.RuleWithOperations, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ScopedResources. +func (in *ScopedResources) DeepCopy() *ScopedResources { + if in == nil { + return nil + } + out := new(ScopedResources) + in.DeepCopyInto(out) + return out +} diff --git a/charts/0.0.2/values.yaml b/charts/0.0.2/values.yaml index e165f2b..d45e6e1 100644 --- a/charts/0.0.2/values.yaml +++ b/charts/0.0.2/values.yaml @@ -7,7 +7,7 @@ webhook: controller: image: - prefix: ghcr.io/damsien + prefix: ghcr.io/syngit-org name: syngit tag: 0.0.2 diff --git a/charts/0.0.3/Chart.yaml b/charts/0.0.3/Chart.yaml new file mode 100644 index 0000000..5f80039 --- /dev/null +++ b/charts/0.0.3/Chart.yaml @@ -0,0 +1,11 @@ +apiVersion: v2 +name: syngit +description: An operator to push resources onto git +type: application +version: 0.0.3 +appVersion: 0.0.3 +home: https://github.com/syngit-org/syngit +icon: https://raw.githubusercontent.com/syngit-org/syngit/main/img/icon.png +maintainers: + - email: dassieu.damien@gmail.com + name: Damien diff --git a/charts/0.0.3/templates/certmanager/certificate.yaml b/charts/0.0.3/templates/certmanager/certificate.yaml new file mode 100644 index 0000000..85e3a50 --- /dev/null +++ b/charts/0.0.3/templates/certmanager/certificate.yaml @@ -0,0 +1,36 @@ +{{- if eq .Values.webhook.certmanager.enable true }} +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + labels: + app.kubernetes.io/name: certificate + app.kubernetes.io/instance: serving-cert + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-selfsigned-issuer +spec: + selfSigned: {} +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + labels: + app.kubernetes.io/name: certificate + app.kubernetes.io/instance: serving-cert + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: operator-webhook-cert +spec: + dnsNames: + - webhook-crd-service.{{ .Release.Namespace }}.svc + - webhook-crd-service.{{ .Release.Namespace }}.svc.cluster.local + - webhook-pusher-service.{{ .Release.Namespace }}.svc + - webhook-pusher-service.{{ .Release.Namespace }}.svc.cluster.local + issuerRef: + kind: Issuer + name: {{ .Release.Name }}-selfsigned-issuer + secretName: {{ .Values.webhook.certmanager.certificate.secret }} +{{- end }} \ No newline at end of file diff --git a/charts/0.0.3/templates/config/bitbucket-configuration.yaml b/charts/0.0.3/templates/config/bitbucket-configuration.yaml new file mode 100644 index 0000000..b3f5434 --- /dev/null +++ b/charts/0.0.3/templates/config/bitbucket-configuration.yaml @@ -0,0 +1,8 @@ +{{- if eq .Values.configuration.bitbucket true }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: bitbucket.org +data: + authenticationEndpoint: https://api.bitbucket.org/2.0/user +{{- end }} \ No newline at end of file diff --git a/charts/0.0.3/templates/config/github-configuration.yaml b/charts/0.0.3/templates/config/github-configuration.yaml new file mode 100644 index 0000000..9b1600a --- /dev/null +++ b/charts/0.0.3/templates/config/github-configuration.yaml @@ -0,0 +1,8 @@ +{{- if eq .Values.configuration.github true }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: github.com +data: + authenticationEndpoint: https://api.github.com/user +{{- end }} \ No newline at end of file diff --git a/charts/0.0.3/templates/config/gitlab-configuration.yaml b/charts/0.0.3/templates/config/gitlab-configuration.yaml new file mode 100644 index 0000000..258ed8f --- /dev/null +++ b/charts/0.0.3/templates/config/gitlab-configuration.yaml @@ -0,0 +1,8 @@ +{{- if eq .Values.configuration.gitlab true }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitlab.com +data: + authenticationEndpoint: https://gitlab.com/api/v4/user +{{- end }} \ No newline at end of file diff --git a/charts/0.0.3/templates/controller/auth_proxy_service.yaml b/charts/0.0.3/templates/controller/auth_proxy_service.yaml new file mode 100644 index 0000000..c09041c --- /dev/null +++ b/charts/0.0.3/templates/controller/auth_proxy_service.yaml @@ -0,0 +1,22 @@ +{{- if eq .Values.controller.rbacProxy.enable true }} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: service + app.kubernetes.io/instance: controller-manager-metrics-service + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-controller-manager-metrics-service +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: https + selector: + control-plane: controller-manager +{{- end }} diff --git a/charts/0.0.3/templates/controller/manager.yaml b/charts/0.0.3/templates/controller/manager.yaml new file mode 100644 index 0000000..959c17d --- /dev/null +++ b/charts/0.0.3/templates/controller/manager.yaml @@ -0,0 +1,90 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + labels: + control-plane: controller-manager + app.kubernetes.io/name: deployment + app.kubernetes.io/instance: controller-manager + app.kubernetes.io/component: manager + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} +spec: + selector: + matchLabels: + control-plane: controller-manager + replicas: 1 + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + control-plane: controller-manager + spec: + containers: + {{- if eq .Values.controller.metrics.enable true }} + - name: kube-rbac-proxy + securityContext: {{ toYaml .Values.controller.rbacProxy.securityContext | nindent 10 }} + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0 + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream={{ .Values.controller.rbacProxy.upstreamAddress }}" + - "--logtostderr=true" + - "--v=0" + ports: + - containerPort: 8443 + protocol: TCP + name: https + resources: {{ toYaml .Values.controller.rbacProxy.resources | nindent 10 }} + {{- end }} + - command: + - /manager + args: + - "--leader-elect" + {{- if eq .Values.controller.metrics.enable true }} + - "--health-probe-bind-address=:8081" + - "--metrics-bind-address={{ .Values.controller.metrics.bindAddress }}" + {{- end }} + image: {{ .Values.controller.image.prefix }}/{{ .Values.controller.image.name }}:{{ .Values.controller.image.tag }} + env: + - name: MANAGER_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + name: manager + securityContext: {{ toYaml .Values.controller.securityContext | nindent 10 }} + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: {{ toYaml .Values.controller.resources | nindent 10 }} + ports: + - containerPort: 9443 + name: wbhk-crd-srv + protocol: TCP + - containerPort: 9444 + name: wbhk-pusher-srv + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + serviceAccountName: {{ .Release.Name }}-controller-manager + terminationGracePeriodSeconds: 10 + {{- if .Values.controller.tolerations }} + tolerations: {{ toYaml .Values.controller.tolerations | nindent 8 }} + {{- end }} + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: {{ .Values.webhook.certmanager.certificate.secret }} \ No newline at end of file diff --git a/charts/0.0.3/templates/crd/syngit.syngit.io_remotesyncer.yaml b/charts/0.0.3/templates/crd/syngit.syngit.io_remotesyncer.yaml new file mode 100644 index 0000000..57161de --- /dev/null +++ b/charts/0.0.3/templates/crd/syngit.syngit.io_remotesyncer.yaml @@ -0,0 +1,1598 @@ +{{- if eq .Values.installCRD true }} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: remotesyncers.syngit.syngit.io +spec: + group: syngit.syngit.io + names: + kind: RemoteSyncer + listKind: RemoteSyncerList + plural: remotesyncers + singular: remotesyncer + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: RemoteSyncer is the Schema for the remotesyncers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + authorizedUsers: + items: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + minItems: 1 + type: array + branch: + type: string + bypassInterceptionSubjects: + items: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + type: array + commitMode: + type: string + commitProcess: + type: string + defaultBlockAppliedMessage: + type: string + defaultUnauthorizedUserMode: + type: string + defaultUserBind: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + excludedFields: + items: + type: string + type: array + excludedResources: + items: + properties: + apiGroups: + items: + type: string + type: array + apiVersions: + items: + type: string + type: array + names: + items: + type: string + type: array + resources: + items: + type: string + type: array + required: + - apiGroups + - apiVersions + - resources + type: object + type: array + includedResources: + items: + properties: + apiGroups: + items: + type: string + type: array + apiVersions: + items: + type: string + type: array + names: + items: + type: string + type: array + repoPath: + type: string + resources: + items: + type: string + type: array + required: + - apiGroups + - apiVersions + - resources + type: object + type: array + operations: + items: + description: OperationType specifies an operation for a request. + type: string + maxItems: 3 + minItems: 1 + type: array + remoteRepository: + format: uri + type: string + required: + - authorizedUsers + - branch + - commitMode + - commitProcess + - defaultUnauthorizedUserMode + - operations + - remoteRepository + type: object + status: + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastBypassedObjectState: + properties: + lastBypassObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastBypassObjectTime: + format: date-time + type: string + lastBypassObjectUserInfo: + description: |- + UserInfo holds the information about the user needed to implement the + user.Info interface. + properties: + extra: + additionalProperties: + description: ExtraValue masks the value so protobuf can + generate + items: + type: string + type: array + description: Any additional information provided by the authenticator. + type: object + groups: + description: The names of groups this user is a part of. + items: + type: string + type: array + x-kubernetes-list-type: atomic + uid: + description: |- + A unique value that identifies this user across time. If this user is + deleted and another user by the same name is added, they will have + different UIDs. + type: string + username: + description: The name that uniquely identifies this user among + all active users. + type: string + type: object + type: object + lastObservedObjectState: + properties: + lastObservedObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastObservedObjectTime: + format: date-time + type: string + lastObservedObjectUserInfo: + description: |- + UserInfo holds the information about the user needed to implement the + user.Info interface. + properties: + extra: + additionalProperties: + description: ExtraValue masks the value so protobuf can + generate + items: + type: string + type: array + description: Any additional information provided by the authenticator. + type: object + groups: + description: The names of groups this user is a part of. + items: + type: string + type: array + x-kubernetes-list-type: atomic + uid: + description: |- + A unique value that identifies this user across time. If this user is + deleted and another user by the same name is added, they will have + different UIDs. + type: string + username: + description: The name that uniquely identifies this user among + all active users. + type: string + type: object + type: object + lastPushedObjectState: + properties: + lastPushedGitUser: + type: string + lastPushedObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastPushedObjectCommitHash: + type: string + lastPushedObjectGitPath: + type: string + lastPushedObjectGitRepo: + type: string + lastPushedObjectState: + type: string + lastPushedObjectTime: + format: date-time + type: string + type: object + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v2alpha2 + schema: + openAPIV3Schema: + description: RemoteSyncer is the Schema for the remotesyncers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + authorizedUsers: + items: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + minItems: 1 + type: array + branch: + type: string + bypassInterceptionSubjects: + items: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + type: array + commitProcess: + type: string + defaultBlockAppliedMessage: + type: string + defaultUnauthorizedUserMode: + type: string + defaultUserBind: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + excludedFields: + items: + type: string + type: array + remoteRepository: + format: uri + type: string + rootPath: + type: string + scopedResources: + properties: + matchPolicy: + description: MatchPolicyType specifies the type of match policy. + type: string + objectSelector: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + rules: + items: + description: |- + RuleWithOperations is a tuple of Operations and Resources. It is recommended to make + sure that all the tuple expansions are valid. + properties: + apiGroups: + description: |- + APIGroups is the API groups the resources belong to. '*' is all groups. + If '*' is present, the length of the slice must be one. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + apiVersions: + description: |- + APIVersions is the API versions the resources belong to. '*' is all versions. + If '*' is present, the length of the slice must be one. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + operations: + description: |- + Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * + for all of those operations and any future admission operations that are added. + If '*' is present, the length of the slice must be one. + Required. + items: + description: OperationType specifies an operation for + a request. + type: string + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Resources is a list of resources this rule applies to. + + + For example: + 'pods' means pods. + 'pods/log' means the log subresource of pods. + '*' means all resources, but not subresources. + 'pods/*' means all subresources of pods. + '*/scale' means all scale subresources. + '*/*' means all resources and their subresources. + + + If wildcard is present, the validation rule will ensure resources do not + overlap with each other. + + + Depending on the enclosing object, subresources might not be allowed. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + scope: + description: |- + scope specifies the scope of this rule. + Valid values are "Cluster", "Namespaced", and "*" + "Cluster" means that only cluster-scoped resources will match this rule. + Namespace API objects are cluster-scoped. + "Namespaced" means that only namespaced resources will match this rule. + "*" means that there are no scope restrictions. + Subresources match the scope of their parent resource. + Default is "*". + type: string + type: object + type: array + type: object + required: + - authorizedUsers + - branch + - commitProcess + - defaultUnauthorizedUserMode + - remoteRepository + type: object + status: + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastBypassedObjectState: + properties: + lastBypassObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastBypassObjectTime: + format: date-time + type: string + lastBypassObjectUserInfo: + description: |- + UserInfo holds the information about the user needed to implement the + user.Info interface. + properties: + extra: + additionalProperties: + description: ExtraValue masks the value so protobuf can + generate + items: + type: string + type: array + description: Any additional information provided by the authenticator. + type: object + groups: + description: The names of groups this user is a part of. + items: + type: string + type: array + x-kubernetes-list-type: atomic + uid: + description: |- + A unique value that identifies this user across time. If this user is + deleted and another user by the same name is added, they will have + different UIDs. + type: string + username: + description: The name that uniquely identifies this user among + all active users. + type: string + type: object + type: object + lastObservedObjectState: + properties: + lastObservedObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastObservedObjectTime: + format: date-time + type: string + lastObservedObjectUserInfo: + description: |- + UserInfo holds the information about the user needed to implement the + user.Info interface. + properties: + extra: + additionalProperties: + description: ExtraValue masks the value so protobuf can + generate + items: + type: string + type: array + description: Any additional information provided by the authenticator. + type: object + groups: + description: The names of groups this user is a part of. + items: + type: string + type: array + x-kubernetes-list-type: atomic + uid: + description: |- + A unique value that identifies this user across time. If this user is + deleted and another user by the same name is added, they will have + different UIDs. + type: string + username: + description: The name that uniquely identifies this user among + all active users. + type: string + type: object + type: object + lastPushedObjectState: + properties: + lastPushedGitUser: + type: string + lastPushedObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastPushedObjectCommitHash: + type: string + lastPushedObjectGitPath: + type: string + lastPushedObjectGitRepo: + type: string + lastPushedObjectState: + type: string + lastPushedObjectTime: + format: date-time + type: string + type: object + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v3alpha3 + schema: + openAPIV3Schema: + description: RemoteSyncer is the Schema for the remotesyncers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + branch: + type: string + bypassInterceptionSubjects: + items: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + type: array + commitProcess: + type: string + defaultBlockAppliedMessage: + type: string + defaultUnauthorizedUserMode: + type: string + defaultUser: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + excludedFields: + items: + type: string + type: array + excludedFieldsConfig: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + remoteRepository: + format: uri + type: string + rootPath: + type: string + scopedResources: + properties: + matchPolicy: + description: MatchPolicyType specifies the type of match policy. + type: string + objectSelector: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + rules: + items: + description: |- + RuleWithOperations is a tuple of Operations and Resources. It is recommended to make + sure that all the tuple expansions are valid. + properties: + apiGroups: + description: |- + APIGroups is the API groups the resources belong to. '*' is all groups. + If '*' is present, the length of the slice must be one. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + apiVersions: + description: |- + APIVersions is the API versions the resources belong to. '*' is all versions. + If '*' is present, the length of the slice must be one. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + operations: + description: |- + Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * + for all of those operations and any future admission operations that are added. + If '*' is present, the length of the slice must be one. + Required. + items: + description: OperationType specifies an operation for + a request. + type: string + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Resources is a list of resources this rule applies to. + + + For example: + 'pods' means pods. + 'pods/log' means the log subresource of pods. + '*' means all resources, but not subresources. + 'pods/*' means all subresources of pods. + '*/scale' means all scale subresources. + '*/*' means all resources and their subresources. + + + If wildcard is present, the validation rule will ensure resources do not + overlap with each other. + + + Depending on the enclosing object, subresources might not be allowed. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + scope: + description: |- + scope specifies the scope of this rule. + Valid values are "Cluster", "Namespaced", and "*" + "Cluster" means that only cluster-scoped resources will match this rule. + Namespace API objects are cluster-scoped. + "Namespaced" means that only namespaced resources will match this rule. + "*" means that there are no scope restrictions. + Subresources match the scope of their parent resource. + Default is "*". + type: string + type: object + type: array + type: object + required: + - branch + - commitProcess + - defaultUnauthorizedUserMode + - remoteRepository + type: object + status: + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastBypassedObjectState: + properties: + lastBypassObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastBypassObjectTime: + format: date-time + type: string + lastBypassObjectUserInfo: + description: |- + UserInfo holds the information about the user needed to implement the + user.Info interface. + properties: + extra: + additionalProperties: + description: ExtraValue masks the value so protobuf can + generate + items: + type: string + type: array + description: Any additional information provided by the authenticator. + type: object + groups: + description: The names of groups this user is a part of. + items: + type: string + type: array + x-kubernetes-list-type: atomic + uid: + description: |- + A unique value that identifies this user across time. If this user is + deleted and another user by the same name is added, they will have + different UIDs. + type: string + username: + description: The name that uniquely identifies this user among + all active users. + type: string + type: object + type: object + lastObservedObjectState: + properties: + lastObservedObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastObservedObjectTime: + format: date-time + type: string + lastObservedObjectUserInfo: + description: |- + UserInfo holds the information about the user needed to implement the + user.Info interface. + properties: + extra: + additionalProperties: + description: ExtraValue masks the value so protobuf can + generate + items: + type: string + type: array + description: Any additional information provided by the authenticator. + type: object + groups: + description: The names of groups this user is a part of. + items: + type: string + type: array + x-kubernetes-list-type: atomic + uid: + description: |- + A unique value that identifies this user across time. If this user is + deleted and another user by the same name is added, they will have + different UIDs. + type: string + username: + description: The name that uniquely identifies this user among + all active users. + type: string + type: object + type: object + lastPushedObjectState: + properties: + lastPushedGitUser: + type: string + lastPushedObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastPushedObjectCommitHash: + type: string + lastPushedObjectGitPath: + type: string + lastPushedObjectGitRepo: + type: string + lastPushedObjectState: + type: string + lastPushedObjectTime: + format: date-time + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} + +{{- end }} diff --git a/charts/0.0.3/templates/crd/syngit.syngit.io_remoteuser.yaml b/charts/0.0.3/templates/crd/syngit.syngit.io_remoteuser.yaml new file mode 100644 index 0000000..2e490fb --- /dev/null +++ b/charts/0.0.3/templates/crd/syngit.syngit.io_remoteuser.yaml @@ -0,0 +1,679 @@ +{{- if eq .Values.installCRD true }} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: remoteusers.syngit.syngit.io +spec: + group: syngit.syngit.io + names: + kind: RemoteUser + listKind: RemoteUserList + plural: remoteusers + singular: remoteuser + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: RemoteUser is the Schema for the remoteusers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + customGitServerConfigRef: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + email: + type: string + gitBaseDomainFQDN: + type: string + insecureSkipTlsVerify: + type: boolean + secretRef: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + testAuthentication: + type: boolean + required: + - email + - gitBaseDomainFQDN + - secretRef + type: object + status: + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + connexionStatus: + properties: + details: + type: string + status: + type: string + type: object + gitServerConfiguration: + properties: + authenticationEndpoint: + type: string + caBundle: + type: string + inherited: + type: boolean + insecureSkipTlsVerify: + type: boolean + type: object + gitUser: + type: string + lastAuthTime: + format: date-time + type: string + secretBoundStatus: + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v2alpha2 + schema: + openAPIV3Schema: + description: RemoteUser is the Schema for the remoteusers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + customGitServerConfigRef: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + email: + type: string + gitBaseDomainFQDN: + type: string + insecureSkipTlsVerify: + type: boolean + ownRemoteUserBinding: + type: boolean + secretRef: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + testAuthentication: + type: boolean + required: + - email + - gitBaseDomainFQDN + - ownRemoteUserBinding + - secretRef + type: object + status: + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + connexionStatus: + properties: + details: + type: string + status: + type: string + type: object + gitServerConfiguration: + properties: + authenticationEndpoint: + type: string + caBundle: + type: string + inherited: + type: boolean + insecureSkipTlsVerify: + type: boolean + type: object + gitUser: + type: string + lastAuthTime: + format: date-time + type: string + secretBoundStatus: + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v3alpha3 + schema: + openAPIV3Schema: + description: RemoteUser is the Schema for the remoteusers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + customGitServerConfigRef: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + email: + type: string + gitBaseDomainFQDN: + type: string + insecureSkipTlsVerify: + type: boolean + ownRemoteUserBinding: + type: boolean + secretRef: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + testAuthentication: + type: boolean + required: + - email + - gitBaseDomainFQDN + - ownRemoteUserBinding + - secretRef + type: object + status: + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + connexionStatus: + properties: + details: + type: string + status: + type: string + type: object + gitServerConfiguration: + properties: + authenticationEndpoint: + type: string + caBundle: + type: string + inherited: + type: boolean + insecureSkipTlsVerify: + type: boolean + type: object + gitUser: + type: string + lastAuthTime: + format: date-time + type: string + secretBoundStatus: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + +{{- end }} diff --git a/charts/0.0.3/templates/crd/syngit.syngit.io_remoteuserbinding.yaml b/charts/0.0.3/templates/crd/syngit.syngit.io_remoteuserbinding.yaml new file mode 100644 index 0000000..8e94fee --- /dev/null +++ b/charts/0.0.3/templates/crd/syngit.syngit.io_remoteuserbinding.yaml @@ -0,0 +1,517 @@ +{{- if eq .Values.installCRD true }} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: remoteuserbindings.syngit.syngit.io +spec: + group: syngit.syngit.io + names: + kind: RemoteUserBinding + listKind: RemoteUserBindingList + plural: remoteuserbindings + singular: remoteuserbinding + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: RemoteUserBinding is the Schema for the remoteuserbindings API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + remoteRefs: + items: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: array + subject: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + required: + - remoteRefs + - subject + type: object + status: + properties: + gitUserHosts: + items: + properties: + gitFQDN: + type: string + lastUsedTime: + format: date-time + type: string + remoteUserUsed: + type: string + secretRef: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + state: + type: string + required: + - secretRef + type: object + type: array + lastUsedTime: + format: date-time + type: string + state: + type: string + userKubernetesID: + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v2alpha2 + schema: + openAPIV3Schema: + description: RemoteUserBinding is the Schema for the remoteuserbindings API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + remoteRefs: + items: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: array + subject: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + required: + - remoteRefs + - subject + type: object + status: + properties: + gitUserHosts: + items: + properties: + gitFQDN: + type: string + lastUsedTime: + format: date-time + type: string + remoteUserUsed: + type: string + secretRef: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + state: + type: string + required: + - secretRef + type: object + type: array + lastUsedTime: + format: date-time + type: string + state: + type: string + userKubernetesID: + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v3alpha3 + schema: + openAPIV3Schema: + description: RemoteUserBinding is the Schema for the remoteuserbindings API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + remoteRefs: + items: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: array + subject: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + required: + - remoteRefs + - subject + type: object + status: + properties: + gitUserHosts: + items: + properties: + gitFQDN: + type: string + lastUsedTime: + format: date-time + type: string + remoteUserUsed: + type: string + secretRef: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + state: + type: string + required: + - secretRef + type: object + type: array + lastUsedTime: + format: date-time + type: string + state: + type: string + userKubernetesID: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + +{{- end }} diff --git a/charts/0.0.3/templates/monitoring/monitor.yaml b/charts/0.0.3/templates/monitoring/monitor.yaml new file mode 100644 index 0000000..32037d9 --- /dev/null +++ b/charts/0.0.3/templates/monitoring/monitor.yaml @@ -0,0 +1,25 @@ +{{- if eq .Values.monitoring.enable true }} +--- +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: controller-manager + app.kubernetes.io/name: servicemonitor + app.kubernetes.io/instance: controller-manager-metrics-monitor + app.kubernetes.io/component: metrics + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-controller-manager-metrics-monitor +spec: + endpoints: + - path: /metrics + port: https + scheme: https + bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token + tlsConfig: + insecureSkipVerify: true + selector: + matchLabels: + control-plane: controller-manager +{{- end }} \ No newline at end of file diff --git a/charts/0.0.3/templates/rbac/controller/auth_proxy_client_clusterrole.yaml b/charts/0.0.3/templates/rbac/controller/auth_proxy_client_clusterrole.yaml new file mode 100644 index 0000000..1015170 --- /dev/null +++ b/charts/0.0.3/templates/rbac/controller/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,18 @@ +# {{- if eq .Values.controller.rbacProxy.enable true }} +# --- +# apiVersion: rbac.authorization.k8s.io/v1 +# kind: ClusterRole +# metadata: +# labels: +# app.kubernetes.io/name: clusterrole +# app.kubernetes.io/instance: metrics-reader +# app.kubernetes.io/component: kube-rbac-proxy +# app.kubernetes.io/created-by: {{ .Release.Name }} +# app.kubernetes.io/part-of: {{ .Release.Name }} +# name: {{ .Release.Name }}-metrics-reader +# rules: +# - nonResourceURLs: +# - "/metrics" +# verbs: +# - get +# {{- end }} diff --git a/charts/0.0.3/templates/rbac/controller/auth_proxy_role.yaml b/charts/0.0.3/templates/rbac/controller/auth_proxy_role.yaml new file mode 100644 index 0000000..8f7cad3 --- /dev/null +++ b/charts/0.0.3/templates/rbac/controller/auth_proxy_role.yaml @@ -0,0 +1,26 @@ +{{- if eq .Values.controller.rbacProxy.enable true }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: proxy-role + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-proxy-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +{{- end }} diff --git a/charts/0.0.3/templates/rbac/controller/auth_proxy_role_binding.yaml b/charts/0.0.3/templates/rbac/controller/auth_proxy_role_binding.yaml new file mode 100644 index 0000000..a874a2c --- /dev/null +++ b/charts/0.0.3/templates/rbac/controller/auth_proxy_role_binding.yaml @@ -0,0 +1,21 @@ +{{- if eq .Values.controller.rbacProxy.enable true }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: proxy-rolebinding + app.kubernetes.io/component: kube-rbac-proxy + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Release.Name }}-proxy-role +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-controller-manager + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/0.0.3/templates/rbac/controller/leader_election_role.yaml b/charts/0.0.3/templates/rbac/controller/leader_election_role.yaml new file mode 100644 index 0000000..b579d48 --- /dev/null +++ b/charts/0.0.3/templates/rbac/controller/leader_election_role.yaml @@ -0,0 +1,43 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/name: role + app.kubernetes.io/instance: leader-election-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-leader-election-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/charts/0.0.3/templates/rbac/controller/leader_election_role_binding.yaml b/charts/0.0.3/templates/rbac/controller/leader_election_role_binding.yaml new file mode 100644 index 0000000..80f5c15 --- /dev/null +++ b/charts/0.0.3/templates/rbac/controller/leader_election_role_binding.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/name: rolebinding + app.kubernetes.io/instance: leader-election-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Release.Name }}-leader-election-role +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-controller-manager + namespace: {{ .Release.Namespace }} diff --git a/config/samples/cluster_role.yaml b/charts/0.0.3/templates/rbac/controller/role.yaml similarity index 77% rename from config/samples/cluster_role.yaml rename to charts/0.0.3/templates/rbac/controller/role.yaml index 45c7ac9..2973ce3 100644 --- a/config/samples/cluster_role.yaml +++ b/charts/0.0.3/templates/rbac/controller/role.yaml @@ -1,21 +1,8 @@ -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: operator-manager-rb -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: operator-manager-role -subjects: - - kind: ServiceAccount - name: syngit-controller-manager - namespace: syngit-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: operator-manager-role - namespace: operator-system + name: {{ .Release.Name }}-manager-role rules: # Any resources can be pushed to the git repo. # The scope depends but the controller @@ -28,7 +15,7 @@ rules: - get - list - watch -# Create and patch events related to syngit objects in any namespace +# Create and patch events related to kgio objects in any namespace - apiGroups: - "" resources: @@ -116,4 +103,3 @@ rules: - get - patch - update - diff --git a/charts/0.0.3/templates/rbac/controller/role_binding.yaml b/charts/0.0.3/templates/rbac/controller/role_binding.yaml new file mode 100644 index 0000000..6fea6d6 --- /dev/null +++ b/charts/0.0.3/templates/rbac/controller/role_binding.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/name: clusterrolebinding + app.kubernetes.io/instance: manager-rolebinding + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ .Release.Name }}-manager-role +subjects: +- kind: ServiceAccount + name: {{ .Release.Name }}-controller-manager + namespace: {{ .Release.Namespace }} diff --git a/charts/0.0.3/templates/rbac/controller/service_account.yaml b/charts/0.0.3/templates/rbac/controller/service_account.yaml new file mode 100644 index 0000000..5e9b742 --- /dev/null +++ b/charts/0.0.3/templates/rbac/controller/service_account.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/name: serviceaccount + app.kubernetes.io/instance: controller-manager-sa + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-controller-manager diff --git a/charts/0.0.3/templates/rbac/end-user/remotesyncer_editor_role.yaml b/charts/0.0.3/templates/rbac/end-user/remotesyncer_editor_role.yaml new file mode 100644 index 0000000..b2291d5 --- /dev/null +++ b/charts/0.0.3/templates/rbac/end-user/remotesyncer_editor_role.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: remotesyncers-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-remotesyncers-editor-role +rules: +- apiGroups: + - syngit.syngit.io + resources: + - remotesyncerss + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - syngit.syngit.io + resources: + - remotesyncerss/status + verbs: + - get diff --git a/charts/0.0.3/templates/rbac/end-user/remotesyncer_viewer_role.yaml b/charts/0.0.3/templates/rbac/end-user/remotesyncer_viewer_role.yaml new file mode 100644 index 0000000..c15dd76 --- /dev/null +++ b/charts/0.0.3/templates/rbac/end-user/remotesyncer_viewer_role.yaml @@ -0,0 +1,26 @@ +# permissions for end users to view remotesyncerss. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: remotesyncers-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-remotesyncers-viewer-role +rules: +- apiGroups: + - syngit.syngit.io + resources: + - remotesyncerss + verbs: + - get + - list + - watch +- apiGroups: + - syngit.syngit.io + resources: + - remotesyncerss/status + verbs: + - get diff --git a/charts/0.0.3/templates/rbac/end-user/remoteuser_editor_role.yaml b/charts/0.0.3/templates/rbac/end-user/remoteuser_editor_role.yaml new file mode 100644 index 0000000..f4a7af0 --- /dev/null +++ b/charts/0.0.3/templates/rbac/end-user/remoteuser_editor_role.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: remoteuser-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-remoteuser-editor-role +rules: +- apiGroups: + - syngit.syngit.io + resources: + - remoteusers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - syngit.syngit.io + resources: + - remoteusers/status + verbs: + - get diff --git a/charts/0.0.3/templates/rbac/end-user/remoteuser_viewer_role.yaml b/charts/0.0.3/templates/rbac/end-user/remoteuser_viewer_role.yaml new file mode 100644 index 0000000..e8def41 --- /dev/null +++ b/charts/0.0.3/templates/rbac/end-user/remoteuser_viewer_role.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: gitremote-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-gitremote-viewer-role +rules: +- apiGroups: + - syngit.syngit.io + resources: + - remoteusers + verbs: + - get + - list + - watch +- apiGroups: + - syngit.syngit.io + resources: + - remoteusers/status + verbs: + - get diff --git a/charts/0.0.3/templates/rbac/end-user/remoteuserbinding_editor_role.yaml b/charts/0.0.3/templates/rbac/end-user/remoteuserbinding_editor_role.yaml new file mode 100644 index 0000000..7f71339 --- /dev/null +++ b/charts/0.0.3/templates/rbac/end-user/remoteuserbinding_editor_role.yaml @@ -0,0 +1,30 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: remoteuserbinding-editor-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-remoteuserbinding-editor-role +rules: +- apiGroups: + - syngit.syngit.io + resources: + - remoteuserbindings + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - syngit.syngit.io + resources: + - remoteuserbindings/status + verbs: + - get diff --git a/charts/0.0.3/templates/rbac/end-user/remoteuserbinding_viewer_role.yaml b/charts/0.0.3/templates/rbac/end-user/remoteuserbinding_viewer_role.yaml new file mode 100644 index 0000000..99f85ca --- /dev/null +++ b/charts/0.0.3/templates/rbac/end-user/remoteuserbinding_viewer_role.yaml @@ -0,0 +1,26 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/name: clusterrole + app.kubernetes.io/instance: remoteuserbinding-viewer-role + app.kubernetes.io/component: rbac + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: {{ .Release.Name }}-remoteuserbinding-viewer-role +rules: +- apiGroups: + - syngit.syngit.io + resources: + - remoteuserbindings + verbs: + - get + - list + - watch +- apiGroups: + - syngit.syngit.io + resources: + - remoteuserbindings/status + verbs: + - get diff --git a/charts/0.0.3/templates/webhook/webhook-service.yaml b/charts/0.0.3/templates/webhook/webhook-service.yaml new file mode 100644 index 0000000..c715163 --- /dev/null +++ b/charts/0.0.3/templates/webhook/webhook-service.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: service + app.kubernetes.io/instance: webhook-crd-service + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: webhook-crd-service +spec: + ports: + - port: 443 + protocol: TCP + targetPort: 9443 + selector: + control-plane: controller-manager +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: service + app.kubernetes.io/instance: syngit-remote-syncer-webhook-service + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: {{ .Release.Name }} + app.kubernetes.io/part-of: {{ .Release.Name }} + name: syngit-remote-syncer-webhook-service +spec: + ports: + - port: 443 + protocol: TCP + targetPort: 9444 + selector: + control-plane: controller-manager \ No newline at end of file diff --git a/charts/0.0.3/templates/webhook/webhook.yaml b/charts/0.0.3/templates/webhook/webhook.yaml new file mode 100644 index 0000000..f3a768b --- /dev/null +++ b/charts/0.0.3/templates/webhook/webhook.yaml @@ -0,0 +1,50 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + name: {{ .Release.Namespace }}-validating-webhook-configuration + {{- if eq .Values.webhook.certmanager.enable true }} + annotations: + cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/operator-webhook-cert + {{- end }} +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-crd-service + namespace: {{ .Release.Namespace }} + path: /validate-kgio-dams-kgio-v1-gitremote + failurePolicy: Fail + name: vgitremote.kb.io + rules: + - apiGroups: + - kgio.dams.kgio + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - gitremotes + sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-crd-service + namespace: {{ .Release.Namespace }} + path: /validate-kgio-dams-kgio-v1-resourcesinterceptor + failurePolicy: Fail + name: vresourcesinterceptor.kb.io + rules: + - apiGroups: + - kgio.dams.kgio + apiVersions: + - v1 + operations: + - CREATE + - UPDATE + resources: + - resourcesinterceptors + sideEffects: None \ No newline at end of file diff --git a/charts/0.0.3/values.yaml b/charts/0.0.3/values.yaml new file mode 100644 index 0000000..621338e --- /dev/null +++ b/charts/0.0.3/values.yaml @@ -0,0 +1,66 @@ +webhook: + certmanager: + enable: true + certificate: + name: webhook-cert + secret: webhook-server-cert + +controller: + image: + prefix: ghcr.io/syngit-org + name: syngit + tag: 0.0.3 + + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false + privileged: false + runAsNonRoot: true + seccompProfile: + type: "RuntimeDefault" + capabilities: + drop: + - "ALL" + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + tolerations: [] + + metrics: + enable: false + bindAddress: 127.0.0.1:8080 + + rbacProxy: + enable: false + upstreamAddress: http://127.0.0.1:8080/ + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 5m + memory: 64Mi + securityContext: + runAsUser: 1000 + allowPrivilegeEscalation: false + privileged: false + runAsNonRoot: true + seccompProfile: + type: "RuntimeDefault" + capabilities: + drop: + - "ALL" + +monitoring: + enable: false + +installCRD: true + +configuration: + gitlab: true + github: true + bitbucket: true diff --git a/cmd/main.go b/cmd/main.go index 7b8036d..ac78a63 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -37,6 +37,7 @@ import ( syngitv1alpha1 "syngit.io/syngit/api/v1alpha1" syngitv2alpha2 "syngit.io/syngit/api/v2alpha2" + syngitv3alpha3 "syngit.io/syngit/api/v3alpha3" "syngit.io/syngit/internal/controller" //+kubebuilder:scaffold:imports ) @@ -51,6 +52,7 @@ func init() { utilruntime.Must(syngitv1alpha1.AddToScheme(scheme)) utilruntime.Must(syngitv2alpha2.AddToScheme(scheme)) + utilruntime.Must(syngitv3alpha3.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme } @@ -133,12 +135,6 @@ func main() { setupLog.Error(err, "unable to create controller", "controller", "RemoteUser") os.Exit(1) } - if os.Getenv("ENABLE_WEBHOOKS") != "false" { - if err = (&syngitv2alpha2.RemoteUser{}).SetupWebhookWithManager(mgr); err != nil { - setupLog.Error(err, "unable to create webhook", "webhook", "RemoteUser") - os.Exit(1) - } - } mgr.GetWebhookServer().Register("/reconcile-syngit-remoteuser-owner", &webhook.Admission{Handler: &controller.RemoteUserWebhookHandler{ Client: mgr.GetClient(), Decoder: admission.NewDecoder(mgr.GetScheme()), @@ -162,11 +158,17 @@ func main() { os.Exit(1) } if os.Getenv("ENABLE_WEBHOOKS") != "false" { - if err = (&syngitv2alpha2.RemoteSyncer{}).SetupWebhookWithManager(mgr); err != nil { + if err = (&syngitv3alpha3.RemoteSyncer{}).SetupWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "RemoteSyncer") os.Exit(1) } } + if os.Getenv("ENABLE_WEBHOOKS") != "false" { + if err = (&syngitv3alpha3.RemoteUser{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "RemoteUser") + os.Exit(1) + } + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/config/crd/bases/syngit.syngit.io_remotesyncers.yaml b/config/crd/bases/syngit.syngit.io_remotesyncers.yaml index d11d3a5..2d127f4 100644 --- a/config/crd/bases/syngit.syngit.io_remotesyncers.yaml +++ b/config/crd/bases/syngit.syngit.io_remotesyncers.yaml @@ -1044,6 +1044,552 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - name: v3alpha3 + schema: + openAPIV3Schema: + description: RemoteSyncer is the Schema for the remotesyncers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + branch: + type: string + bypassInterceptionSubjects: + items: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + type: array + commitProcess: + type: string + defaultBlockAppliedMessage: + type: string + defaultUnauthorizedUserMode: + type: string + defaultUser: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + excludedFields: + items: + type: string + type: array + excludedFieldsConfig: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + remoteRepository: + format: uri + type: string + rootPath: + type: string + scopedResources: + properties: + matchPolicy: + description: MatchPolicyType specifies the type of match policy. + type: string + objectSelector: + description: |- + A label selector is a label query over a set of resources. The result of matchLabels and + matchExpressions are ANDed. An empty label selector matches all objects. A null + label selector matches no objects. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + rules: + items: + description: |- + RuleWithOperations is a tuple of Operations and Resources. It is recommended to make + sure that all the tuple expansions are valid. + properties: + apiGroups: + description: |- + APIGroups is the API groups the resources belong to. '*' is all groups. + If '*' is present, the length of the slice must be one. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + apiVersions: + description: |- + APIVersions is the API versions the resources belong to. '*' is all versions. + If '*' is present, the length of the slice must be one. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + operations: + description: |- + Operations is the operations the admission hook cares about - CREATE, UPDATE, DELETE, CONNECT or * + for all of those operations and any future admission operations that are added. + If '*' is present, the length of the slice must be one. + Required. + items: + description: OperationType specifies an operation for + a request. + type: string + type: array + x-kubernetes-list-type: atomic + resources: + description: |- + Resources is a list of resources this rule applies to. + + + For example: + 'pods' means pods. + 'pods/log' means the log subresource of pods. + '*' means all resources, but not subresources. + 'pods/*' means all subresources of pods. + '*/scale' means all scale subresources. + '*/*' means all resources and their subresources. + + + If wildcard is present, the validation rule will ensure resources do not + overlap with each other. + + + Depending on the enclosing object, subresources might not be allowed. + Required. + items: + type: string + type: array + x-kubernetes-list-type: atomic + scope: + description: |- + scope specifies the scope of this rule. + Valid values are "Cluster", "Namespaced", and "*" + "Cluster" means that only cluster-scoped resources will match this rule. + Namespace API objects are cluster-scoped. + "Namespaced" means that only namespaced resources will match this rule. + "*" means that there are no scope restrictions. + Subresources match the scope of their parent resource. + Default is "*". + type: string + type: object + type: array + type: object + required: + - branch + - commitProcess + - defaultUnauthorizedUserMode + - remoteRepository + type: object + status: + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lastBypassedObjectState: + properties: + lastBypassObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastBypassObjectTime: + format: date-time + type: string + lastBypassObjectUserInfo: + description: |- + UserInfo holds the information about the user needed to implement the + user.Info interface. + properties: + extra: + additionalProperties: + description: ExtraValue masks the value so protobuf can + generate + items: + type: string + type: array + description: Any additional information provided by the authenticator. + type: object + groups: + description: The names of groups this user is a part of. + items: + type: string + type: array + x-kubernetes-list-type: atomic + uid: + description: |- + A unique value that identifies this user across time. If this user is + deleted and another user by the same name is added, they will have + different UIDs. + type: string + username: + description: The name that uniquely identifies this user among + all active users. + type: string + type: object + type: object + lastObservedObjectState: + properties: + lastObservedObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastObservedObjectTime: + format: date-time + type: string + lastObservedObjectUserInfo: + description: |- + UserInfo holds the information about the user needed to implement the + user.Info interface. + properties: + extra: + additionalProperties: + description: ExtraValue masks the value so protobuf can + generate + items: + type: string + type: array + description: Any additional information provided by the authenticator. + type: object + groups: + description: The names of groups this user is a part of. + items: + type: string + type: array + x-kubernetes-list-type: atomic + uid: + description: |- + A unique value that identifies this user across time. If this user is + deleted and another user by the same name is added, they will have + different UIDs. + type: string + username: + description: The name that uniquely identifies this user among + all active users. + type: string + type: object + type: object + lastPushedObjectState: + properties: + lastPushedGitUser: + type: string + lastPushedObject: + properties: + group: + type: string + name: + type: string + resource: + type: string + version: + type: string + required: + - group + - name + - resource + - version + type: object + lastPushedObjectCommitHash: + type: string + lastPushedObjectGitPath: + type: string + lastPushedObjectGitRepo: + type: string + lastPushedObjectState: + type: string + lastPushedObjectTime: + format: date-time + type: string + type: object + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/bases/syngit.syngit.io_remoteuserbindings.yaml b/config/crd/bases/syngit.syngit.io_remoteuserbindings.yaml index eeb3832..fb1a64d 100644 --- a/config/crd/bases/syngit.syngit.io_remoteuserbindings.yaml +++ b/config/crd/bases/syngit.syngit.io_remoteuserbindings.yaml @@ -343,6 +343,172 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - name: v3alpha3 + schema: + openAPIV3Schema: + description: RemoteUserBinding is the Schema for the remoteuserbindings API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + remoteRefs: + items: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + type: array + subject: + description: |- + Subject contains a reference to the object or user identities a role binding applies to. This can either hold a direct API object reference, + or a value for non-objects such as user and group names. + properties: + apiGroup: + description: |- + APIGroup holds the API group of the referenced subject. + Defaults to "" for ServiceAccount subjects. + Defaults to "rbac.authorization.k8s.io" for User and Group subjects. + type: string + kind: + description: |- + Kind of object being referenced. Values defined by this API group are "User", "Group", and "ServiceAccount". + If the Authorizer does not recognized the kind value, the Authorizer should report an error. + type: string + name: + description: Name of the object being referenced. + type: string + namespace: + description: |- + Namespace of the referenced object. If the object kind is non-namespace, such as "User" or "Group", and this value is not empty + the Authorizer should report an error. + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + required: + - remoteRefs + - subject + type: object + status: + properties: + gitUserHosts: + items: + properties: + gitFQDN: + type: string + lastUsedTime: + format: date-time + type: string + remoteUserUsed: + type: string + secretRef: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference + a secret resource. + type: string + namespace: + description: namespace defines the space within which the + secret name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + state: + type: string + required: + - secretRef + type: object + type: array + lastUsedTime: + format: date-time + type: string + state: + type: string + userKubernetesID: + type: string + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/bases/syngit.syngit.io_remoteusers.yaml b/config/crd/bases/syngit.syngit.io_remoteusers.yaml index 50f393c..3d057b5 100644 --- a/config/crd/bases/syngit.syngit.io_remoteusers.yaml +++ b/config/crd/bases/syngit.syngit.io_remoteusers.yaml @@ -450,6 +450,227 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - name: v3alpha3 + schema: + openAPIV3Schema: + description: RemoteUser is the Schema for the remoteusers API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + properties: + customGitServerConfigRef: + description: |- + ObjectReference contains enough information to let you inspect or modify the referred object. + --- + New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. + 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. + 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular + restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". + Those cannot be well described when embedded. + 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. + 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity + during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple + and the version of the actual struct is irrelevant. + 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type + will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. + + + Instead of using this type, create a locally provided and used type that is well-focused on your reference. + For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: |- + If referring to a piece of an object instead of an entire object, this string + should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within a pod, this would take on a value like: + "spec.containers{name}" (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" (container with + index 2 in this pod). This syntax is chosen only to have some well-defined way of + referencing a part of an object. + TODO: this design is not final and this field is subject to change in the future. + type: string + kind: + description: |- + Kind of the referent. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + namespace: + description: |- + Namespace of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/ + type: string + resourceVersion: + description: |- + Specific resourceVersion to which this reference is made, if any. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency + type: string + uid: + description: |- + UID of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids + type: string + type: object + x-kubernetes-map-type: atomic + email: + type: string + gitBaseDomainFQDN: + type: string + insecureSkipTlsVerify: + type: boolean + ownRemoteUserBinding: + type: boolean + secretRef: + description: |- + SecretReference represents a Secret Reference. It has enough information to retrieve secret + in any namespace + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + testAuthentication: + type: boolean + required: + - email + - gitBaseDomainFQDN + - ownRemoteUserBinding + - secretRef + type: object + status: + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + connexionStatus: + properties: + details: + type: string + status: + type: string + type: object + gitServerConfiguration: + properties: + authenticationEndpoint: + type: string + caBundle: + type: string + inherited: + type: boolean + insecureSkipTlsVerify: + type: boolean + type: object + gitUser: + type: string + lastAuthTime: + format: date-time + type: string + secretBoundStatus: + type: string + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index a8213b9..b0cd736 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -20,7 +20,6 @@ patches: # - path: patches/cainjection_in_remoteusers.yaml #- path: patches/cainjection_in_remoteuserbindings.yaml # - path: patches/cainjection_in_remotesyncers.yaml -#- path: patches/cainjection_in_remoteusers.yaml #+kubebuilder:scaffold:crdkustomizecainjectionpatch # [WEBHOOK] To enable webhook, uncomment the following section diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index a0ebe1d..7642fdc 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -25,9 +25,24 @@ rules: - update - watch - apiGroups: - - syngit.syngit.io + - corev1 + resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - corev1 + resources: + - events + verbs: + - create + - patch +- apiGroups: + - corev1 resources: - - remoteUser + - secrets verbs: - get - list @@ -84,3 +99,29 @@ rules: - get - patch - update +- apiGroups: + - syngit.syngit.io + resources: + - remoteusers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - syngit.syngit.io + resources: + - remoteusers/finalizers + verbs: + - update +- apiGroups: + - syngit.syngit.io + resources: + - remoteusers/status + verbs: + - get + - patch + - update diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index a14c584..6ff1dc8 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -3,5 +3,7 @@ resources: - syngit_v2alpha2_remoteuser.yaml - syngit_v2alpha2_remoteuserbinding.yaml - syngit_v2alpha2_remotesyncer.yaml -- syngit_v2alpha2_remoteuser.yaml +- syngit_v3alpha3_remotesyncer.yaml +- syngit_v3alpha3_remoteuser.yaml +- syngit_v3alpha3_remoteuserbinding.yaml #+kubebuilder:scaffold:manifestskustomizesamples diff --git a/config/samples/v3alpha3/syngit_v3alpha3_remotesyncer.yaml b/config/samples/v3alpha3/syngit_v3alpha3_remotesyncer.yaml new file mode 100644 index 0000000..222c353 --- /dev/null +++ b/config/samples/v3alpha3/syngit_v3alpha3_remotesyncer.yaml @@ -0,0 +1,12 @@ +apiVersion: syngit.syngit.io/v3alpha3 +kind: RemoteSyncer +metadata: + labels: + app.kubernetes.io/name: remotesyncer + app.kubernetes.io/instance: remotesyncer-sample + app.kubernetes.io/part-of: syngit + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: syngit + name: remotesyncer-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/v3alpha3/syngit_v3alpha3_remoteuser.yaml b/config/samples/v3alpha3/syngit_v3alpha3_remoteuser.yaml new file mode 100644 index 0000000..b70f2d6 --- /dev/null +++ b/config/samples/v3alpha3/syngit_v3alpha3_remoteuser.yaml @@ -0,0 +1,12 @@ +apiVersion: syngit.syngit.io/v3alpha3 +kind: RemoteUser +metadata: + labels: + app.kubernetes.io/name: remoteuser + app.kubernetes.io/instance: remoteuser-sample + app.kubernetes.io/part-of: syngit + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: syngit + name: remoteuser-sample +spec: + # TODO(user): Add fields here diff --git a/config/samples/v3alpha3/syngit_v3alpha3_remoteuserbinding.yaml b/config/samples/v3alpha3/syngit_v3alpha3_remoteuserbinding.yaml new file mode 100644 index 0000000..e259fc4 --- /dev/null +++ b/config/samples/v3alpha3/syngit_v3alpha3_remoteuserbinding.yaml @@ -0,0 +1,12 @@ +apiVersion: syngit.syngit.io/v3alpha3 +kind: RemoteUserBinding +metadata: + labels: + app.kubernetes.io/name: remoteuserbinding + app.kubernetes.io/instance: remoteuserbinding-sample + app.kubernetes.io/part-of: syngit + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/created-by: syngit + name: remoteuserbinding-sample +spec: + # TODO(user): Add fields here diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index c325f7c..c11fbe7 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -10,14 +10,14 @@ webhooks: service: name: webhook-service namespace: system - path: /validate-syngit-syngit-io-v2alpha2-remotesyncer + path: /validate-syngit-syngit-io-v3alpha3-remotesyncer failurePolicy: Fail name: vremotesyncer.kb.io rules: - apiGroups: - syngit.syngit.io apiVersions: - - v2alpha2 + - v3alpha3 operations: - CREATE - UPDATE @@ -30,14 +30,14 @@ webhooks: service: name: webhook-service namespace: system - path: /validate-syngit-syngit-io-v2alpha2-remoteuser + path: /validate-syngit-syngit-io-v3alpha3-remoteuser failurePolicy: Fail name: vremoteuser.kb.io rules: - apiGroups: - syngit.syngit.io apiVersions: - - v2alpha2 + - v3alpha3 operations: - CREATE - UPDATE @@ -57,7 +57,7 @@ webhooks: - apiGroups: - syngit.syngit.io apiVersions: - - v2alpha2 + - v3alpha3 operations: - CREATE - DELETE diff --git a/internal/controller/dynamic_webhook_handlers.go b/internal/controller/dynamic_webhook_handlers.go index 3c53643..269f999 100644 --- a/internal/controller/dynamic_webhook_handlers.go +++ b/internal/controller/dynamic_webhook_handlers.go @@ -15,7 +15,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" logf "sigs.k8s.io/controller-runtime/pkg/log" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" ) type WebhookInterceptsAll struct { diff --git a/internal/controller/git_pusher.go b/internal/controller/git_pusher.go index 386a9ca..97585a7 100644 --- a/internal/controller/git_pusher.go +++ b/internal/controller/git_pusher.go @@ -16,7 +16,7 @@ import ( admissionv1 "k8s.io/api/admission/v1" "k8s.io/apimachinery/pkg/runtime/schema" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" ) type GitPusher struct { @@ -101,8 +101,11 @@ func (gp *GitPusher) Push() (GitPushResponse, error) { func (gp *GitPusher) pathConstructor(w *git.Worktree) (string, error) { gvr := gp.interceptedGVR - tempPath := gp.remoteSyncer.Spec.RootPath - tempPath += "/" + gp.remoteSyncer.Namespace + "/" + gvr.Group + "/" + gvr.Version + "/" + gvr.Resource + "/" + tempPath := "" + if gp.remoteSyncer.Spec.RootPath != "" { + tempPath += gp.remoteSyncer.Spec.RootPath + "/" + } + tempPath += gp.remoteSyncer.Namespace + "/" + gvr.Group + "/" + gvr.Version + "/" + gvr.Resource + "/" path, err := gp.validatePath(tempPath) if err != nil { diff --git a/internal/controller/reconcile_remoteuser_owner.go b/internal/controller/reconcile_remoteuser_owner.go index 08adb30..1d2afd2 100644 --- a/internal/controller/reconcile_remoteuser_owner.go +++ b/internal/controller/reconcile_remoteuser_owner.go @@ -10,7 +10,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" ) /* diff --git a/internal/controller/remotesyncer_controller.go b/internal/controller/remotesyncer_controller.go index 07c05c6..0e845ce 100644 --- a/internal/controller/remotesyncer_controller.go +++ b/internal/controller/remotesyncer_controller.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" ) // RemoteSyncerReconciler reconciles a RemoteSyncer object diff --git a/internal/controller/remotesyncer_controller_test.go b/internal/controller/remotesyncer_controller_test.go index 58d1000..b5cbfcc 100644 --- a/internal/controller/remotesyncer_controller_test.go +++ b/internal/controller/remotesyncer_controller_test.go @@ -27,7 +27,7 @@ package controller // metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -// syngit "syngit.io/syngit/api/v2alpha2" +// syngit "syngit.io/syngit/api/v3alpha3" // ) // var _ = Describe("RemoteSyncer Controller", func() { diff --git a/internal/controller/remoteuser_controller.go b/internal/controller/remoteuser_controller.go index db60c61..f70cb0e 100644 --- a/internal/controller/remoteuser_controller.go +++ b/internal/controller/remoteuser_controller.go @@ -40,7 +40,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" ) // RemoteUserReconciler reconciles a RemoteUser object @@ -106,6 +106,7 @@ func (r *RemoteUserReconciler) setServerConfiguration(ctx context.Context, remot // +kubebuilder:rbac:groups=corev1,resources=secrets,verbs=get;list;watch // +kubebuilder:rbac:groups=corev1,resources=configmaps,verbs=get;list;watch // +kubebuilder:rbac:groups=corev1,resources=events,verbs=create;patch + func (r *RemoteUserReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { _ = log.FromContext(ctx) diff --git a/internal/controller/remoteuser_controller_test.go b/internal/controller/remoteuser_controller_test.go index bd8d87f..65678de 100644 --- a/internal/controller/remoteuser_controller_test.go +++ b/internal/controller/remoteuser_controller_test.go @@ -28,65 +28,110 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" ) var _ = Describe("RemoteUser Controller", func() { + + const ( + timeout = time.Second * 10 + duration = time.Second * 10 + interval = time.Millisecond * 250 + + userNamespace = "default" + resourceName = "test-remoteuser" + ) + + const remoteGitServerConfName = "sample-git-server.com-conf" + confNamespacedName := types.NamespacedName{ + Name: remoteGitServerConfName, + Namespace: userNamespace, + } + remoteGitServerConf := &corev1.ConfigMap{} + + const secretRefName = "sample-secret" + secretNamespacedName := types.NamespacedName{ + Name: secretRefName, + Namespace: userNamespace, + } + secretRef := &corev1.Secret{} + const username = "username" + const password = "password" + + defaultGitServerConfiguration := syngit.GitServerConfiguration{ + AuthenticationEndpoint: "", + InsecureSkipTlsVerify: false, + CaBundle: "", + } + customGitServerConfigiguration := syngit.GitServerConfiguration{ + AuthenticationEndpoint: "https://sample-git-server.com/api/v4/user", + InsecureSkipTlsVerify: false, + CaBundle: "CA Bundle cert", + } + const actualInsecureSkipTlsVerify = true + + const resourceNameOwned = resourceName + "-owned-by-rub" + typeNamespacedNameOwned := types.NamespacedName{ + Name: resourceNameOwned, + Namespace: userNamespace, + } + const resourceNameCustomGit = resourceName + "-custom-git-conf" + typeNamespacedNameCustomGit := types.NamespacedName{ + Name: resourceNameCustomGit, + Namespace: userNamespace, + } + Context("When reconciling a resource", func() { ctx := context.Background() - const ( - timeout = time.Second * 10 - duration = time.Second * 10 - interval = time.Millisecond * 250 - - userNamespace = "default" - resourceName = "test-remoteuser" - ) - - const remoteGitServerName = "sample-git-server.com-conf" - confNamespacedName := types.NamespacedName{ - Name: remoteGitServerName, - Namespace: userNamespace, - } - remoteGitServerConf := &corev1.ConfigMap{} - - defaultGitServerConfiguration := syngit.GitServerConfiguration{ - AuthenticationEndpoint: "", - InsecureSkipTlsVerify: false, - CaBundle: "", - } - - typeNamespacedName := types.NamespacedName{ - Name: resourceName, - Namespace: userNamespace, - } - remoteuser := &syngit.RemoteUser{} - BeforeEach(func() { - By("creating the custom remote git server configuration") + By("Creating the custom remote git server configuration") err := k8sClient.Get(ctx, confNamespacedName, remoteGitServerConf) if err != nil && errors.IsNotFound(err) { resource := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: remoteGitServerName, + Name: remoteGitServerConfName, Namespace: userNamespace, }, Data: map[string]string{ - "authenticationEndpoint": "https://sample-git-server.com/api/v4/user", - "caBundle": "CA Bundle cert", - "insecureSkipTlsVerify": "true", + "authenticationEndpoint": customGitServerConfigiguration.AuthenticationEndpoint, + "caBundle": customGitServerConfigiguration.CaBundle, + "insecureSkipTlsVerify": func() string { + if customGitServerConfigiguration.InsecureSkipTlsVerify { + return "true" + } else { + return "false" + } + }(), }, } Expect(k8sClient.Create(ctx, resource)).To(Succeed()) } + By("Creating the secret credentials") + err = k8sClient.Get(ctx, secretNamespacedName, secretRef) + if err != nil && errors.IsNotFound(err) { + resource := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: secretRefName, + Namespace: userNamespace, + }, + StringData: map[string]string{ + "username": username, + "password": password, + }, + } + Expect(k8sClient.Create(ctx, resource)).To(Succeed()) + } + + remoteuser := &syngit.RemoteUser{} + By("Creating a RemoteUser that owns a RemoteUserBinding and is bound to a config") - err = k8sClient.Get(ctx, typeNamespacedName, remoteuser) + err = k8sClient.Get(ctx, typeNamespacedNameOwned, remoteuser) if err != nil && errors.IsNotFound(err) { resource := &syngit.RemoteUser{ ObjectMeta: metav1.ObjectMeta{ - Name: resourceName, + Name: resourceNameOwned, Namespace: userNamespace, }, Spec: syngit.RemoteUserSpec{ @@ -94,6 +139,34 @@ var _ = Describe("RemoteUser Controller", func() { GitBaseDomainFQDN: "sample-git-server.com", OwnRemoteUserBinding: true, TestAuthentication: false, + SecretRef: corev1.SecretReference{ + Name: secretRefName, + }, + }, + } + Expect(k8sClient.Create(ctx, resource)).To(Succeed()) + } + + By("Creating a RemoteUser that inherit from a remote git sever configuration") + err = k8sClient.Get(ctx, typeNamespacedNameCustomGit, remoteuser) + if err != nil && errors.IsNotFound(err) { + resource := &syngit.RemoteUser{ + ObjectMeta: metav1.ObjectMeta{ + Name: resourceNameCustomGit, + Namespace: userNamespace, + }, + Spec: syngit.RemoteUserSpec{ + Email: "sample@email.com", + GitBaseDomainFQDN: "sample-git-server.com", + OwnRemoteUserBinding: false, + TestAuthentication: false, + InsecureSkipTlsVerify: actualInsecureSkipTlsVerify, + CustomGitServerConfigRef: corev1.ObjectReference{ + Name: remoteGitServerConfName, + }, + SecretRef: corev1.SecretReference{ + Name: secretRefName, + }, }, } Expect(k8sClient.Create(ctx, resource)).To(Succeed()) @@ -102,19 +175,30 @@ var _ = Describe("RemoteUser Controller", func() { AfterEach(func() { // TODO(user): Cleanup logic after each test, like removing the resource instance. - resource := &syngit.RemoteUser{} - err := k8sClient.Get(ctx, typeNamespacedName, resource) + resourceOwned := &syngit.RemoteUser{} + err := k8sClient.Get(ctx, typeNamespacedNameOwned, resourceOwned) + Expect(err).NotTo(HaveOccurred()) + + resourceGitConfig := &syngit.RemoteUser{} + err = k8sClient.Get(ctx, typeNamespacedNameCustomGit, resourceGitConfig) Expect(err).NotTo(HaveOccurred()) resourceConf := &corev1.ConfigMap{} err = k8sClient.Get(ctx, confNamespacedName, resourceConf) Expect(err).NotTo(HaveOccurred()) + resourceSecret := &corev1.Secret{} + err = k8sClient.Get(ctx, secretNamespacedName, resourceSecret) + Expect(err).NotTo(HaveOccurred()) + By("Cleanup the specific resource instance RemoteUser") - Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) + Expect(k8sClient.Delete(ctx, resourceOwned)).To(Succeed()) By("Cleanup the associated custom remote git server configuration") Expect(k8sClient.Delete(ctx, resourceConf)).To(Succeed()) + + By("Cleanup the associated credentials secret reference") + Expect(k8sClient.Delete(ctx, resourceSecret)).To(Succeed()) }) Context("When updating a RemoteUser", func() { @@ -132,7 +216,7 @@ var _ = Describe("RemoteUser Controller", func() { // }) It("Should have the configuration stored in the status", func() { - ruLookupKey := types.NamespacedName{Name: resourceName, Namespace: userNamespace} + ruLookupKey := types.NamespacedName{Name: resourceNameOwned, Namespace: userNamespace} createRemoteUser := &syngit.RemoteUser{} Eventually(func() bool { @@ -142,14 +226,28 @@ var _ = Describe("RemoteUser Controller", func() { Expect(createRemoteUser.Status.GitServerConfiguration).Should(Equal(defaultGitServerConfiguration)) - confBool := false - if remoteGitServerConf.Data["insecureSkipTlsVerify"] == "true" { - confBool = true - } - Expect(createRemoteUser.Status.GitServerConfiguration.CaBundle).Should(Equal(remoteGitServerConf.Data["caBundle"])) - Expect(createRemoteUser.Status.GitServerConfiguration.InsecureSkipTlsVerify).Should(Equal(confBool)) - Expect(createRemoteUser.Status.GitServerConfiguration.AuthenticationEndpoint).Should(Equal(remoteGitServerConf.Data["authenticationEndpoint"])) + Expect(createRemoteUser.Status.GitServerConfiguration.CaBundle).Should(Equal(defaultGitServerConfiguration.CaBundle)) + Expect(createRemoteUser.Status.GitServerConfiguration.InsecureSkipTlsVerify).Should(Equal(defaultGitServerConfiguration.InsecureSkipTlsVerify)) + Expect(createRemoteUser.Status.GitServerConfiguration.AuthenticationEndpoint).Should(Equal((defaultGitServerConfiguration.AuthenticationEndpoint))) + }) + }) + + Context("When updating a RemoteUser", func() { + + It("Should have the top configuration propagated", func() { + ruLookupKey := types.NamespacedName{Name: resourceNameCustomGit, Namespace: userNamespace} + createRemoteUser := &syngit.RemoteUser{} + + Eventually(func() bool { + err := k8sClient.Get(ctx, ruLookupKey, createRemoteUser) + return err == nil && createRemoteUser.Status.GitServerConfiguration.CaBundle != "" + }, timeout, interval).Should(BeTrue()) + + Expect(createRemoteUser.Status.GitServerConfiguration.CaBundle).Should(Equal(customGitServerConfigiguration.CaBundle)) + Expect(createRemoteUser.Status.GitServerConfiguration.InsecureSkipTlsVerify).Should(Equal(actualInsecureSkipTlsVerify)) + Expect(createRemoteUser.Status.GitServerConfiguration.AuthenticationEndpoint).Should(Equal(customGitServerConfigiguration.AuthenticationEndpoint)) }) }) }) + }) diff --git a/internal/controller/remoteuserbinding_controller.go b/internal/controller/remoteuserbinding_controller.go index 753908c..2b2152f 100644 --- a/internal/controller/remoteuserbinding_controller.go +++ b/internal/controller/remoteuserbinding_controller.go @@ -31,7 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" ) // RemoteUserBindingReconciler reconciles a RemoteUserBinding object @@ -44,7 +44,6 @@ type RemoteUserBindingReconciler struct { //+kubebuilder:rbac:groups=syngit.syngit.io,resources=remoteuserbindings,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=syngit.syngit.io,resources=remoteuserbindings/status,verbs=get;update;patch //+kubebuilder:rbac:groups=syngit.syngit.io,resources=remoteuserbindings/finalizers,verbs=update -//+kubebuilder:rbac:groups=syngit.syngit.io,resources=remoteUser,verbs=get;list;watch func (r *RemoteUserBindingReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { _ = log.FromContext(ctx) diff --git a/internal/controller/remoteuserbinding_controller_test.go b/internal/controller/remoteuserbinding_controller_test.go index 8f8136f..fc5cbbe 100644 --- a/internal/controller/remoteuserbinding_controller_test.go +++ b/internal/controller/remoteuserbinding_controller_test.go @@ -27,7 +27,7 @@ package controller // metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -// syngit "syngit.io/syngit/api/v2alpha2" +// syngit "syngit.io/syngit/api/v3alpha3" // ) // var _ = Describe("RemoteUserBinding Controller", func() { diff --git a/internal/controller/suite_test.go b/internal/controller/suite_test.go index 51dfeea..719930a 100644 --- a/internal/controller/suite_test.go +++ b/internal/controller/suite_test.go @@ -32,8 +32,10 @@ import ( "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" //+kubebuilder:scaffold:imports ) @@ -93,6 +95,11 @@ var _ = BeforeSuite(func() { }).SetupWithManager(k8sManager) Expect(err).ToNot(HaveOccurred()) + k8sManager.GetWebhookServer().Register("/reconcile-syngit-remoteuser-owner", &webhook.Admission{Handler: &RemoteUserWebhookHandler{ + Client: k8sManager.GetClient(), + Decoder: admission.NewDecoder(k8sManager.GetScheme()), + }}) + err = (&RemoteUserBindingReconciler{ Client: k8sManager.GetClient(), Scheme: k8sManager.GetScheme(), diff --git a/internal/controller/webhook_request_checker.go b/internal/controller/webhook_request_checker.go index 52768c4..8ffda17 100644 --- a/internal/controller/webhook_request_checker.go +++ b/internal/controller/webhook_request_checker.go @@ -8,14 +8,14 @@ import ( "sync" "github.com/go-logr/logr" + "gopkg.in/yaml.v3" admissionv1 "k8s.io/api/admission/v1" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/yaml" - syngit "syngit.io/syngit/api/v2alpha2" + syngit "syngit.io/syngit/api/v3alpha3" ) type gitUser struct { @@ -157,22 +157,21 @@ func (wrc *WebhookRequestChecker) userAllowed(details *wrcDetails) (bool, error) InsecureSkipTlsVerify: false, } + var remoteUserBindings = &syngit.RemoteUserBindingList{} + err = wrc.k8sClient.List(ctx, remoteUserBindings, client.InNamespace(wrc.remoteSyncer.Namespace)) + if err != nil { + errMsg := err.Error() + details.messageAddition = errMsg + return false, errors.New(errMsg) + } + userCountLoop := 0 // Prevent non-unique name attack - for _, ref := range wrc.remoteSyncer.Spec.AuthorizedUsers { - namespacedName := &types.NamespacedName{ - Namespace: wrc.remoteSyncer.Namespace, - Name: ref.Name, - } - remoteUserBinding := &syngit.RemoteUserBinding{} - err := wrc.k8sClient.Get(ctx, *namespacedName, remoteUserBinding) - if err != nil { - continue - } + for _, remoteUserBinding := range remoteUserBindings.Items { // The subject name can not be unique -> in specific conditions, a commit can be done as another user // Need to be studied if remoteUserBinding.Spec.Subject.Name == incomingUser.Username { - remoteConf, gitUser, err = wrc.searchForGitToken(*remoteUserBinding, fqdn, remoteConf) + remoteConf, gitUser, err = wrc.searchForGitTokenFromRemoteUserBinding(remoteUserBinding, fqdn, remoteConf) if err != nil { errMsg := err.Error() details.messageAddition = errMsg @@ -183,10 +182,35 @@ func (wrc *WebhookRequestChecker) userAllowed(details *wrcDetails) (bool, error) } if userCountLoop == 0 { - errMsg := "no RemoteUserBinding found for the user " + incomingUser.Username - details.messageAddition = errMsg - return false, errors.New(errMsg) + + // Check if there is a default user that we can use + if wrc.remoteSyncer.Spec.DefaultUnauthorizedUserMode != syngit.UseDefaultUser || wrc.remoteSyncer.Spec.DefaultUser.Name == "" { + errMsg := "no RemoteUserBinding found for the user " + incomingUser.Username + details.messageAddition = errMsg + return false, errors.New(errMsg) + } + + // Search for the default RemoteUser object + namespacedName := &types.NamespacedName{ + Namespace: wrc.remoteSyncer.Namespace, + Name: wrc.remoteSyncer.Spec.DefaultUser.Name, + } + remoteUser := &syngit.RemoteUser{} + err := wrc.k8sClient.Get(ctx, *namespacedName, remoteUser) + if err != nil { + errMsg := "the default user is not found : " + wrc.remoteSyncer.Spec.DefaultUser.Name + details.messageAddition = errMsg + return false, err + } + + remoteConf, gitUser, err = wrc.searchForGitToken(*remoteUser, fqdn, remoteConf) + if err != nil { + errMsg := err.Error() + details.messageAddition = errMsg + return false, err + } } + if userCountLoop > 1 { const errMsg = "multiple RemoteUserBinding found OR the name of the user is not unique; this version of the operator work with the name as unique identifier for users" details.messageAddition = errMsg @@ -199,38 +223,23 @@ func (wrc *WebhookRequestChecker) userAllowed(details *wrcDetails) (bool, error) return true, nil } -func (wrc *WebhookRequestChecker) searchForGitToken(gub syngit.RemoteUserBinding, fqdn string, remoteConf *syngit.GitServerConfiguration) (*syngit.GitServerConfiguration, *gitUser, error) { +func (wrc *WebhookRequestChecker) searchForGitToken(remoteUser syngit.RemoteUser, fqdn string, remoteConf *syngit.GitServerConfiguration) (*syngit.GitServerConfiguration, *gitUser, error) { userGitName := "" userGitEmail := "" userGitToken := "" + namespace := wrc.remoteSyncer.Namespace - remoteUserCount := 0 secretCount := 0 ctx := context.Background() - namespace := wrc.remoteSyncer.Namespace - for _, ref := range gub.Spec.RemoteRefs { - namespacedName := &types.NamespacedName{ + if remoteUser.Spec.GitBaseDomainFQDN == fqdn { + secretNamespacedName := &types.NamespacedName{ Namespace: namespace, - Name: ref.Name, + Name: remoteUser.Spec.SecretRef.Name, } - remoteUser := &syngit.RemoteUser{} - err := wrc.k8sClient.Get(ctx, *namespacedName, remoteUser) - if err != nil { - continue - } - - remoteUserCount++ - if remoteUser.Spec.GitBaseDomainFQDN == fqdn { - secretNamespacedName := &types.NamespacedName{ - Namespace: namespace, - Name: remoteUser.Spec.SecretRef.Name, - } - secret := &corev1.Secret{} - err := wrc.k8sClient.Get(ctx, *secretNamespacedName, secret) - if err != nil { - continue - } + secret := &corev1.Secret{} + err := wrc.k8sClient.Get(ctx, *secretNamespacedName, secret) + if err == nil { userGitName = string(secret.Data["username"]) userGitToken = string(secret.Data["password"]) secretCount++ @@ -248,21 +257,50 @@ func (wrc *WebhookRequestChecker) searchForGitToken(gub syngit.RemoteUserBinding gitToken: userGitToken, } + if secretCount == 0 { + return remoteConf, gitUser, errors.New("no Secret found for the current user to log on the git repository with this fqdn : " + fqdn) + } + if userGitToken == "" { + return remoteConf, gitUser, errors.New("no token found in the secret; the token must be specified in the password field and the secret type must be kubernetes.io/basic-auth") + } + + return remoteConf, gitUser, nil +} + +func (wrc *WebhookRequestChecker) searchForGitTokenFromRemoteUserBinding(rub syngit.RemoteUserBinding, fqdn string, remoteConf *syngit.GitServerConfiguration) (*syngit.GitServerConfiguration, *gitUser, error) { + remoteUserCount := 0 + ctx := context.Background() + + var gitUser *gitUser + + namespace := wrc.remoteSyncer.Namespace + for _, ref := range rub.Spec.RemoteRefs { + namespacedName := &types.NamespacedName{ + Namespace: namespace, + Name: ref.Name, + } + remoteUser := &syngit.RemoteUser{} + err := wrc.k8sClient.Get(ctx, *namespacedName, remoteUser) + if err != nil { + continue + } + remoteUserCount++ + + remoteConf, gitUser, err = wrc.searchForGitToken(*remoteUser, fqdn, remoteConf) + if err != nil { + return remoteConf, gitUser, err + } + } + if remoteUserCount == 0 { return remoteConf, gitUser, errors.New("no RemoteUser found for the current user with this fqdn : " + fqdn) } if remoteUserCount > 1 { return remoteConf, gitUser, errors.New("more than one RemoteUser found for the current user with this fqdn : " + fqdn) } - if secretCount == 0 { - return remoteConf, gitUser, errors.New("no Secret found for the current user to log on the git repository with this fqdn : " + fqdn) - } if remoteUserCount > 1 { return remoteConf, gitUser, errors.New("more than one Secret found for the current user to log on the git repository with this fqdn : " + fqdn) } - if userGitToken == "" { - return remoteConf, gitUser, errors.New("no token found in the secret; the token must be specified in the password field and the secret type must be kubernetes.io/basic-auth") - } return remoteConf, gitUser, nil } @@ -317,6 +355,34 @@ func (wrc *WebhookRequestChecker) convertToYaml(details *wrcDetails) error { // Paths to remove paths := wrc.remoteSyncer.Spec.ExcludedFields + // Check if the excludedFields ConfigMap exists + if wrc.remoteSyncer.Spec.ExcludedFieldsConfig.Name != "" { + ctx := context.Background() + secretNamespacedName := &types.NamespacedName{ + Namespace: wrc.remoteSyncer.Namespace, + Name: wrc.remoteSyncer.Spec.ExcludedFieldsConfig.Name, + } + excludedFieldsConfig := &corev1.ConfigMap{} + err := wrc.k8sClient.Get(ctx, *secretNamespacedName, excludedFieldsConfig) + if err != nil { + errMsg := err.Error() + details.messageAddition = errMsg + return errors.New(errMsg) + } + yamlString := excludedFieldsConfig.Data["excludedFields"] + var excludedFields []string + + // Unmarshal the YAML string into the Go array + err = yaml.Unmarshal([]byte(yamlString), &excludedFields) + if err != nil { + errMsg := "failed to convert the excludedFields from the ConfigMap (wrong yaml format)" + details.messageAddition = errMsg + return errors.New(errMsg) + } + + paths = append(paths, excludedFields...) + } + // Remove unwanted fields for _, path := range paths { ExcludedFieldsFromJson(data, path)