初始化 PostgreSQL 租户控制器项目
Lint / Run on Ubuntu (push) Has been cancelled
E2E Tests / Run on Ubuntu (push) Has been cancelled
Tests / Run on Ubuntu (push) Has been cancelled

This commit is contained in:
2026-09-09 19:52:54 +00:00
commit 4ad94dc194
64 changed files with 4729 additions and 0 deletions
+44
View File
@@ -0,0 +1,44 @@
/*
Copyright 2026.
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 v1alpha1 contains API Schema definitions for the database v1alpha1 API group.
// +kubebuilder:object:generate=true
// +groupName=database.ddupan.top
package v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
var (
// SchemeGroupVersion is group version used to register these objects.
// This name is used by applyconfiguration generators (e.g. controller-gen).
SchemeGroupVersion = schema.GroupVersion{Group: "database.ddupan.top", Version: "v1alpha1"}
// GroupVersion is an alias for SchemeGroupVersion, for backward compatibility.
GroupVersion = SchemeGroupVersion
// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
SchemeBuilder = runtime.NewSchemeBuilder(func(scheme *runtime.Scheme) error {
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
})
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
+143
View File
@@ -0,0 +1,143 @@
/*
Copyright 2026.
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 v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// PostgreSQLInstanceSpec defines the desired state of PostgreSQLInstance
type PostgreSQLInstanceSpec struct {
// Endpoint is the PostgreSQL server managed by this instance.
// +required
Endpoint PostgreSQLEndpoint `json:"endpoint"`
// AdminCredentialRef points to an OpenBao KV secret containing the
// administrative login. Secret values are never copied into this resource.
// +required
AdminCredentialRef OpenBaoSecretReference `json:"adminCredentialRef"`
// AllowedExtensions is the allowlist tenants may request.
// +listType=set
// +optional
AllowedExtensions []string `json:"allowedExtensions,omitempty"`
}
// PostgreSQLEndpoint identifies a PostgreSQL server.
type PostgreSQLEndpoint struct {
// +required
Host string `json:"host"`
// +kubebuilder:default=5432
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
// +optional
Port int32 `json:"port,omitempty"`
// Database used for administrative connections.
// +kubebuilder:default=postgres
// +optional
Database string `json:"database,omitempty"`
// +kubebuilder:validation:Enum=disable;require;verify-ca;verify-full
// +kubebuilder:default=verify-full
// +optional
SSLMode string `json:"sslMode,omitempty"`
}
// OpenBaoSecretReference identifies keys in an OpenBao KV secret.
type OpenBaoSecretReference struct {
// +required
Path string `json:"path"`
// +kubebuilder:default=username
// +optional
UsernameKey string `json:"usernameKey,omitempty"`
// +kubebuilder:default=password
// +optional
PasswordKey string `json:"passwordKey,omitempty"`
}
// PostgreSQLInstanceStatus defines the observed state of PostgreSQLInstance.
type PostgreSQLInstanceStatus struct {
// ObservedGeneration is the most recent generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// PostgreSQLVersion is reported by the target server.
// +optional
PostgreSQLVersion string `json:"postgresqlVersion,omitempty"`
// conditions represent the current state of the PostgreSQLInstance resource.
// Each condition has a unique type and reflects the status of a specific aspect of the resource.
//
// Standard condition types include:
// - "Available": the resource is fully functional
// - "Progressing": the resource is being created or updated
// - "Degraded": the resource failed to reach or maintain its desired state
//
// The status of each condition is one of True, False, or Unknown.
// +listType=map
// +listMapKey=type
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Cluster,shortName=pginstance
// +kubebuilder:printcolumn:name="Endpoint",type=string,JSONPath=`.spec.endpoint.host`
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
// +kubebuilder:resource:scope=Cluster
// PostgreSQLInstance is the Schema for the postgresqlinstances API
type PostgreSQLInstance struct {
metav1.TypeMeta `json:",inline"`
// metadata is a standard object metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitzero"`
// spec defines the desired state of PostgreSQLInstance
// +required
Spec PostgreSQLInstanceSpec `json:"spec"`
// status defines the observed state of PostgreSQLInstance
// +optional
Status PostgreSQLInstanceStatus `json:"status,omitzero"`
}
// +kubebuilder:object:root=true
// PostgreSQLInstanceList contains a list of PostgreSQLInstance
type PostgreSQLInstanceList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitzero"`
Items []PostgreSQLInstance `json:"items"`
}
func init() {
SchemeBuilder.Register(func(s *runtime.Scheme) error {
s.AddKnownTypes(SchemeGroupVersion, &PostgreSQLInstance{}, &PostgreSQLInstanceList{})
return nil
})
}
+131
View File
@@ -0,0 +1,131 @@
/*
Copyright 2026.
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 v1alpha1
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// PostgreSQLTenantSpec defines the desired state of PostgreSQLTenant
type PostgreSQLTenantSpec struct {
// InstanceRef names the cluster-scoped PostgreSQLInstance to use.
// +required
InstanceRef string `json:"instanceRef"`
// Database defaults to metadata.name when omitted.
// +optional
Database string `json:"database,omitempty"`
// OwnerRole defaults to <database>_owner when omitted.
// +optional
OwnerRole string `json:"ownerRole,omitempty"`
// LoginRole defaults to metadata.name when omitted.
// +optional
LoginRole string `json:"loginRole,omitempty"`
// Extensions to install from the instance allowlist.
// +listType=set
// +optional
Extensions []string `json:"extensions,omitempty"`
// Credential configures the application login credential.
// +required
Credential PostgreSQLCredentialSpec `json:"credential"`
// DeletionPolicy controls whether deleting this object removes the database.
// +kubebuilder:validation:Enum=Retain;Delete
// +kubebuilder:default=Retain
// +optional
DeletionPolicy string `json:"deletionPolicy,omitempty"`
}
// PostgreSQLCredentialSpec describes where credentials live and when to rotate them.
type PostgreSQLCredentialSpec struct {
// OpenBaoPath is the KV path receiving the generated login credential.
// +required
OpenBaoPath string `json:"openBaoPath"`
}
// PostgreSQLTenantStatus defines the observed state of PostgreSQLTenant.
type PostgreSQLTenantStatus struct {
// ObservedGeneration is the most recent generation observed by the controller.
// +optional
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
// DatabaseOID is the server-side identity observed for the database.
// +optional
DatabaseOID uint32 `json:"databaseOID,omitempty"`
// conditions represent the current state of the PostgreSQLTenant resource.
// Each condition has a unique type and reflects the status of a specific aspect of the resource.
//
// Standard condition types include:
// - "Available": the resource is fully functional
// - "Progressing": the resource is being created or updated
// - "Degraded": the resource failed to reach or maintain its desired state
//
// The status of each condition is one of True, False, or Unknown.
// +listType=map
// +listMapKey=type
// +optional
Conditions []metav1.Condition `json:"conditions,omitempty"`
}
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:scope=Namespaced,shortName=pgtenant
// +kubebuilder:printcolumn:name="Instance",type=string,JSONPath=`.spec.instanceRef`
// +kubebuilder:printcolumn:name="Database",type=string,JSONPath=`.spec.database`
// +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
// PostgreSQLTenant is the Schema for the postgresqltenants API
type PostgreSQLTenant struct {
metav1.TypeMeta `json:",inline"`
// metadata is a standard object metadata
// +optional
metav1.ObjectMeta `json:"metadata,omitzero"`
// spec defines the desired state of PostgreSQLTenant
// +required
Spec PostgreSQLTenantSpec `json:"spec"`
// status defines the observed state of PostgreSQLTenant
// +optional
Status PostgreSQLTenantStatus `json:"status,omitzero"`
}
// +kubebuilder:object:root=true
// PostgreSQLTenantList contains a list of PostgreSQLTenant
type PostgreSQLTenantList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitzero"`
Items []PostgreSQLTenant `json:"items"`
}
func init() {
SchemeBuilder.Register(func(s *runtime.Scheme) error {
s.AddKnownTypes(SchemeGroupVersion, &PostgreSQLTenant{}, &PostgreSQLTenantList{})
return nil
})
}
+276
View File
@@ -0,0 +1,276 @@
//go:build !ignore_autogenerated
/*
Copyright 2026.
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 v1alpha1
import (
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OpenBaoSecretReference) DeepCopyInto(out *OpenBaoSecretReference) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OpenBaoSecretReference.
func (in *OpenBaoSecretReference) DeepCopy() *OpenBaoSecretReference {
if in == nil {
return nil
}
out := new(OpenBaoSecretReference)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PostgreSQLCredentialSpec) DeepCopyInto(out *PostgreSQLCredentialSpec) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLCredentialSpec.
func (in *PostgreSQLCredentialSpec) DeepCopy() *PostgreSQLCredentialSpec {
if in == nil {
return nil
}
out := new(PostgreSQLCredentialSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PostgreSQLEndpoint) DeepCopyInto(out *PostgreSQLEndpoint) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLEndpoint.
func (in *PostgreSQLEndpoint) DeepCopy() *PostgreSQLEndpoint {
if in == nil {
return nil
}
out := new(PostgreSQLEndpoint)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PostgreSQLInstance) DeepCopyInto(out *PostgreSQLInstance) {
*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 PostgreSQLInstance.
func (in *PostgreSQLInstance) DeepCopy() *PostgreSQLInstance {
if in == nil {
return nil
}
out := new(PostgreSQLInstance)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PostgreSQLInstance) 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 *PostgreSQLInstanceList) DeepCopyInto(out *PostgreSQLInstanceList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]PostgreSQLInstance, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLInstanceList.
func (in *PostgreSQLInstanceList) DeepCopy() *PostgreSQLInstanceList {
if in == nil {
return nil
}
out := new(PostgreSQLInstanceList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PostgreSQLInstanceList) 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 *PostgreSQLInstanceSpec) DeepCopyInto(out *PostgreSQLInstanceSpec) {
*out = *in
out.Endpoint = in.Endpoint
out.AdminCredentialRef = in.AdminCredentialRef
if in.AllowedExtensions != nil {
in, out := &in.AllowedExtensions, &out.AllowedExtensions
*out = make([]string, len(*in))
copy(*out, *in)
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLInstanceSpec.
func (in *PostgreSQLInstanceSpec) DeepCopy() *PostgreSQLInstanceSpec {
if in == nil {
return nil
}
out := new(PostgreSQLInstanceSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PostgreSQLInstanceStatus) DeepCopyInto(out *PostgreSQLInstanceStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLInstanceStatus.
func (in *PostgreSQLInstanceStatus) DeepCopy() *PostgreSQLInstanceStatus {
if in == nil {
return nil
}
out := new(PostgreSQLInstanceStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PostgreSQLTenant) DeepCopyInto(out *PostgreSQLTenant) {
*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 PostgreSQLTenant.
func (in *PostgreSQLTenant) DeepCopy() *PostgreSQLTenant {
if in == nil {
return nil
}
out := new(PostgreSQLTenant)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PostgreSQLTenant) 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 *PostgreSQLTenantList) DeepCopyInto(out *PostgreSQLTenantList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]PostgreSQLTenant, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLTenantList.
func (in *PostgreSQLTenantList) DeepCopy() *PostgreSQLTenantList {
if in == nil {
return nil
}
out := new(PostgreSQLTenantList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *PostgreSQLTenantList) 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 *PostgreSQLTenantSpec) DeepCopyInto(out *PostgreSQLTenantSpec) {
*out = *in
if in.Extensions != nil {
in, out := &in.Extensions, &out.Extensions
*out = make([]string, len(*in))
copy(*out, *in)
}
out.Credential = in.Credential
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLTenantSpec.
func (in *PostgreSQLTenantSpec) DeepCopy() *PostgreSQLTenantSpec {
if in == nil {
return nil
}
out := new(PostgreSQLTenantSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *PostgreSQLTenantStatus) DeepCopyInto(out *PostgreSQLTenantStatus) {
*out = *in
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]v1.Condition, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PostgreSQLTenantStatus.
func (in *PostgreSQLTenantStatus) DeepCopy() *PostgreSQLTenantStatus {
if in == nil {
return nil
}
out := new(PostgreSQLTenantStatus)
in.DeepCopyInto(out)
return out
}