Merge branch 'master' into feature/tests
# Conflicts: # pkg/spec/postgresql.go
This commit is contained in:
		
						commit
						9086beaa40
					
				|  | @ -43,4 +43,4 @@ spec: | ||||||
|     maximum_lag_on_failover: 33554432 |     maximum_lag_on_failover: 33554432 | ||||||
|   maintenanceWindows: |   maintenanceWindows: | ||||||
|   - 01:00-06:00 #UTC |   - 01:00-06:00 #UTC | ||||||
|   - Sat:00:00-Sat:04:00 |   - Sat:00:00-04:00 | ||||||
|  |  | ||||||
|  | @ -105,11 +105,41 @@ func (c *Cluster) logVolumeChanges(old, new spec.Volume, reason string) { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (c *Cluster) getOAuthToken() (string, error) { | ||||||
|  | 	//TODO: we can move this function to the Controller in case it will be needed there. As for now we use it only in the Cluster
 | ||||||
|  | 	// Temporary getting postgresql-operator secret from the NamespaceDefault
 | ||||||
|  | 	credentialsSecret, err := c.KubeClient. | ||||||
|  | 		Secrets(c.OpConfig.OAuthTokenSecretName.Namespace). | ||||||
|  | 		Get(c.OpConfig.OAuthTokenSecretName.Name) | ||||||
|  | 
 | ||||||
|  | 	if err != nil { | ||||||
|  | 		c.logger.Debugf("Oauth token secret name: %s", c.OpConfig.OAuthTokenSecretName) | ||||||
|  | 		return "", fmt.Errorf("could not get credentials secret: %v", err) | ||||||
|  | 	} | ||||||
|  | 	data := credentialsSecret.Data | ||||||
|  | 
 | ||||||
|  | 	if string(data["read-only-token-type"]) != "Bearer" { | ||||||
|  | 		return "", fmt.Errorf("wrong token type: %v", data["read-only-token-type"]) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return string(data["read-only-token-secret"]), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (c *Cluster) getTeamMembers() ([]string, error) { | func (c *Cluster) getTeamMembers() ([]string, error) { | ||||||
| 	if c.Spec.TeamID == "" { | 	if c.Spec.TeamID == "" { | ||||||
| 		return nil, fmt.Errorf("no teamId specified") | 		return nil, fmt.Errorf("no teamId specified") | ||||||
| 	} | 	} | ||||||
| 	teamInfo, err := c.TeamsAPIClient.TeamInfo(c.Spec.TeamID) | 	if !c.OpConfig.EnableTeamsAPI { | ||||||
|  | 		c.logger.Debug("Team API is disabled, returning empty list of members") | ||||||
|  | 		return []string{}, nil | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	token, err := c.getOAuthToken() | ||||||
|  | 	if err != nil { | ||||||
|  | 		return []string{}, fmt.Errorf("could not get oauth token: %v", err) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	teamInfo, err := c.TeamsAPIClient.TeamInfo(c.Spec.TeamID, token) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, fmt.Errorf("could not get team info: %v", err) | 		return nil, fmt.Errorf("could not get team info: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -47,7 +47,8 @@ func New(controllerConfig *Config, operatorConfig *config.Config) *Controller { | ||||||
| 		logger.Level = logrus.DebugLevel | 		logger.Level = logrus.DebugLevel | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	controllerConfig.TeamsAPIClient = teams.NewTeamsAPI(operatorConfig.TeamsAPIUrl, logger, operatorConfig.EnableTeamsAPI) | 	controllerConfig.TeamsAPIClient = teams.NewTeamsAPI(operatorConfig.TeamsAPIUrl, logger) | ||||||
|  | 
 | ||||||
| 	return &Controller{ | 	return &Controller{ | ||||||
| 		Config:   *controllerConfig, | 		Config:   *controllerConfig, | ||||||
| 		opConfig: operatorConfig, | 		opConfig: operatorConfig, | ||||||
|  | @ -78,7 +79,6 @@ func (c *Controller) initController() { | ||||||
| 		c.logger.Fatalf("could not register ThirdPartyResource: %v", err) | 		c.logger.Fatalf("could not register ThirdPartyResource: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	c.TeamsAPIClient.RefreshTokenAction = c.getOAuthToken |  | ||||||
| 	if infraRoles, err := c.getInfrastructureRoles(); err != nil { | 	if infraRoles, err := c.getInfrastructureRoles(); err != nil { | ||||||
| 		c.logger.Warningf("could not get infrastructure roles: %v", err) | 		c.logger.Warningf("could not get infrastructure roles: %v", err) | ||||||
| 	} else { | 	} else { | ||||||
|  |  | ||||||
|  | @ -29,25 +29,6 @@ func (c *Controller) makeClusterConfig() cluster.Config { | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (c *Controller) getOAuthToken() (string, error) { |  | ||||||
| 	// Temporary getting postgresql-operator secret from the NamespaceDefault
 |  | ||||||
| 	credentialsSecret, err := c.KubeClient. |  | ||||||
| 		Secrets(c.opConfig.OAuthTokenSecretName.Namespace). |  | ||||||
| 		Get(c.opConfig.OAuthTokenSecretName.Name) |  | ||||||
| 
 |  | ||||||
| 	if err != nil { |  | ||||||
| 		c.logger.Debugf("Oauth token secret name: %s", c.opConfig.OAuthTokenSecretName) |  | ||||||
| 		return "", fmt.Errorf("could not get credentials secret: %v", err) |  | ||||||
| 	} |  | ||||||
| 	data := credentialsSecret.Data |  | ||||||
| 
 |  | ||||||
| 	if string(data["read-only-token-type"]) != "Bearer" { |  | ||||||
| 		return "", fmt.Errorf("wrong token type: %v", data["read-only-token-type"]) |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return string(data["read-only-token-secret"]), nil |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func thirdPartyResource(TPRName string) *extv1beta.ThirdPartyResource { | func thirdPartyResource(TPRName string) *extv1beta.ThirdPartyResource { | ||||||
| 	return &extv1beta.ThirdPartyResource{ | 	return &extv1beta.ThirdPartyResource{ | ||||||
| 		ObjectMeta: v1.ObjectMeta{ | 		ObjectMeta: v1.ObjectMeta{ | ||||||
|  |  | ||||||
|  | @ -3,7 +3,6 @@ package spec | ||||||
| import ( | import ( | ||||||
| 	"encoding/json" | 	"encoding/json" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"regexp" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| 	"time" | 	"time" | ||||||
| 
 | 
 | ||||||
|  | @ -13,11 +12,10 @@ import ( | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type MaintenanceWindow struct { | type MaintenanceWindow struct { | ||||||
| 	StartTime    time.Time    // Start time
 | 	Everyday  bool | ||||||
| 	StartWeekday time.Weekday // Start weekday
 | 	Weekday   time.Weekday | ||||||
| 
 | 	StartTime time.Time // Start time
 | ||||||
| 	EndTime    time.Time    // End time
 | 	EndTime   time.Time // End time
 | ||||||
| 	EndWeekday time.Weekday // End weekday
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type Volume struct { | type Volume struct { | ||||||
|  | @ -94,61 +92,49 @@ type PostgresqlList struct { | ||||||
| 	Items []Postgresql `json:"items"` | 	Items []Postgresql `json:"items"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| var alphaRegexp = regexp.MustCompile("^[a-zA-Z]*$") |  | ||||||
| var weekdays = map[string]int{"Sun": 0, "Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5, "Sat": 6} | var weekdays = map[string]int{"Sun": 0, "Mon": 1, "Tue": 2, "Wed": 3, "Thu": 4, "Fri": 5, "Sat": 6} | ||||||
| 
 | 
 | ||||||
| func parseTime(s string) (t time.Time, wd time.Weekday, wdProvided bool, err error) { | func parseTime(s string) (time.Time, error) { | ||||||
| 	var timeLayout string |  | ||||||
| 
 |  | ||||||
| 	parts := strings.Split(s, ":") | 	parts := strings.Split(s, ":") | ||||||
| 	if len(parts) == 3 { | 	if len(parts) != 2 { | ||||||
| 		if len(parts[0]) != 3 || !alphaRegexp.MatchString(parts[0]) { | 		return time.Time{}, fmt.Errorf("incorrect time format") | ||||||
| 			err = fmt.Errorf("weekday must be 3 characters length") |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		timeLayout = "Mon:15:04" |  | ||||||
| 		wdProvided = true |  | ||||||
| 		weekday, ok := weekdays[parts[0]] |  | ||||||
| 		if !ok { |  | ||||||
| 			err = fmt.Errorf("incorrect weekday") |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 		wd = time.Weekday(weekday) |  | ||||||
| 	} else { |  | ||||||
| 		wdProvided = false |  | ||||||
| 		timeLayout = "15:04" |  | ||||||
| 	} | 	} | ||||||
|  | 	timeLayout := "15:04" | ||||||
| 
 | 
 | ||||||
| 	tp, err := time.Parse(timeLayout, s) | 	tp, err := time.Parse(timeLayout, s) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return | 		return time.Time{}, err | ||||||
| 	} | 	} | ||||||
| 	t = tp.UTC() |  | ||||||
| 
 | 
 | ||||||
| 	return | 	return tp.UTC(), nil | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func parseWeekday(s string) (time.Weekday, error) { | ||||||
|  | 	weekday, ok := weekdays[s] | ||||||
|  | 	if !ok { | ||||||
|  | 		return time.Weekday(0), fmt.Errorf("incorrect weekday") | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return time.Weekday(weekday), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *MaintenanceWindow) MarshalJSON() ([]byte, error) { | func (m *MaintenanceWindow) MarshalJSON() ([]byte, error) { | ||||||
| 	var startWd, endWd string | 	if m.Everyday { | ||||||
| 	if m.StartWeekday == time.Monday && m.EndWeekday == time.Sunday { | 		return []byte(fmt.Sprintf("\"%s-%s\"", | ||||||
| 		startWd = "" | 			m.StartTime.Format("15:04"), | ||||||
| 		endWd = "" | 			m.EndTime.Format("15:04"))), nil | ||||||
| 	} else { | 	} else { | ||||||
| 		startWd = m.StartWeekday.String()[:3] + ":" | 		return []byte(fmt.Sprintf("\"%s:%s-%s\"", | ||||||
| 		endWd = m.EndWeekday.String()[:3] + ":" | 			m.Weekday.String()[:3], | ||||||
|  | 			m.StartTime.Format("15:04"), | ||||||
|  | 			m.EndTime.Format("15:04"))), nil | ||||||
| 	} | 	} | ||||||
| 
 |  | ||||||
| 	return []byte(fmt.Sprintf("\"%s%s-%s%s\"", |  | ||||||
| 		startWd, m.StartTime.Format("15:04"), |  | ||||||
| 		endWd, m.EndTime.Format("15:04"))), nil |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (m *MaintenanceWindow) UnmarshalJSON(data []byte) error { | func (m *MaintenanceWindow) UnmarshalJSON(data []byte) error { | ||||||
| 	var ( | 	var ( | ||||||
| 		got                 MaintenanceWindow | 		got MaintenanceWindow | ||||||
| 		weekdayProvidedFrom bool | 		err error | ||||||
| 		weekdayProvidedTo   bool |  | ||||||
| 		err                 error |  | ||||||
| 	) | 	) | ||||||
| 
 | 
 | ||||||
| 	parts := strings.Split(string(data[1:len(data)-1]), "-") | 	parts := strings.Split(string(data[1:len(data)-1]), "-") | ||||||
|  | @ -156,29 +142,35 @@ func (m *MaintenanceWindow) UnmarshalJSON(data []byte) error { | ||||||
| 		return fmt.Errorf("incorrect maintenance window format") | 		return fmt.Errorf("incorrect maintenance window format") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	got.StartTime, got.StartWeekday, weekdayProvidedFrom, err = parseTime(parts[0]) | 	fromParts := strings.Split(parts[0], ":") | ||||||
|  | 	switch len(fromParts) { | ||||||
|  | 	case 3: | ||||||
|  | 		got.Everyday = false | ||||||
|  | 		got.Weekday, err = parseWeekday(fromParts[0]) | ||||||
|  | 		if err != nil { | ||||||
|  | 			return fmt.Errorf("could not parse weekday: %v", err) | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		got.StartTime, err = parseTime(fromParts[1] + ":" + fromParts[2]) | ||||||
|  | 	case 2: | ||||||
|  | 		got.Everyday = true | ||||||
|  | 		got.StartTime, err = parseTime(fromParts[0] + ":" + fromParts[1]) | ||||||
|  | 	default: | ||||||
|  | 		return fmt.Errorf("incorrect maintenance window format") | ||||||
|  | 	} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return fmt.Errorf("could not parse start time: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	got.EndTime, got.EndWeekday, weekdayProvidedTo, err = parseTime(parts[1]) | 	got.EndTime, err = parseTime(parts[1]) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return fmt.Errorf("could not parse end time: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if got.EndTime.Before(got.StartTime) { | 	if got.EndTime.Before(got.StartTime) { | ||||||
| 		return fmt.Errorf("'From' time must be prior to the 'To' time") | 		return fmt.Errorf("'From' time must be prior to the 'To' time") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if (int(got.StartWeekday)+6)%7 > (int(got.EndWeekday)+6)%7 { |  | ||||||
| 		return fmt.Errorf("'From' weekday must be prior to the 'To' weekday") |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if !weekdayProvidedFrom || !weekdayProvidedTo { |  | ||||||
| 		got.StartWeekday = time.Monday |  | ||||||
| 		got.EndWeekday = time.Sunday |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	*m = got | 	*m = got | ||||||
| 
 | 
 | ||||||
| 	return nil | 	return nil | ||||||
|  | @ -202,13 +194,12 @@ func (pl *PostgresqlList) GetListMeta() unversioned.List { | ||||||
| 
 | 
 | ||||||
| func extractClusterName(clusterName string, teamName string) (string, error) { | func extractClusterName(clusterName string, teamName string) (string, error) { | ||||||
| 	teamNameLen := len(teamName) | 	teamNameLen := len(teamName) | ||||||
| 
 |  | ||||||
| 	if len(clusterName) < teamNameLen+2 { | 	if len(clusterName) < teamNameLen+2 { | ||||||
| 		return "", fmt.Errorf("name is too short") | 		return "", fmt.Errorf("name is too short") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if teamNameLen == 0 { | 	if teamNameLen == 0 { | ||||||
| 		return "", fmt.Errorf("Team name is empty") | 		return "", fmt.Errorf("team name is empty") | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if strings.ToLower(clusterName[:teamNameLen+1]) != strings.ToLower(teamName)+"-" { | 	if strings.ToLower(clusterName[:teamNameLen+1]) != strings.ToLower(teamName)+"-" { | ||||||
|  |  | ||||||
|  | @ -38,34 +38,22 @@ type Team struct { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type API struct { | type API struct { | ||||||
| 	url                string | 	url        string | ||||||
| 	httpClient         *http.Client | 	httpClient *http.Client | ||||||
| 	logger             *logrus.Entry | 	logger     *logrus.Entry | ||||||
| 	RefreshTokenAction func() (string, error) |  | ||||||
| 	enabled            bool |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func NewTeamsAPI(url string, log *logrus.Logger, enabled bool) *API { | func NewTeamsAPI(url string, log *logrus.Logger) *API { | ||||||
| 	t := API{ | 	t := API{ | ||||||
| 		url:        strings.TrimRight(url, "/"), | 		url:        strings.TrimRight(url, "/"), | ||||||
| 		httpClient: &http.Client{}, | 		httpClient: &http.Client{}, | ||||||
| 		logger:     log.WithField("pkg", "teamsapi"), | 		logger:     log.WithField("pkg", "teamsapi"), | ||||||
| 		enabled:    enabled, |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return &t | 	return &t | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (t *API) TeamInfo(teamID string) (*Team, error) { | func (t *API) TeamInfo(teamID, token string) (*Team, error) { | ||||||
| 	// TODO: avoid getting a new token on every call to the Teams API.
 |  | ||||||
| 	if !t.enabled { |  | ||||||
| 		t.logger.Debug("Team API is disabled, returning empty list of members") |  | ||||||
| 		return &Team{}, nil |  | ||||||
| 	} |  | ||||||
| 	token, err := t.RefreshTokenAction() |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 	url := fmt.Sprintf("%s/teams/%s", t.url, teamID) | 	url := fmt.Sprintf("%s/teams/%s", t.url, teamID) | ||||||
| 	t.logger.Debugf("Request url: %s", url) | 	t.logger.Debugf("Request url: %s", url) | ||||||
| 	req, err := http.NewRequest("GET", url, nil) | 	req, err := http.NewRequest("GET", url, nil) | ||||||
|  | @ -84,7 +72,7 @@ func (t *API) TeamInfo(teamID string) (*Team, error) { | ||||||
| 		d := json.NewDecoder(resp.Body) | 		d := json.NewDecoder(resp.Body) | ||||||
| 		err = d.Decode(&raw) | 		err = d.Decode(&raw) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, fmt.Errorf("team API query failed with status code %d and malformed response: %v", resp.StatusCode, err) | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if errMessage, ok := raw["error"]; ok { | 		if errMessage, ok := raw["error"]; ok { | ||||||
|  | @ -97,7 +85,7 @@ func (t *API) TeamInfo(teamID string) (*Team, error) { | ||||||
| 	d := json.NewDecoder(resp.Body) | 	d := json.NewDecoder(resp.Body) | ||||||
| 	err = d.Decode(teamInfo) | 	err = d.Decode(teamInfo) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, fmt.Errorf("could not parse team API response: %v", err) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	return teamInfo, nil | 	return teamInfo, nil | ||||||
|  |  | ||||||
|  | @ -0,0 +1,182 @@ | ||||||
|  | package teams | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"github.com/Sirupsen/logrus" | ||||||
|  | 	"net/http" | ||||||
|  | 	"net/http/httptest" | ||||||
|  | 	"reflect" | ||||||
|  | 	"testing" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var ( | ||||||
|  | 	logger = logrus.New() | ||||||
|  | 	token  = "ec45b1cfbe7100c6315d183a3eb6cec0M2U1LWJkMzEtZDgzNzNmZGQyNGM3IiwiYXV0aF90aW1lIjoxNDkzNzMwNzQ1LCJpc3MiOiJodHRwcz" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | var teamsAPItc = []struct { | ||||||
|  | 	in     string | ||||||
|  | 	inCode int | ||||||
|  | 	out    *Team | ||||||
|  | 	err    error | ||||||
|  | }{ | ||||||
|  | 	{`{ | ||||||
|  | "dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", | ||||||
|  | "id": "acid", | ||||||
|  | "id_name": "ACID", | ||||||
|  | "team_id": "111222", | ||||||
|  | "type": "official", | ||||||
|  | "name": "Acid team name", | ||||||
|  | "mail": [ | ||||||
|  | "email1@example.com", | ||||||
|  | "email2@example.com" | ||||||
|  | ], | ||||||
|  | "alias": [ | ||||||
|  | "acid" | ||||||
|  | ], | ||||||
|  | "member": [ | ||||||
|  |   "member1", | ||||||
|  |   "member2", | ||||||
|  |   "member3" | ||||||
|  | ], | ||||||
|  | "infrastructure-accounts": [ | ||||||
|  | { | ||||||
|  |   "id": "1234512345", | ||||||
|  |   "name": "acid", | ||||||
|  |   "provider": "aws", | ||||||
|  |   "type": "aws", | ||||||
|  |   "description": "", | ||||||
|  |   "owner": "acid", | ||||||
|  |   "owner_dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", | ||||||
|  |   "disabled": false | ||||||
|  | }, | ||||||
|  | { | ||||||
|  |   "id": "5432154321", | ||||||
|  |   "name": "db", | ||||||
|  |   "provider": "aws", | ||||||
|  |   "type": "aws", | ||||||
|  |   "description": "", | ||||||
|  |   "owner": "acid", | ||||||
|  |   "owner_dn": "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", | ||||||
|  |   "disabled": false | ||||||
|  | } | ||||||
|  | ], | ||||||
|  | "cost_center": "00099999", | ||||||
|  | "delivery_lead": "member4", | ||||||
|  | "parent_team_id": "111221" | ||||||
|  | }`, | ||||||
|  | 		200, | ||||||
|  | 		&Team{ | ||||||
|  | 			Dn:           "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", | ||||||
|  | 			ID:           "acid", | ||||||
|  | 			TeamName:     "ACID", | ||||||
|  | 			TeamID:       "111222", | ||||||
|  | 			Type:         "official", | ||||||
|  | 			FullName:     "Acid team name", | ||||||
|  | 			Aliases:      []string{"acid"}, | ||||||
|  | 			Mails:        []string{"email1@example.com", "email2@example.com"}, | ||||||
|  | 			Members:      []string{"member1", "member2", "member3"}, | ||||||
|  | 			CostCenter:   "00099999", | ||||||
|  | 			DeliveryLead: "member4", | ||||||
|  | 			ParentTeamID: "111221", | ||||||
|  | 			InfrastructureAccounts: []InfrastructureAccount{ | ||||||
|  | 				{ | ||||||
|  | 					ID:          "1234512345", | ||||||
|  | 					Name:        "acid", | ||||||
|  | 					Provider:    "aws", | ||||||
|  | 					Type:        "aws", | ||||||
|  | 					Description: "", | ||||||
|  | 					Owner:       "acid", | ||||||
|  | 					OwnerDn:     "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", | ||||||
|  | 					Disabled:    false}, | ||||||
|  | 				{ | ||||||
|  | 					ID:          "5432154321", | ||||||
|  | 					Name:        "db", | ||||||
|  | 					Provider:    "aws", | ||||||
|  | 					Type:        "aws", | ||||||
|  | 					Description: "", | ||||||
|  | 					Owner:       "acid", | ||||||
|  | 					OwnerDn:     "cn=100100,ou=official,ou=foobar,dc=zalando,dc=net", | ||||||
|  | 					Disabled:    false}, | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		nil}, { | ||||||
|  | 		`{"error": "Access Token not valid"}`, | ||||||
|  | 		401, | ||||||
|  | 		nil, | ||||||
|  | 		fmt.Errorf(`team API query failed with status code 401 and message: '"Access Token not valid"'`), | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		`{"status": "I'm a teapot'"}`, | ||||||
|  | 		418, | ||||||
|  | 		nil, | ||||||
|  | 		fmt.Errorf(`team API query failed with status code 418`), | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		`{"status": "I'm a teapot`, | ||||||
|  | 		418, | ||||||
|  | 		nil, | ||||||
|  | 		fmt.Errorf(`team API query failed with status code 418 and malformed response: unexpected EOF`), | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		`{"status": "I'm a teapot`, | ||||||
|  | 		200, | ||||||
|  | 		nil, | ||||||
|  | 		fmt.Errorf(`could not parse team API response: unexpected EOF`), | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var requestsURLtc = []struct { | ||||||
|  | 	url string | ||||||
|  | 	err error | ||||||
|  | }{ | ||||||
|  | 	{ | ||||||
|  | 		"coffee://localhost/", | ||||||
|  | 		fmt.Errorf(`Get coffee://localhost/teams/acid: unsupported protocol scheme "coffee"`), | ||||||
|  | 	}, | ||||||
|  | 	{ | ||||||
|  | 		"http://192.168.0.%31/", | ||||||
|  | 		fmt.Errorf(`parse http://192.168.0.%%31/teams/acid: invalid URL escape "%%31"`), | ||||||
|  | 	}, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestInfo(t *testing.T) { | ||||||
|  | 	for _, tc := range teamsAPItc { | ||||||
|  | 		func() { | ||||||
|  | 			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { | ||||||
|  | 				if r.Header.Get("Authorization") != "Bearer " + token { | ||||||
|  | 					t.Errorf("Authorization token is wrong or not provided") | ||||||
|  | 				} | ||||||
|  | 				w.WriteHeader(tc.inCode) | ||||||
|  | 				fmt.Fprint(w, tc.in) | ||||||
|  | 			})) | ||||||
|  | 			defer ts.Close() | ||||||
|  | 			api := NewTeamsAPI(ts.URL, logger) | ||||||
|  | 
 | ||||||
|  | 			actual, err := api.TeamInfo("acid", token) | ||||||
|  | 			if err != nil && err.Error() != tc.err.Error() { | ||||||
|  | 				t.Errorf("Expected error: %v, got: %v", tc.err, err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 
 | ||||||
|  | 			if !reflect.DeepEqual(actual, tc.out) { | ||||||
|  | 				t.Errorf("Expected %#v, got: %#v", tc.out, actual) | ||||||
|  | 			} | ||||||
|  | 		}() | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func TestRequest(t *testing.T) { | ||||||
|  | 	for _, tc := range requestsURLtc { | ||||||
|  | 		api := NewTeamsAPI(tc.url, logger) | ||||||
|  | 		resp, err := api.TeamInfo("acid", token) | ||||||
|  | 		if resp != nil { | ||||||
|  | 			t.Errorf("Response expected to be nil") | ||||||
|  | 			continue | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if err.Error() != tc.err.Error() { | ||||||
|  | 			t.Errorf("Expected error: %v, got: %v", tc.err, err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | @ -41,7 +41,7 @@ func NameFromMeta(meta v1.ObjectMeta) spec.NamespacedName { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func PGUserPassword(user spec.PgUser) string { | func PGUserPassword(user spec.PgUser) string { | ||||||
| 	if (len(user.Password) == md5.Size && user.Password[:3] == md5prefix) || user.Password == "" { | 	if (len(user.Password) == md5.Size*2+len(md5prefix) && user.Password[:3] == md5prefix) || user.Password == "" { | ||||||
| 		// Avoid processing already encrypted or empty passwords
 | 		// Avoid processing already encrypted or empty passwords
 | ||||||
| 		return user.Password | 		return user.Password | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue