mirror of
https://github.com/zalando/postgres-operator.git
synced 2026-10-08 01:42:23 +02:00
Make use of kubernetes client-go v4
* client-go v4.0.0-beta0 * remove unnecessary methods for tpr object * rest client: use interface instead of structure pointer * proper names for constants; some clean up for log messages * remove teams api client from controller and make it per cluster
This commit is contained in:
@@ -4,10 +4,7 @@ import "time"
|
||||
|
||||
// General kubernetes-related constants
|
||||
const (
|
||||
ListClustersURITemplate = "/apis/" + TPRVendor + "/" + TPRApiVersion + "/namespaces/%s/" + ResourceName // Namespace
|
||||
WatchClustersURITemplate = "/apis/" + TPRVendor + "/" + TPRApiVersion + "/watch/namespaces/%s/" + ResourceName // Namespace
|
||||
K8sVersion = "v1"
|
||||
K8sAPIPath = "/api"
|
||||
K8sAPIPath = "/apis"
|
||||
StatefulsetDeletionInterval = 1 * time.Second
|
||||
StatefulsetDeletionTimeout = 30 * time.Second
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ package constants
|
||||
|
||||
const (
|
||||
PasswordLength = 64
|
||||
UserSecretTemplate = "%s.%s.credentials." + TPRName + "." + TPRVendor // Username, ClusterName
|
||||
UserSecretTemplate = "%s.%s.credentials." + TPRKind + "." + TPRGroup // Username, ClusterName
|
||||
SuperuserKeyName = "superuser"
|
||||
ReplicationUserKeyName = "replication"
|
||||
RoleFlagSuperuser = "SUPERUSER"
|
||||
|
||||
@@ -2,9 +2,10 @@ package constants
|
||||
|
||||
// Different properties of the PostgreSQL Third Party Resources
|
||||
const (
|
||||
TPRName = "postgresql"
|
||||
TPRVendor = "acid.zalan.do"
|
||||
TPRKind = "postgresql"
|
||||
TPRGroup = "acid.zalan.do"
|
||||
TPRDescription = "Managed PostgreSQL clusters"
|
||||
TPRApiVersion = "v1"
|
||||
ResourceName = TPRName + "s"
|
||||
TPRName = TPRKind + "." + TPRGroup
|
||||
ResourceName = TPRKind + "s"
|
||||
)
|
||||
|
||||
@@ -37,5 +37,5 @@ func (c *Ext234Resize) ResizeFilesystem(deviceName string, commandExecutor func(
|
||||
(strings.Contains(out, "on-line resizing required") && ext2fsSuccessRegexp.MatchString(out)) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("unrecognized output: %s, assuming error", out)
|
||||
return fmt.Errorf("unrecognized output: %q, assuming error", out)
|
||||
}
|
||||
|
||||
+18
-29
@@ -1,22 +1,19 @@
|
||||
package k8sutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
v1beta1 "k8s.io/client-go/kubernetes/typed/apps/v1beta1"
|
||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
extensions "k8s.io/client-go/kubernetes/typed/extensions/v1beta1"
|
||||
"k8s.io/client-go/pkg/api"
|
||||
apierrors "k8s.io/client-go/pkg/api/errors"
|
||||
"k8s.io/client-go/pkg/api/unversioned"
|
||||
"k8s.io/client-go/pkg/runtime"
|
||||
"k8s.io/client-go/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/constants"
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/util/retryutil"
|
||||
)
|
||||
@@ -31,6 +28,7 @@ type KubernetesClient struct {
|
||||
v1core.ConfigMapsGetter
|
||||
v1beta1.StatefulSetsGetter
|
||||
extensions.ThirdPartyResourcesGetter
|
||||
RESTClient rest.Interface
|
||||
}
|
||||
|
||||
func NewFromKubernetesInterface(src kubernetes.Interface) (c KubernetesClient) {
|
||||
@@ -44,6 +42,7 @@ func NewFromKubernetesInterface(src kubernetes.Interface) (c KubernetesClient) {
|
||||
c.PersistentVolumesGetter = src.CoreV1()
|
||||
c.StatefulSetsGetter = src.AppsV1beta1()
|
||||
c.ThirdPartyResourcesGetter = src.ExtensionsV1beta1()
|
||||
c.RESTClient = src.CoreV1().RESTClient()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -51,6 +50,7 @@ func RestConfig(kubeConfig string, outOfCluster bool) (*rest.Config, error) {
|
||||
if outOfCluster {
|
||||
return clientcmd.BuildConfigFromFlags("", kubeConfig)
|
||||
}
|
||||
|
||||
return rest.InClusterConfig()
|
||||
}
|
||||
|
||||
@@ -66,35 +66,24 @@ func ResourceNotFound(err error) bool {
|
||||
return apierrors.IsNotFound(err)
|
||||
}
|
||||
|
||||
func KubernetesRestClient(c *rest.Config) (*rest.RESTClient, error) {
|
||||
c.GroupVersion = &unversioned.GroupVersion{Version: constants.K8sVersion}
|
||||
c.APIPath = constants.K8sAPIPath
|
||||
c.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
|
||||
|
||||
schemeBuilder := runtime.NewSchemeBuilder(
|
||||
func(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(
|
||||
unversioned.GroupVersion{
|
||||
Group: constants.TPRVendor,
|
||||
Version: constants.TPRApiVersion,
|
||||
},
|
||||
&spec.Postgresql{},
|
||||
&spec.PostgresqlList{},
|
||||
&api.ListOptions{},
|
||||
&api.DeleteOptions{},
|
||||
)
|
||||
return nil
|
||||
})
|
||||
if err := schemeBuilder.AddToScheme(api.Scheme); err != nil {
|
||||
return nil, fmt.Errorf("could not apply functions to register PostgreSQL TPR type: %v", err)
|
||||
func KubernetesRestClient(cfg rest.Config) (rest.Interface, error) {
|
||||
cfg.GroupVersion = &schema.GroupVersion{
|
||||
Group: constants.TPRGroup,
|
||||
Version: constants.TPRApiVersion,
|
||||
}
|
||||
cfg.APIPath = constants.K8sAPIPath
|
||||
cfg.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: api.Codecs}
|
||||
|
||||
return rest.RESTClientFor(c)
|
||||
return rest.RESTClientFor(&cfg)
|
||||
}
|
||||
|
||||
func WaitTPRReady(restclient rest.Interface, interval, timeout time.Duration, ns string) error {
|
||||
return retryutil.Retry(interval, timeout, func() (bool, error) {
|
||||
_, err := restclient.Get().RequestURI(fmt.Sprintf(constants.ListClustersURITemplate, ns)).DoRaw()
|
||||
_, err := restclient.
|
||||
Get().
|
||||
Namespace(ns).
|
||||
Resource(constants.ResourceName).
|
||||
DoRaw()
|
||||
if err != nil {
|
||||
if ResourceNotFound(err) { // not set up yet. wait more.
|
||||
return false, nil
|
||||
|
||||
@@ -66,11 +66,11 @@ func (s DefaultUserSyncStrategy) ExecuteSyncRequests(reqs []spec.PgSyncUserReque
|
||||
switch r.Kind {
|
||||
case spec.PGSyncUserAdd:
|
||||
if err := s.createPgUser(r.User, db); err != nil {
|
||||
return fmt.Errorf("could not create user '%s': %v", r.User.Name, err)
|
||||
return fmt.Errorf("could not create user %q: %v", r.User.Name, err)
|
||||
}
|
||||
case spec.PGsyncUserAlter:
|
||||
if err := s.alterPgUser(r.User, db); err != nil {
|
||||
return fmt.Errorf("could not alter user '%s': %v", r.User.Name, err)
|
||||
return fmt.Errorf("could not alter user %q: %v", r.User.Name, err)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unrecognized operation: %v", r.Kind)
|
||||
@@ -100,7 +100,7 @@ func (s DefaultUserSyncStrategy) createPgUser(user spec.PgUser, db *sql.DB) (err
|
||||
|
||||
_, err = db.Query(query) // TODO: Try several times
|
||||
if err != nil {
|
||||
err = fmt.Errorf("dB error: %s, query: %v", err, query)
|
||||
err = fmt.Errorf("dB error: %v, query: %q", err, query)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ func (s DefaultUserSyncStrategy) alterPgUser(user spec.PgUser, db *sql.DB) (err
|
||||
|
||||
_, err = db.Query(query) // TODO: Try several times
|
||||
if err != nil {
|
||||
err = fmt.Errorf("dB error: %s query %v", err, query)
|
||||
err = fmt.Errorf("dB error: %v query %q", err, query)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -8,7 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/motomux/pretty"
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||
)
|
||||
@@ -34,7 +34,7 @@ func RandomPassword(n int) string {
|
||||
}
|
||||
|
||||
// NameFromMeta converts a metadata object to the NamespacedName name representation.
|
||||
func NameFromMeta(meta v1.ObjectMeta) spec.NamespacedName {
|
||||
func NameFromMeta(meta metav1.ObjectMeta) spec.NamespacedName {
|
||||
return spec.NamespacedName{
|
||||
Namespace: meta.Namespace,
|
||||
Name: meta.Name,
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/client-go/pkg/api/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/zalando-incubator/postgres-operator/pkg/spec"
|
||||
)
|
||||
@@ -53,7 +53,7 @@ func TestRandomPassword(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestNameFromMeta(t *testing.T) {
|
||||
meta := v1.ObjectMeta{
|
||||
meta := metav1.ObjectMeta{
|
||||
Name: "testcluster",
|
||||
Namespace: "default",
|
||||
}
|
||||
@@ -73,7 +73,7 @@ func TestPGUserPassword(t *testing.T) {
|
||||
for _, tt := range pgUsers {
|
||||
pwd := PGUserPassword(tt.in)
|
||||
if pwd != tt.out {
|
||||
t.Errorf("PgUserPassword expected: %s, got: %s", tt.out, pwd)
|
||||
t.Errorf("PgUserPassword expected: %q, got: %q", tt.out, pwd)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,7 +81,7 @@ func TestPGUserPassword(t *testing.T) {
|
||||
func TestPrettyDiff(t *testing.T) {
|
||||
for _, tt := range prettyDiffTest {
|
||||
if actual := PrettyDiff(tt.inA, tt.inB); actual != tt.out {
|
||||
t.Errorf("PrettyDiff expected: %s, got: %s", tt.out, actual)
|
||||
t.Errorf("PrettyDiff expected: %q, got: %q", tt.out, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,11 +42,11 @@ func (c *EBSVolumeResizer) VolumeBelongsToProvider(pv *v1.PersistentVolume) bool
|
||||
func (c *EBSVolumeResizer) GetProviderVolumeID(pv *v1.PersistentVolume) (string, error) {
|
||||
volumeID := pv.Spec.AWSElasticBlockStore.VolumeID
|
||||
if volumeID == "" {
|
||||
return "", fmt.Errorf("volume id is empty for volume %s", pv.Name)
|
||||
return "", fmt.Errorf("volume id is empty for volume %q", pv.Name)
|
||||
}
|
||||
idx := strings.LastIndex(volumeID, constants.EBSVolumeIDStart) + 1
|
||||
if idx == 0 {
|
||||
return "", fmt.Errorf("malfored EBS volume id %s", volumeID)
|
||||
return "", fmt.Errorf("malfored EBS volume id %q", volumeID)
|
||||
}
|
||||
return volumeID[idx:], nil
|
||||
}
|
||||
@@ -60,7 +60,7 @@ func (c *EBSVolumeResizer) ResizeVolume(volumeId string, newSize int64) error {
|
||||
}
|
||||
vol := volumeOutput.Volumes[0]
|
||||
if *vol.VolumeId != volumeId {
|
||||
return fmt.Errorf("describe volume %s returned information about a non-matching volume %s", volumeId, *vol.VolumeId)
|
||||
return fmt.Errorf("describe volume %q returned information about a non-matching volume %q", volumeId, *vol.VolumeId)
|
||||
}
|
||||
if *vol.Size == newSize {
|
||||
// nothing to do
|
||||
@@ -74,7 +74,7 @@ func (c *EBSVolumeResizer) ResizeVolume(volumeId string, newSize int64) error {
|
||||
|
||||
state := *output.VolumeModification.ModificationState
|
||||
if state == constants.EBSVolumeStateFailed {
|
||||
return fmt.Errorf("could not modify persistent volume %s: modification state failed", volumeId)
|
||||
return fmt.Errorf("could not modify persistent volume %q: modification state failed", volumeId)
|
||||
}
|
||||
if state == "" {
|
||||
return fmt.Errorf("received empty modification status")
|
||||
@@ -91,10 +91,10 @@ func (c *EBSVolumeResizer) ResizeVolume(volumeId string, newSize int64) error {
|
||||
return false, fmt.Errorf("could not describe volume modification: %v", err)
|
||||
}
|
||||
if len(out.VolumesModifications) != 1 {
|
||||
return false, fmt.Errorf("describe volume modification didn't return one record for volume \"%s\"", volumeId)
|
||||
return false, fmt.Errorf("describe volume modification didn't return one record for volume %q", volumeId)
|
||||
}
|
||||
if *out.VolumesModifications[0].VolumeId != volumeId {
|
||||
return false, fmt.Errorf("non-matching volume id when describing modifications: \"%s\" is different from \"%s\"",
|
||||
return false, fmt.Errorf("non-matching volume id when describing modifications: %q is different from %q",
|
||||
*out.VolumesModifications[0].VolumeId, volumeId)
|
||||
}
|
||||
return *out.VolumesModifications[0].ModificationState != constants.EBSVolumeStateModifying, nil
|
||||
|
||||
Reference in New Issue
Block a user