-
Notifications
You must be signed in to change notification settings - Fork 1k
Create cross namespace secrets #1490
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
pkg/cluster/cluster.go
Outdated
if strings.Contains(username, ".") { | ||
splits := strings.Split(username, ".") | ||
name = splits[1] | ||
namespace = splits[0] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if the username is .user
? Then namespace is ""
and should become the default namespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, such a username is considered invalid username and I think this should continue. I don't see a reason why this should be allowed, if no namespace is provided then username only should be provided.
pkg/cluster/cluster.go
Outdated
name := username | ||
namespace := c.Namespace | ||
|
||
if strings.Contains(username, ".") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs some attention.
Also include update to regex in manifest schema.
TPR) and `{tprgroup}` with the group of the CRD. No other placeholders are | ||
allowed. The default is | ||
`{username}.{cluster}.credentials.{tprkind}.{tprgroup}`. | ||
operator. `{namesapce}` is replaced with name of the namespace (if any, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo: namesApce
-> namespace
allowed. The default is | ||
`{username}.{cluster}.credentials.{tprkind}.{tprgroup}`. | ||
operator. `{namesapce}` is replaced with name of the namespace (if any, | ||
otherwise empty), `{username}` is replaced with name of the secret, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is an ambiguous description because a secret always lives in a namespace.
My best guess is that what is meant here is
This part of the secret name is empty if the secret and a PG cluster it belongs to are in the same namespace
e2e/tests/test_e2e.py
Outdated
''' | ||
app_namespace = "appspace" | ||
k8s = self.k8s | ||
k8s.api.core_v1.create_namespace(app_namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am unsure if kind
always creates a new namespace fast enough. It is better to have some type of timeout / waiting here to avoid spurious test failures.
e2e/tests/test_e2e.py
Outdated
} | ||
}) | ||
self.eventuallyEqual(lambda: k8s.count_secrets_in_namespace(app_namespace), | ||
1, "Secret not created in user namespace") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To make it more informative, please log the name of the secret and the namespace
pkg/cluster/cluster_test.go
Outdated
|
||
err := cluster.initRobotUsers() | ||
if err != nil { | ||
t.Errorf("%s Could not create namespaced users with error: %s", testName, err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Does
namespaced user
here really meannamespaced secret
? - I doubt there is a need to log a test name, the golang test framework likely reports it automatically
pkg/cluster/cluster_test.go
Outdated
func TestValidUsernames(t *testing.T) { | ||
testName := "test username validity" | ||
|
||
invalidUsernames := []string{"_", ".", ".user", "appspace.", "appspace.user.extra", "user_", "_user", "-user", "user-", ",", ",user", "user,", "namespace,user"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is the name -
disallowed by other means ?
pkg/cluster/sync.go
Outdated
for _, cachedUser := range c.pgUsersCache { | ||
if _, exists := c.pgUsers[cachedUser.Name]; !exists { | ||
userNames = append(userNames, cachedUser.Name) | ||
pg_role := u.Name |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pg_role
should be pgRole
because of the golang naming conventions.
userNames = append(userNames, u.Name) | ||
// add team member role name with rename suffix in case we need to rename it back | ||
if u.Origin == spec.RoleOriginTeamsAPI && c.OpConfig.EnableTeamMemberDeprecation { | ||
deletedUsers[u.Name+c.OpConfig.RoleDeletionSuffix] = u.Name | ||
userNames = append(userNames, u.Name+c.OpConfig.RoleDeletionSuffix) | ||
} | ||
} | ||
|
||
// add team members that exist only in cache | ||
// to trigger a rename of the role in ProduceSyncRequests | ||
for _, cachedUser := range c.pgUsersCache { | ||
if _, exists := c.pgUsers[cachedUser.Name]; !exists { | ||
userNames = append(userNames, cachedUser.Name) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happened to these lines ? they are still needed for renaming roles removed fro PostgresTeam CRD
pkg/cluster/sync.go
Outdated
if u.Namespace != c.Namespace { | ||
// to avoid the conflict of having multiple users of same name | ||
// but each in different namespace. | ||
pg_role = fmt.Sprintf("%s.%s", u.Name, u.Namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so the template for the secret name is namespace.username
but (in case of this name conflict) the role also gets a namespace as part of its name ? Will the resultant secret contain the namespace twice ?
…into cross_namespace_secret
# template for database user secrets generated by the operator | ||
# template for database user secrets generated by the operator, | ||
# here username contains the namespace in the format namespace.username | ||
# if the user is in different namespace than cluster |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is the secret in the different namespace not the user.
e2e/tests/test_e2e.py
Outdated
k8s = self.k8s | ||
v1_appnamespace = client.V1Namespace(metadata=client.V1ObjectMeta(name=app_namespace)) | ||
try: | ||
k8s.api.core_v1.create_namespace(v1_appnamespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is unlikely the actual namespace creation will timeout. What I meant in my previous review was the following:
- The API call to create namespace may take some time, especially on
kind
where we know from experience even basic k8s operations sometimes take minutes - the patch at line 603 may run into problems because of that
- Since we run e2e tests in different environments (locally, GitHub Action, CDP etc) that may lead to unwanted spurious test failures
Earlier I used simple timeouts in such cases, but now we have function like self.k8s.wait_for_pod_start
and so on. You may just add a new one named self.k8s.wait_for_namespace_creation
e2e/tests/test_e2e.py
Outdated
} | ||
}) | ||
self.eventuallyEqual(lambda: k8s.count_secrets_with_label("cluster_name=acid-minimal-cluster,application=spilo", app_namespace), | ||
1, "Secret not created for user in namespace", app_namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To which parameter of eventuallyEqual
does app_namespace
correspond ?
if u.Namespace != c.Namespace { | ||
// to avoid the conflict of having multiple users of same name | ||
// but each in different namespace. | ||
pgRole = fmt.Sprintf("%s.%s", u.Name, u.Namespace) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel that behavior needs to be logged and mentioned in the docs. Just because it may happen an end user unaware of the name conflict expects to get username
but gets instead namespace.username
pkg/cluster/sync.go
Outdated
for _, u := range c.pgUsers { | ||
userNames = append(userNames, u.Name) | ||
pgRole := u.Name | ||
if u.Namespace != c.Namespace { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make sure u.Namespace
is always set. Currently it's missing in initTeamMembers
and readPgUsersFromDatabase
methods which leads to the wrong name appended here. This makes the second e2e test fail atm (it wants to create a user that already exists).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
scratch initTeamMembers
and readPgUsersFromDatabase
. It's easier to just add && u.Namespace != ""
here to not touch more unit tests. I pushed the change now.
👍 |
2 similar comments
👍 |
👍 |
If namespace is provided with the username in manifest,
then create the secret for that user in that namespace.
Also, the name of the secret will contain the namespace.