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:
Murat Kabilov
2017-07-25 15:25:17 +02:00
committed by GitHub
parent 4455f1b639
commit 1f8b37f33d
31 changed files with 579 additions and 666 deletions
+1 -4
View File
@@ -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
+1 -1
View File
@@ -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"
+4 -3
View File
@@ -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"
)
+1 -1
View File
@@ -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
View File
@@ -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
+4 -4
View File
@@ -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
View File
@@ -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 -4
View File
@@ -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)
}
}
}
+6 -6
View File
@@ -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