deprecate ClusterName field of Postgresql type and remove team from REST endpoints (#2015)

* deprecate ClusterName field of Postgresql type
* remove for teamId from operator API endpints /status /logs /history
* update dns_format_string and yaml template in UI
This commit is contained in:
Felix Kunde 2022-08-29 15:00:25 +02:00 committed by GitHub
parent 89375186b3
commit 4c07494ac7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 51 additions and 68 deletions

View File

@ -36,6 +36,9 @@ type PostgresSpec struct {
TeamID string `json:"teamId"`
DockerImage string `json:"dockerImage,omitempty"`
// deprecated field storing cluster name without teamId prefix
ClusterName string `json:"-"`
SpiloRunAsUser *int64 `json:"spiloRunAsUser,omitempty"`
SpiloRunAsGroup *int64 `json:"spiloRunAsGroup,omitempty"`
SpiloFSGroup *int64 `json:"spiloFSGroup,omitempty"`
@ -62,7 +65,6 @@ type PostgresSpec struct {
NumberOfInstances int32 `json:"numberOfInstances"`
MaintenanceWindows []MaintenanceWindow `json:"maintenanceWindows,omitempty"`
Clone *CloneDescription `json:"clone,omitempty"`
ClusterName string `json:"-"`
Databases map[string]string `json:"databases,omitempty"`
PreparedDatabases map[string]PreparedDatabase `json:"preparedDatabases,omitempty"`
SchedulerName *string `json:"schedulerName,omitempty"`

View File

@ -31,9 +31,9 @@ type controllerInformer interface {
GetOperatorConfig() *config.Config
GetStatus() *spec.ControllerStatus
TeamClusterList() map[string][]spec.NamespacedName
ClusterStatus(team, namespace, cluster string) (*cluster.ClusterStatus, error)
ClusterLogs(team, namespace, cluster string) ([]*spec.LogEntry, error)
ClusterHistory(team, namespace, cluster string) ([]*spec.Diff, error)
ClusterStatus(namespace, cluster string) (*cluster.ClusterStatus, error)
ClusterLogs(namespace, cluster string) ([]*spec.LogEntry, error)
ClusterHistory(namespace, cluster string) ([]*spec.Diff, error)
ClusterDatabasesMap() map[string][]string
WorkerLogs(workerID uint32) ([]*spec.LogEntry, error)
ListQueue(workerID uint32) (*spec.QueueDump, error)
@ -55,9 +55,9 @@ const (
)
var (
clusterStatusRe = fmt.Sprintf(`^/clusters/%s/%s/%s/?$`, teamRe, namespaceRe, clusterRe)
clusterLogsRe = fmt.Sprintf(`^/clusters/%s/%s/%s/logs/?$`, teamRe, namespaceRe, clusterRe)
clusterHistoryRe = fmt.Sprintf(`^/clusters/%s/%s/%s/history/?$`, teamRe, namespaceRe, clusterRe)
clusterStatusRe = fmt.Sprintf(`^/clusters/%s/%s/?$`, namespaceRe, clusterRe)
clusterLogsRe = fmt.Sprintf(`^/clusters/%s/%s/logs/?$`, namespaceRe, clusterRe)
clusterHistoryRe = fmt.Sprintf(`^/clusters/%s/%s/history/?$`, namespaceRe, clusterRe)
teamURLRe = fmt.Sprintf(`^/clusters/%s/?$`, teamRe)
clusterStatusURL = regexp.MustCompile(clusterStatusRe)
@ -170,7 +170,7 @@ func (s *Server) clusters(w http.ResponseWriter, req *http.Request) {
if matches := util.FindNamedStringSubmatch(clusterStatusURL, req.URL.Path); matches != nil {
namespace := matches["namespace"]
resp, err = s.controller.ClusterStatus(matches["team"], namespace, matches["cluster"])
resp, err = s.controller.ClusterStatus(namespace, matches["cluster"])
} else if matches := util.FindNamedStringSubmatch(teamURL, req.URL.Path); matches != nil {
teamClusters := s.controller.TeamClusterList()
clusters, found := teamClusters[matches["team"]]
@ -181,21 +181,21 @@ func (s *Server) clusters(w http.ResponseWriter, req *http.Request) {
clusterNames := make([]string, 0)
for _, cluster := range clusters {
clusterNames = append(clusterNames, cluster.Name[len(matches["team"])+1:])
clusterNames = append(clusterNames, cluster.Name)
}
resp, err = clusterNames, nil
} else if matches := util.FindNamedStringSubmatch(clusterLogsURL, req.URL.Path); matches != nil {
namespace := matches["namespace"]
resp, err = s.controller.ClusterLogs(matches["team"], namespace, matches["cluster"])
resp, err = s.controller.ClusterLogs(namespace, matches["cluster"])
} else if matches := util.FindNamedStringSubmatch(clusterHistoryURL, req.URL.Path); matches != nil {
namespace := matches["namespace"]
resp, err = s.controller.ClusterHistory(matches["team"], namespace, matches["cluster"])
resp, err = s.controller.ClusterHistory(namespace, matches["cluster"])
} else if req.URL.Path == clustersURL {
clusterNamesPerTeam := make(map[string][]string)
for team, clusters := range s.controller.TeamClusterList() {
for _, cluster := range clusters {
clusterNamesPerTeam[team] = append(clusterNamesPerTeam[team], cluster.Name[len(team)+1:])
clusterNamesPerTeam[team] = append(clusterNamesPerTeam[team], cluster.Name)
}
}
resp, err = clusterNamesPerTeam, nil

View File

@ -5,9 +5,9 @@ import (
)
const (
clusterStatusTest = "/clusters/test-id/test_namespace/testcluster/"
clusterStatusNumericTest = "/clusters/test-id-1/test_namespace/testcluster/"
clusterLogsTest = "/clusters/test-id/test_namespace/testcluster/logs/"
clusterStatusTest = "/clusters/test-namespace/testcluster/"
clusterStatusNumericTest = "/clusters/test-namespace-1/testcluster/"
clusterLogsTest = "/clusters/test-namespace/testcluster/logs/"
teamTest = "/clusters/test-id/"
)

View File

@ -1478,7 +1478,8 @@ func (c *Cluster) GetCurrentProcess() Process {
// GetStatus provides status of the cluster
func (c *Cluster) GetStatus() *ClusterStatus {
status := &ClusterStatus{
Cluster: c.Spec.ClusterName,
Cluster: c.Name,
Namespace: c.Namespace,
Team: c.Spec.TeamID,
Status: c.Status,
Spec: c.Spec,

View File

@ -587,7 +587,7 @@ func TestServiceAnnotations(t *testing.T) {
clusterAnnotations: make(map[string]string),
operatorAnnotations: make(map[string]string),
expect: map[string]string{
"external-dns.alpha.kubernetes.io/hostname": "test.test.db.example.com",
"external-dns.alpha.kubernetes.io/hostname": "acid-test.test.db.example.com,test.acid.db.example.com",
"service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout": "3600",
},
},
@ -723,7 +723,7 @@ func TestServiceAnnotations(t *testing.T) {
clusterAnnotations: make(map[string]string),
operatorAnnotations: make(map[string]string),
expect: map[string]string{
"external-dns.alpha.kubernetes.io/hostname": "test-repl.test.db.example.com",
"external-dns.alpha.kubernetes.io/hostname": "acid-test-repl.test.db.example.com,test-repl.acid.db.example.com",
"service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout": "3600",
},
},
@ -751,11 +751,6 @@ func TestServiceAnnotations(t *testing.T) {
for _, tt := range tests {
t.Run(tt.about, func(t *testing.T) {
cl.OpConfig.EnableTeamIdClusternamePrefix = tt.enableTeamIdClusterPrefix
if tt.enableTeamIdClusterPrefix {
cl.Postgresql.Spec.ClusterName = "test"
} else {
cl.Postgresql.Spec.ClusterName = "acid-test"
}
cl.OpConfig.CustomServiceAnnotations = tt.operatorAnnotations
cl.OpConfig.EnableMasterLoadBalancer = tt.enableMasterLoadBalancerOC
@ -764,6 +759,7 @@ func TestServiceAnnotations(t *testing.T) {
cl.OpConfig.ReplicaDNSNameFormat = "{cluster}-repl.{namespace}.{hostedzone}"
cl.OpConfig.DbHostedZone = "db.example.com"
cl.Postgresql.Spec.ClusterName = ""
cl.Postgresql.Spec.TeamID = "acid"
cl.Postgresql.Spec.ServiceAnnotations = tt.clusterAnnotations
cl.Postgresql.Spec.EnableMasterLoadBalancer = tt.enableMasterLoadBalancerSpec

View File

@ -59,6 +59,7 @@ type WorkerStatus struct {
type ClusterStatus struct {
Team string
Cluster string
Namespace string
MasterService *v1.Service
ReplicaService *v1.Service
MasterEndpoint *v1.Endpoints

View File

@ -507,22 +507,20 @@ func (c *Cluster) roleLabelsSet(shouldAddExtraLabels bool, role PostgresRole) la
func (c *Cluster) dnsName(role PostgresRole) string {
var dnsString string
if role == Master {
dnsString = c.masterDNSName()
} else {
dnsString = c.replicaDNSName()
}
// when cluster name starts with teamId prefix create an extra DNS entry
// to support the old format when prefix contraint was enabled (but is disabled now)
if !c.OpConfig.EnableTeamIdClusternamePrefix {
clusterNameWithoutTeamPrefix, _ := acidv1.ExtractClusterName(c.Name, c.Spec.TeamID)
if clusterNameWithoutTeamPrefix != "" {
if role == Replica {
clusterNameWithoutTeamPrefix = fmt.Sprintf("%s-repl", clusterNameWithoutTeamPrefix)
}
dnsString = fmt.Sprintf("%s,%s", dnsString, c.oldDNSFormat(clusterNameWithoutTeamPrefix))
// if cluster name starts with teamID we might need to provide backwards compatibility
clusterNameWithoutTeamPrefix, _ := acidv1.ExtractClusterName(c.Name, c.Spec.TeamID)
if clusterNameWithoutTeamPrefix != "" {
if role == Replica {
clusterNameWithoutTeamPrefix = fmt.Sprintf("%s-repl", clusterNameWithoutTeamPrefix)
}
dnsString = fmt.Sprintf("%s,%s", dnsString, c.oldDNSFormat(clusterNameWithoutTeamPrefix))
}
return dnsString
@ -530,15 +528,17 @@ func (c *Cluster) dnsName(role PostgresRole) string {
func (c *Cluster) masterDNSName() string {
return strings.ToLower(c.OpConfig.MasterDNSNameFormat.Format(
"cluster", c.Spec.ClusterName,
"cluster", c.Name,
"namespace", c.Namespace,
"team", c.teamName(),
"hostedzone", c.OpConfig.DbHostedZone))
}
func (c *Cluster) replicaDNSName() string {
return strings.ToLower(c.OpConfig.ReplicaDNSNameFormat.Format(
"cluster", c.Spec.ClusterName,
"cluster", c.Name,
"namespace", c.Namespace,
"team", c.teamName(),
"hostedzone", c.OpConfig.DbHostedZone))
}

View File

@ -15,11 +15,11 @@ import (
)
// ClusterStatus provides status of the cluster
func (c *Controller) ClusterStatus(team, namespace, cluster string) (*cluster.ClusterStatus, error) {
func (c *Controller) ClusterStatus(namespace, cluster string) (*cluster.ClusterStatus, error) {
clusterName := spec.NamespacedName{
Namespace: namespace,
Name: team + "-" + cluster,
Name: cluster,
}
c.clustersMu.RLock()
@ -92,11 +92,11 @@ func (c *Controller) GetStatus() *spec.ControllerStatus {
}
// ClusterLogs dumps cluster ring logs
func (c *Controller) ClusterLogs(team, namespace, name string) ([]*spec.LogEntry, error) {
func (c *Controller) ClusterLogs(namespace, name string) ([]*spec.LogEntry, error) {
clusterName := spec.NamespacedName{
Namespace: namespace,
Name: team + "-" + name,
Name: name,
}
c.clustersMu.RLock()
@ -215,11 +215,11 @@ func (c *Controller) WorkerStatus(workerID uint32) (*cluster.WorkerStatus, error
}
// ClusterHistory dumps history of cluster changes
func (c *Controller) ClusterHistory(team, namespace, name string) ([]*spec.Diff, error) {
func (c *Controller) ClusterHistory(namespace, name string) ([]*spec.Diff, error) {
clusterName := spec.NamespacedName{
Namespace: namespace,
Name: team + "-" + name,
Name: name,
}
c.clustersMu.RLock()

View File

@ -159,24 +159,16 @@ func (c *Controller) acquireInitialListOfClusters() error {
}
func (c *Controller) addCluster(lg *logrus.Entry, clusterName spec.NamespacedName, pgSpec *acidv1.Postgresql) (*cluster.Cluster, error) {
var (
extractedClusterName string
err error
)
if c.opConfig.EnableTeamIdClusternamePrefix {
if extractedClusterName, err = acidv1.ExtractClusterName(clusterName.Name, pgSpec.Spec.TeamID); err != nil {
if _, err := acidv1.ExtractClusterName(clusterName.Name, pgSpec.Spec.TeamID); err != nil {
c.KubeClient.SetPostgresCRDStatus(clusterName, acidv1.ClusterStatusInvalid)
return nil, err
}
} else {
extractedClusterName = clusterName.Name
}
cl := cluster.New(c.makeClusterConfig(), c.KubeClient, *pgSpec, lg, c.eventRecorder)
cl.Run(c.stopCh)
teamName := strings.ToLower(cl.Spec.TeamID)
cl.ClusterName = extractedClusterName
defer c.clustersMu.Unlock()
c.clustersMu.Lock()

View File

@ -64,7 +64,7 @@ new
a.btn.btn-small.btn-warning(
if='{ clusterExists }'
href='/#/status/{ namespace.state }/{ team }-{ name }'
href='/#/status/{ namespace.state }/{ name }'
)
| Cluster exists (show status)
@ -137,10 +137,10 @@ new
input.form-control(
ref='name'
type='text'
placeholder='new-cluster (can be { 53 - team.length - 1 } characters long)'
placeholder='new-cluster (can be 53 characters long)'
title='Database cluster name, must be a valid hostname component'
pattern='[a-z0-9]+[a-z0-9\-]+[a-z0-9]+'
maxlength='{ 53 - team.length - 1 }'
maxlength=53
required
value='{ name }'
onchange='{ nameChange }'
@ -520,7 +520,7 @@ new
apiVersion: "acid.zalan.do/v1"
metadata:
name: "{{ team }}-{{ name }}"
name: "{{ name }}"
namespace: "{{ namespace.state }}"
labels:
team: {{ team }}
@ -670,13 +670,12 @@ new
this.updateDNSName = () => {
this.dnsName = this.config.dns_format_string.format(
this.name,
this.team,
this.namespace.state,
)
}
this.updateClusterName = () => {
this.clusterName = (this.team + '-' + this.name).toLowerCase()
this.clusterName = (this.name).toLowerCase()
this.checkClusterExists()
this.updateDNSName()
}
@ -950,7 +949,7 @@ new
this.team = ''
}
this.clusterName = (this.name + '-' + this.team).toLowerCase()
this.clusterName = (this.name + '-').toLowerCase()
this.volumeSize = 10
this.instanceCount = 1
this.ranges = {}

View File

@ -55,7 +55,7 @@ spec:
value: |-
{
"docs_link":"https://postgres-operator.readthedocs.io/en/latest/",
"dns_format_string": "{1}-{0}.{2}",
"dns_format_string": "{0}.{1}",
"databases_visible": true,
"master_load_balancer_visible": true,
"nat_gateways_visible": false,

View File

@ -321,7 +321,7 @@ DEFAULT_UI_CONFIG = {
'databases_visible': True,
'resources_visible': RESOURCES_VISIBLE,
'postgresql_versions': ['11','12','13','14'],
'dns_format_string': '{0}.{1}.{2}',
'dns_format_string': '{0}.{1}',
'pgui_link': '',
'static_network_whitelist': {},
'read_only_mode': READ_ONLY_MODE,
@ -981,15 +981,7 @@ def get_operator_get_logs(worker: int):
@app.route('/operator/clusters/<namespace>/<cluster>/logs')
@authorize
def get_operator_get_logs_per_cluster(namespace: str, cluster: str):
team, cluster_name = cluster.split('-', 1)
# team id might contain hyphens, try to find correct team name
user_teams = get_teams_for_user(session.get('user_name', ''))
for user_team in user_teams:
if cluster.find(user_team + '-') == 0:
team = cluster[:len(user_team)]
cluster_name = cluster[len(user_team + '-'):]
break
return proxy_operator(f'/clusters/{team}/{namespace}/{cluster_name}/logs/')
return proxy_operator(f'/clusters/{namespace}/{cluster}/logs/')
@app.route('/login')

View File

@ -14,7 +14,7 @@ export TARGET_NAMESPACE="${TARGET_NAMESPACE-*}"
default_operator_ui_config='{
"docs_link":"https://postgres-operator.readthedocs.io/en/latest/",
"dns_format_string": "{1}-{0}.{2}",
"dns_format_string": "{0}.{1}",
"databases_visible": true,
"nat_gateways_visible": false,
"resources_visible": true,