Skip to content
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

Subdomain User Operations #76

Merged
merged 8 commits into from
May 9, 2022
Merged

Conversation

rejoshed
Copy link
Contributor

@rejoshed rejoshed commented May 6, 2022

Issue #, if available: CTECH-214

Description of changes:
When account and domain are specified CAPC will find (or create) a user in that domain and perform operations as that user. 🎆

Testing performed:
Created a cluster w/Affinity groups in a subdomain using an account and user in that domain.

Deleted the machinedeployment and watched the deletion process. Recreated machinedeployment. Deleted the whole cluster.

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@aws-paris-bot aws-paris-bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 6, 2022
@aws-paris-bot
Copy link

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@aws-paris-bot aws-paris-bot added approved Indicates a PR has been approved by an approver from all required OWNERS files. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 6, 2022
@rejoshed rejoshed changed the title Init. Subdomain User Operations May 6, 2022
Copy link
Contributor

@maxdrib maxdrib left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to create an e2e test for this scenario? It seems fairly complex so I'd feel more comfortable if we were validating that the users are handled correctly

Comment on lines 217 to 221
// GetOrCreateUserWithKeys will search a domain and account for the first user that has api keys.
// Creates a CAPC user if no such user is found.
func (c *client) GetOrCreateUserWithKeys(user *User) error {
return nil
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove these no-op and unused functions?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this is a draft PR, so yes I'll remove them. : )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I do eventually want methods like this in the codebase to be able to create domains/accounts/users on the fly in testing.

But since we will probably never do that in production, I'll probably put them in the test suite itself.

controllers/utils/base_reconciler.go Show resolved Hide resolved
controllers/utils/base_reconciler.go Outdated Show resolved Hide resolved
r.CSCluster.Spec.Account, r.CSCluster.Spec.Domain)
}
cfg := cloud.Config{APIKey: user.APIKey, SecretKey: user.SecretKey}
if client, err := r.CSClient.NewClientFromSpec(cfg); err != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if client, err := r.CSClient.NewClientFromSpec(cfg); err != nil {
if r.CSUser, err := r.CSClient.NewClientFromSpec(cfg); err != nil {

Can we remove the else statement with this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not without a more verbose variable declaration to bring both vars into scope. : )

if err != nil && strings.Contains(strings.ToLower(err.Error()), "i/o timeout") {
return newC, errors.Wrap(err, "timeout while checking CloudStack API Client connectivity")
}
return newC, errors.Wrap(err, "checking CloudStack API Client connectivity:")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this function always returns an error. When should it return nil for error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't. errors.Wrap will return nil if the passed err is nil.

pkg/cloud/user_credentials.go Outdated Show resolved Hide resolved
pkg/cloud/user_credentials.go Outdated Show resolved Hide resolved
pkg/cloud/user_credentials.go Outdated Show resolved Hide resolved

// GetUserWithKeys will search a domain and account for the first user that has api keys.
// Returns true if a user is found and false otherwise.
func (c *client) GetUserWithKeys(user *User) (bool, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this function work differently from calling ResolveUserKeys directly?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, ResolveUserKeys works if a user is already specified--for example you've already got a user's name or ID.

In all of our current cases we don't know of any sub-domain users until we run. As the method comment mentions, this will look at all users in a domain and resolve the passed user pointer to the first user that has sufficient API keys.


// CreateUserWithKeys will create a CloudStack user in the specified domain and account and generate API keyes for
// said user.
func (c *client) CreateUserWithKeys(user *User) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the functions not used and not implemented.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this is a draft PR, so yes I'll remove them. : )

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, I do eventually want methods like this in the codebase to be able to create domains/accounts/users on the fly in testing.

But since we will probably never do that in production, I'll probably put them in the test suite itself.

@aws-paris-bot aws-paris-bot added size/XL Denotes a PR that changes 500-999 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels May 9, 2022
@@ -109,7 +109,7 @@ func (c *client) ResolveTemplate(
zoneID string,
) (templateID string, retErr error) {
if len(csMachine.Spec.Template.ID) > 0 {
csTemplate, count, err := c.cs.Template.GetTemplateByID(csMachine.Spec.Template.ID, "all")
csTemplate, count, err := c.cs.Template.GetTemplateByID(csMachine.Spec.Template.ID, "executable")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"all" is only availalble to admin users.

// Attempt deletion regardless of machine state.
p := c.cs.VirtualMachine.NewDestroyVirtualMachineParams(*csMachine.Spec.InstanceID)
p := c.csAsync.VirtualMachine.NewDestroyVirtualMachineParams(*csMachine.Spec.InstanceID)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This shouldn't make any difference, but I was checking that.

We use the Async client here anyway, so felt better to match.

return fmt.Sprintf(`"%s" and "%s", %s`, account, domainID, desc)
}
}
DescribeTable("DomainID and Account test table.",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We no longer need to set domain and account, so all these extra tests are for code that doesn't exist.

@@ -229,7 +229,6 @@ var _ = Describe("Network", func() {
dummies.SetDummyIsoNetToNameOnly()
dummies.SetClusterSpecToNet(&dummies.ISONet1)
dummies.CSCluster.Spec.ControlPlaneEndpoint.Host = ""
Ω(client.ResolveZones(dummies.CSCluster)).Should(Succeed())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No such thing anymore!

@rejoshed rejoshed marked this pull request as ready for review May 9, 2022 19:28
@aws-paris-bot aws-paris-bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label May 9, 2022
@rejoshed rejoshed requested review from maxdrib and wongni May 9, 2022 19:35
@rejoshed
Copy link
Contributor Author

rejoshed commented May 9, 2022

@maxdrib

Would it be possible to create an e2e test for this scenario? It seems fairly complex so I'd feel more comfortable if we were validating that the users are handled correctly

Yes, it is possible. I will need to add an account and domain to our EC2 instance that has full perms, and then we'd just add that account and domain to our normal runs.

That said, I probably can't get to this today.

@maxdrib
Copy link
Contributor

maxdrib commented May 9, 2022

The code looks good to me. I think it'd be worth calling out the specific behavior that is implemented when using subdomains w.r.t. users expectations in the README

})

Context("UserCred Semi-Integ Tests", func() {
client, connectionErr := cloud.NewClient("../../cloud-config")
Copy link
Contributor

@maxdrib maxdrib May 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we be hardcoding this path in the tests? I'd prefer to look at the secrets environment variable being set instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completely, we should not.

This and other issues are why I want to turn my attention towards our CI/CD this week.

The semi-integ unit tests only work locally at the moment. They do pass for me, but there are other configuration hurdles besides this one that is preventing the semi-integs from working. For example, the name of the sub domain user should be configurable.

The E2E tests have some of this configuration, but not enough to run all tests. So, yeah. Working to get to this this week. : )

}

// Settup dummies.
// TODO: move these to the test dummies package.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could you create an issue to track this?

Copy link
Contributor Author

@rejoshed rejoshed May 9, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the overhead of an issue for this one todo is necessary, but I can if you really want. I'll be in this file this week too.


// Settup dummies.
// TODO: move these to the test dummies package.
domain = cloud.Domain{Path: "ROOT/blah/blah/subsub"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd also like to see a test case where domain is not provided and we assume it to be root

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will see about adding unit test for that soon, but this is handled via our E2Es.

@maxdrib
Copy link
Contributor

maxdrib commented May 9, 2022

Yes, it is possible. I will need to add an account and domain to our EC2 instance that has full perms, and then we'd just add that account and domain to our normal runs.

@rejoshed would you mind creating an issue to track this?

@aws-paris-bot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: maxdrib, rejoshed, wongni

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:
  • OWNERS [maxdrib,rejoshed,wongni]

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@rejoshed
Copy link
Contributor Author

rejoshed commented May 9, 2022

@maxdrib

E2E test issue for tracking.
#78

Yes, it is possible. I will need to add an account and domain to our EC2 instance that has full perms, and then we'd just add that account and domain to our normal runs.

@rejoshed would you mind creating an issue to track this?

@maxdrib
Copy link
Contributor

maxdrib commented May 9, 2022

/lgtm

@aws-paris-bot aws-paris-bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label May 9, 2022
@rejoshed rejoshed added /lgtm and removed lgtm "Looks good to me", indicates that a PR is ready to be merged. labels May 9, 2022
@kubernetes-sigs kubernetes-sigs deleted a comment from aws-paris-bot May 9, 2022
@rejoshed rejoshed merged commit 382c908 into main May 9, 2022
@rejoshed rejoshed deleted the feature/subdomain-user-operations branch May 9, 2022 20:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. /lgtm size/XL Denotes a PR that changes 500-999 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants