mirror of
https://github.com/zalando/postgres-operator.git
synced 2026-10-08 01:22:27 +02:00
Use code-generation for CRD API and deepcopy methods (#369)
Client-go provides a https://github.com/kubernetes/code-generator package in order to provide the API to work with CRDs similar to the one available for built-in types, i.e. Pods, Statefulsets and so on. Use this package to generate deepcopy methods (required for CRDs), instead of using an external deepcopy package; we also generate APIs used to manipulate both Postgres and OperatorConfiguration CRDs, as well as informers and listers for the Postgres CRD, instead of using generic informers and CRD REST API; by using generated code we can get rid of some custom and obscure CRD-related code and use a better API. All generated code resides in /pkg/generated, with an exception of zz_deepcopy.go in apis/acid.zalan.do/v1 Rename postgres-operator-configuration CRD to OperatorConfiguration, since the former broke naming convention in the code-generator. Moved Postgresql, PostgresqlList, OperatorConfiguration and OperatorConfigurationList and other types used by them into Change the type of the Error field in the Postgresql crd to a string, so that client-go could generate a deepcopy for it. Use generated code to set status of CRD objects as well. Right now this is done with patch, however, Kubernetes 1.11 introduces the /status subresources, allowing us to set the status with the special updateStatus call in the future. For now, we keep the code that is compatible with earlier versions of Kubernetes. Rename postgresql.go to database.go and status.go to logs_and_api.go to reflect the purpose of each of those files. Update client-go dependencies. Minor reformatting and renaming.
This commit is contained in:
@@ -42,7 +42,7 @@ type Resources struct {
|
||||
|
||||
// Auth describes authentication specific configuration parameters
|
||||
type Auth struct {
|
||||
SecretNameTemplate stringTemplate `name:"secret_name_template" default:"{username}.{cluster}.credentials.{tprkind}.{tprgroup}"`
|
||||
SecretNameTemplate StringTemplate `name:"secret_name_template" default:"{username}.{cluster}.credentials.{tprkind}.{tprgroup}"`
|
||||
PamRoleName string `name:"pam_role_name" default:"zalandos"`
|
||||
PamConfiguration string `name:"pam_configuration" default:"https://info.example.com/oauth2/tokeninfo?access_token= uid realm=/employees"`
|
||||
TeamsAPIUrl string `name:"teams_api_url" default:"https://teams.example.com/api/"`
|
||||
@@ -93,9 +93,9 @@ type Config struct {
|
||||
EnableReplicaLoadBalancer bool `name:"enable_replica_load_balancer" default:"false"`
|
||||
// deprecated and kept for backward compatibility
|
||||
EnableLoadBalancer *bool `name:"enable_load_balancer"`
|
||||
MasterDNSNameFormat stringTemplate `name:"master_dns_name_format" default:"{cluster}.{team}.{hostedzone}"`
|
||||
ReplicaDNSNameFormat stringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"`
|
||||
PDBNameFormat stringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"`
|
||||
MasterDNSNameFormat StringTemplate `name:"master_dns_name_format" default:"{cluster}.{team}.{hostedzone}"`
|
||||
ReplicaDNSNameFormat StringTemplate `name:"replica_dns_name_format" default:"{cluster}-repl.{team}.{hostedzone}"`
|
||||
PDBNameFormat StringTemplate `name:"pdb_name_format" default:"postgres-{cluster}-pdb"`
|
||||
Workers uint32 `name:"workers" default:"4"`
|
||||
APIPort int `name:"api_port" default:"8080"`
|
||||
RingLogLines int `name:"ring_log_lines" default:"100"`
|
||||
|
||||
@@ -1,209 +0,0 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/mohae/deepcopy"
|
||||
)
|
||||
|
||||
type OperatorConfiguration struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Configuration OperatorConfigurationData `json:"configuration"`
|
||||
Error error `json:"-"`
|
||||
}
|
||||
|
||||
type OperatorConfigurationList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
Items []OperatorConfiguration `json:"items"`
|
||||
}
|
||||
|
||||
type PostgresUsersConfiguration struct {
|
||||
SuperUsername string `json:"super_username,omitempty"`
|
||||
ReplicationUsername string `json:"replication_username,omitempty"`
|
||||
}
|
||||
|
||||
type KubernetesMetaConfiguration struct {
|
||||
PodServiceAccountName string `json:"pod_service_account_name,omitempty"`
|
||||
// TODO: change it to the proper json
|
||||
PodServiceAccountDefinition string `json:"pod_service_account_definition,omitempty"`
|
||||
PodServiceAccountRoleBindingDefinition string `json:"pod_service_account_role_binding_definition,omitempty"`
|
||||
PodTerminateGracePeriod spec.Duration `json:"pod_terminate_grace_period,omitempty"`
|
||||
WatchedNamespace string `json:"watched_namespace,omitempty"`
|
||||
PDBNameFormat stringTemplate `json:"pdb_name_format,omitempty"`
|
||||
SecretNameTemplate stringTemplate `json:"secret_name_template,omitempty"`
|
||||
OAuthTokenSecretName spec.NamespacedName `json:"oauth_token_secret_name,omitempty"`
|
||||
InfrastructureRolesSecretName spec.NamespacedName `json:"infrastructure_roles_secret_name,omitempty"`
|
||||
PodRoleLabel string `json:"pod_role_label,omitempty"`
|
||||
ClusterLabels map[string]string `json:"cluster_labels,omitempty"`
|
||||
ClusterNameLabel string `json:"cluster_name_label,omitempty"`
|
||||
NodeReadinessLabel map[string]string `json:"node_readiness_label,omitempty"`
|
||||
// TODO: use a proper toleration structure?
|
||||
PodToleration map[string]string `json:"toleration,omitempty"`
|
||||
// TODO: use namespacedname
|
||||
PodEnvironmentConfigMap string `json:"pod_environment_configmap,omitempty"`
|
||||
PodPriorityClassName string `json:"pod_priority_class_name,omitempty"`
|
||||
}
|
||||
|
||||
type PostgresPodResourcesDefaults struct {
|
||||
DefaultCPURequest string `json:"default_cpu_request,omitempty"`
|
||||
DefaultMemoryRequest string `json:"default_memory_request,omitempty"`
|
||||
DefaultCPULimit string `json:"default_cpu_limit,omitempty"`
|
||||
DefaultMemoryLimit string `json:"default_memory_limit,omitempty"`
|
||||
}
|
||||
|
||||
type OperatorTimeouts struct {
|
||||
ResourceCheckInterval spec.Duration `json:"resource_check_interval,omitempty"`
|
||||
ResourceCheckTimeout spec.Duration `json:"resource_check_timeout,omitempty"`
|
||||
PodLabelWaitTimeout spec.Duration `json:"pod_label_wait_timeout,omitempty"`
|
||||
PodDeletionWaitTimeout spec.Duration `json:"pod_deletion_wait_timeout,omitempty"`
|
||||
ReadyWaitInterval spec.Duration `json:"ready_wait_interval,omitempty"`
|
||||
ReadyWaitTimeout spec.Duration `json:"ready_wait_timeout,omitempty"`
|
||||
}
|
||||
|
||||
type LoadBalancerConfiguration struct {
|
||||
DbHostedZone string `json:"db_hosted_zone,omitempty"`
|
||||
EnableMasterLoadBalancer bool `json:"enable_master_load_balancer,omitempty"`
|
||||
EnableReplicaLoadBalancer bool `json:"enable_replica_load_balancer,omitempty"`
|
||||
MasterDNSNameFormat stringTemplate `json:"master_dns_name_format,omitempty"`
|
||||
ReplicaDNSNameFormat stringTemplate `json:"replica_dns_name_format,omitempty"`
|
||||
}
|
||||
|
||||
type AWSGCPConfiguration struct {
|
||||
WALES3Bucket string `json:"wal_s3_bucket,omitempty"`
|
||||
AWSRegion string `json:"aws_region,omitempty"`
|
||||
LogS3Bucket string `json:"log_s3_bucket,omitempty"`
|
||||
KubeIAMRole string `json:"kube_iam_role,omitempty"`
|
||||
}
|
||||
|
||||
type OperatorDebugConfiguration struct {
|
||||
DebugLogging bool `json:"debug_logging,omitempty"`
|
||||
EnableDBAccess bool `json:"enable_database_access,omitempty"`
|
||||
}
|
||||
|
||||
type TeamsAPIConfiguration struct {
|
||||
EnableTeamsAPI bool `json:"enable_teams_api,omitempty"`
|
||||
TeamsAPIUrl string `json:"teams_api_url,omitempty"`
|
||||
TeamAPIRoleConfiguration map[string]string `json:"team_api_role_configuration,omitempty"`
|
||||
EnableTeamSuperuser bool `json:"enable_team_superuser,omitempty"`
|
||||
TeamAdminRole string `json:"team_admin_role,omitempty"`
|
||||
PamRoleName string `json:"pam_role_name,omitempty"`
|
||||
PamConfiguration string `json:"pam_configuration,omitempty"`
|
||||
ProtectedRoles []string `json:"protected_role_names,omitempty"`
|
||||
}
|
||||
|
||||
type LoggingRESTAPIConfiguration struct {
|
||||
APIPort int `json:"api_port,omitempty"`
|
||||
RingLogLines int `json:"ring_log_lines,omitempty"`
|
||||
ClusterHistoryEntries int `json:"cluster_history_entries,omitempty"`
|
||||
}
|
||||
|
||||
type ScalyrConfiguration struct {
|
||||
ScalyrAPIKey string `json:"scalyr_api_key,omitempty"`
|
||||
ScalyrImage string `json:"scalyr_image,omitempty"`
|
||||
ScalyrServerURL string `json:"scalyr_server_url,omitempty"`
|
||||
ScalyrCPURequest string `json:"scalyr_cpu_request,omitempty"`
|
||||
ScalyrMemoryRequest string `json:"scalyr_memory_request,omitempty"`
|
||||
ScalyrCPULimit string `json:"scalyr_cpu_limit,omitempty"`
|
||||
ScalyrMemoryLimit string `json:"scalyr_memory_limit,omitempty"`
|
||||
}
|
||||
|
||||
type OperatorConfigurationData struct {
|
||||
EtcdHost string `json:"etcd_host,omitempty"`
|
||||
DockerImage string `json:"docker_image,omitempty"`
|
||||
Workers uint32 `json:"workers,omitempty"`
|
||||
MinInstances int32 `json:"min_instances,omitempty"`
|
||||
MaxInstances int32 `json:"max_instances,omitempty"`
|
||||
ResyncPeriod spec.Duration `json:"resync_period,omitempty"`
|
||||
RepairPeriod spec.Duration `json:"repair_period,omitempty"`
|
||||
Sidecars map[string]string `json:"sidecar_docker_images,omitempty"`
|
||||
PostgresUsersConfiguration PostgresUsersConfiguration `json:"users"`
|
||||
Kubernetes KubernetesMetaConfiguration `json:"kubernetes"`
|
||||
PostgresPodResources PostgresPodResourcesDefaults `json:"postgres_pod_resources"`
|
||||
Timeouts OperatorTimeouts `json:"timeouts"`
|
||||
LoadBalancer LoadBalancerConfiguration `json:"load_balancer"`
|
||||
AWSGCP AWSGCPConfiguration `json:"aws_or_gcp"`
|
||||
OperatorDebug OperatorDebugConfiguration `json:"debug"`
|
||||
TeamsAPI TeamsAPIConfiguration `json:"teams_api"`
|
||||
LoggingRESTAPI LoggingRESTAPIConfiguration `json:"logging_rest_api"`
|
||||
Scalyr ScalyrConfiguration `json:"scalyr"`
|
||||
}
|
||||
|
||||
type OperatorConfigurationUsers struct {
|
||||
SuperUserName string `json:"superuser_name,omitempty"`
|
||||
Replication string `json:"replication_user_name,omitempty"`
|
||||
ProtectedRoles []string `json:"protected_roles,omitempty"`
|
||||
TeamAPIRoleConfiguration map[string]string `json:"team_api_role_configuration,omitempty"`
|
||||
}
|
||||
|
||||
type OperatorConfigurationCopy OperatorConfiguration
|
||||
type OperatorConfigurationListCopy OperatorConfigurationList
|
||||
|
||||
func (opc *OperatorConfiguration) UnmarshalJSON(data []byte) error {
|
||||
var ref OperatorConfigurationCopy
|
||||
if err := json.Unmarshal(data, &ref); err != nil {
|
||||
return err
|
||||
}
|
||||
*opc = OperatorConfiguration(ref)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opc *OperatorConfiguration) DeepCopyInto(out *OperatorConfiguration) {
|
||||
if opc != nil {
|
||||
*out = deepcopy.Copy(*opc).(OperatorConfiguration)
|
||||
}
|
||||
}
|
||||
|
||||
func (opc *OperatorConfiguration) DeepCopy() *OperatorConfiguration {
|
||||
if opc == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OperatorConfiguration)
|
||||
opc.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
func (opc *OperatorConfiguration) DeepCopyObject() runtime.Object {
|
||||
if c := opc.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opcl *OperatorConfigurationList) UnmarshalJSON(data []byte) error {
|
||||
var ref OperatorConfigurationListCopy
|
||||
if err := json.Unmarshal(data, &ref); err != nil {
|
||||
return nil
|
||||
}
|
||||
*opcl = OperatorConfigurationList(ref)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opcl *OperatorConfigurationList) DeepCopyInto(out *OperatorConfigurationList) {
|
||||
if opcl != nil {
|
||||
*out = deepcopy.Copy(*opcl).(OperatorConfigurationList)
|
||||
}
|
||||
}
|
||||
|
||||
func (opcl *OperatorConfigurationList) DeepCopy() *OperatorConfigurationList {
|
||||
if opcl == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OperatorConfigurationList)
|
||||
opcl.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
func (opcl *OperatorConfigurationList) DeepCopyObject() runtime.Object {
|
||||
if c := opcl.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -19,7 +19,7 @@ type fieldInfo struct {
|
||||
Field reflect.Value
|
||||
}
|
||||
|
||||
type stringTemplate string
|
||||
type StringTemplate string
|
||||
|
||||
func decoderFrom(field reflect.Value) (d decoder) {
|
||||
// it may be impossible for a struct field to fail this check
|
||||
@@ -172,7 +172,7 @@ func processField(value string, field reflect.Value) error {
|
||||
type parserState int
|
||||
|
||||
const (
|
||||
plain parserState = iota
|
||||
plain parserState = iota
|
||||
doubleQuoted
|
||||
singleQuoted
|
||||
)
|
||||
@@ -221,13 +221,13 @@ func getMapPairsFromString(value string) (pairs []string, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (f *stringTemplate) Decode(value string) error {
|
||||
*f = stringTemplate(value)
|
||||
func (f *StringTemplate) Decode(value string) error {
|
||||
*f = StringTemplate(value)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *stringTemplate) Format(a ...string) string {
|
||||
func (f *StringTemplate) Format(a ...string) string {
|
||||
res := string(*f)
|
||||
|
||||
for i := 0; i < len(a); i += 2 {
|
||||
@@ -237,6 +237,6 @@ func (f *stringTemplate) Format(a ...string) string {
|
||||
return res
|
||||
}
|
||||
|
||||
func (f stringTemplate) MarshalJSON() ([]byte, error) {
|
||||
func (f StringTemplate) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(string(f))
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
package constants
|
||||
|
||||
// Different properties of the PostgreSQL Custom Resource Definition
|
||||
const (
|
||||
PostgresCRDKind = "postgresql"
|
||||
PostgresCRDResource = "postgresqls"
|
||||
PostgresCRDShort = "pg"
|
||||
CRDGroup = "acid.zalan.do"
|
||||
CRDApiVersion = "v1"
|
||||
OperatorConfigCRDKind = "postgresql-operator-configuration"
|
||||
OperatorConfigCRDResource = "postgresql-operator-configurations"
|
||||
OperatorConfigCRDShort = "pgopconfig"
|
||||
)
|
||||
@@ -2,25 +2,22 @@ package k8sutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/constants"
|
||||
"k8s.io/api/core/v1"
|
||||
policybeta1 "k8s.io/api/policy/v1beta1"
|
||||
apiextclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
apiextbeta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/kubernetes/typed/apps/v1beta1"
|
||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
policyv1beta1 "k8s.io/client-go/kubernetes/typed/policy/v1beta1"
|
||||
rbacv1beta1 "k8s.io/client-go/kubernetes/typed/rbac/v1beta1"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"reflect"
|
||||
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/constants"
|
||||
acidv1client "github.com/zalando-incubator/postgres-operator/pkg/generated/clientset/versioned"
|
||||
)
|
||||
|
||||
// KubernetesClient describes getters for Kubernetes objects
|
||||
@@ -40,8 +37,8 @@ type KubernetesClient struct {
|
||||
policyv1beta1.PodDisruptionBudgetsGetter
|
||||
apiextbeta1.CustomResourceDefinitionsGetter
|
||||
|
||||
RESTClient rest.Interface
|
||||
CRDREST rest.Interface
|
||||
RESTClient rest.Interface
|
||||
AcidV1ClientSet *acidv1client.Clientset
|
||||
}
|
||||
|
||||
// RestConfig creates REST config
|
||||
@@ -87,27 +84,13 @@ func NewFromConfig(cfg *rest.Config) (KubernetesClient, error) {
|
||||
kubeClient.RESTClient = client.CoreV1().RESTClient()
|
||||
kubeClient.RoleBindingsGetter = client.RbacV1beta1()
|
||||
|
||||
cfg2 := *cfg
|
||||
cfg2.GroupVersion = &schema.GroupVersion{
|
||||
Group: constants.CRDGroup,
|
||||
Version: constants.CRDApiVersion,
|
||||
}
|
||||
cfg2.APIPath = constants.K8sAPIPath
|
||||
// MIGRATION: api.codecs -> scheme.Codecs?
|
||||
cfg2.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
crd, err := rest.RESTClientFor(&cfg2)
|
||||
if err != nil {
|
||||
return kubeClient, fmt.Errorf("could not get rest client: %v", err)
|
||||
}
|
||||
kubeClient.CRDREST = crd
|
||||
|
||||
apiextClient, err := apiextclient.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return kubeClient, fmt.Errorf("could not create api client:%v", err)
|
||||
}
|
||||
|
||||
kubeClient.CustomResourceDefinitionsGetter = apiextClient.ApiextensionsV1beta1()
|
||||
kubeClient.AcidV1ClientSet = acidv1client.NewForConfigOrDie(cfg)
|
||||
|
||||
return kubeClient, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user