Skip to content

start adding unit tests for ironic.ValidateManagementAccess#647

Merged
metal3-io-bot merged 7 commits intometal3-io:masterfrom
dhellmann:unit-test-validate-management-access
Oct 20, 2020
Merged

start adding unit tests for ironic.ValidateManagementAccess#647
metal3-io-bot merged 7 commits intometal3-io:masterfrom
dhellmann:unit-test-validate-management-access

Conversation

@dhellmann
Copy link
Copy Markdown
Member

No description provided.

@metal3-io-bot metal3-io-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 Sep 23, 2020
@dhellmann dhellmann force-pushed the unit-test-validate-management-access branch from 89806b8 to d791e5b Compare September 23, 2020 14:27
@dhellmann
Copy link
Copy Markdown
Member Author

/test-integration

@dhellmann
Copy link
Copy Markdown
Member Author

I would like to freeze non-essential changes for a few days to try to land #650 without having to rebase it, because rebasing will mean redoing the work from scratch.

/hold

@metal3-io-bot metal3-io-bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Sep 24, 2020
@dhellmann dhellmann force-pushed the unit-test-validate-management-access branch from d791e5b to ba1e7d0 Compare October 1, 2020 15:19
@dhellmann
Copy link
Copy Markdown
Member Author

#655 has merged

/hold cancel

@metal3-io-bot metal3-io-bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Oct 1, 2020
@dhellmann
Copy link
Copy Markdown
Member Author

/test-integration

@dhellmann dhellmann force-pushed the unit-test-validate-management-access branch from ba1e7d0 to 28d2d40 Compare October 9, 2020 18:37
@dhellmann
Copy link
Copy Markdown
Member Author

I've rebased this on the work @andfasano did in #649

/test-integration

@dhellmann dhellmann requested a review from andfasano October 9, 2020 18:38
@dhellmann dhellmann force-pushed the unit-test-validate-management-access branch from 28d2d40 to 4beff98 Compare October 9, 2020 19:07
Comment thread pkg/provisioner/ironic/findhost_test.go Outdated
hostName: "name",
provisioningID: "uuid",
ironic: testserver.New(t, "ironic").NotFound("/v1/nodes/name").
ironic: testserver.NewIronic(t).NotFound("/v1/nodes/name").
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

NotFound as a generic method is ok, an alternative could be to use WithNodeError, ie:

testserver.NewIronic(t).WithNodeError("name", http.StatusNotFound).WithNodeError("uuid", http.StatusNotFound)

On a second pass, noticed you've added also a NoNode, which could be even better for simplifying mock's usage since it requires just the node name

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good point. Done.

bodyRaw, err := ioutil.ReadAll(r.Body)
if err != nil {
m.logRequest(r, fmt.Sprintf("ERROR: %s", err))
http.Error(w, fmt.Sprintf("%s", err), 500)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Minor point, http.StatusInternalServerError could be more readable

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed

response := fmt.Sprintf("{\"uuid\": \"%s\", %s", uuid, strings.TrimLeft(body, "{"))

w.Header().Set("Content-Type", "application/json")
w.WriteHeader(201)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

And http.StatusCreated here

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed

assert.Equal(t, "", result.ErrorMessage)
assert.NotEqual(t, "", host.Status.Provisioning.ID)
assert.Equal(t, ironic.CreatedNodes[0].UUID, host.Status.Provisioning.ID)
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(Not blocking) I noticed that the three test cases have been split into three different test methods (TestValidateManagementAccessNoMAC, TestValidateManagementAccessMACOptional and TestValidateManagementAccessCreateNode) sharing a pretty similar setup code.
Maybe it's not worth in this case, but to transform the three methods in a list of cases in a single test method it could be useful to "upgrade" the makeHost() factory method to a proper host builder object with fluent interface, so that also the host could become a parameter of the cases list (and of course also the expectations code will need to be adjusted).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Given that the ValidateManagementAccess is a pretty big method to be covered, the existing node and/or credentials change case will be added within this PR?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The setup portions of the functions are similar, but the checks were different enough that it seemed like it would be clearer to just write separate functions this time, instead of having more complicated logic to decide which tests to apply in each case.

In terms of test coverage, I think this PR is big enough and I would like to merge it before finishing the tests for ValidateManagementAccess.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes, makes sense

}

// Implements provisioner.EventPublisher to swallow events for tests.
func nullEventPublisher(reason, message string) {}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice one, we could introduce a set of different hard-coded publishers (ie null, std) to be reused in all the tests to remove some other lines of code

})

// hackily add uuid to the json response by inserting it to the front of the string
response := fmt.Sprintf("{\"uuid\": \"%s\", %s", uuid, strings.TrimLeft(body, "{"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just as a confirmation, is it fine to return all the fields sent in the body request as a response? From a quick glance on the API here should be fine. Maybe in future we could need something more sophisticated, but for the current test seems ok

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes, my understanding is the API is supposed to return the node, which may include new fields (as with UUID here) and should include the data passed to us. A better implementation would extract the input into a nodes.Node, add the UUID, then marshal it back to JSON for the response, but I'm trying to keep things simple.

@dhellmann dhellmann force-pushed the unit-test-validate-management-access branch from 4beff98 to 2f1cebc Compare October 13, 2020 14:20
@dhellmann dhellmann requested a review from andfasano October 13, 2020 14:20
@dhellmann dhellmann force-pushed the unit-test-validate-management-access branch from 2f1cebc to f1d8c9d Compare October 13, 2020 14:33
Copy link
Copy Markdown
Member

@andfasano andfasano left a comment

Choose a reason for hiding this comment

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

Current changes look fine to me

@metal3-io-bot
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: andfasano, dhellmann

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

The pull request process is described here

Details Needs approval from an approver in each of these files:

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

Signed-off-by: Doug Hellmann <dhellmann@redhat.com>
Make the BMC access type registration function public so we can add
fixture types in tests for the ironic provisioner.

Signed-off-by: Doug Hellmann <dhellmann@redhat.com>
Add a testbmc type so the ironic tests that create hosts can use a
test:// URL for the BMC address.

Signed-off-by: Doug Hellmann <dhellmann@redhat.com>
Verify that ValidateManagementAccess() reports an error when the
driver needs a bootMACAddress and the host does not have one.

Signed-off-by: Doug Hellmann <dhellmann@redhat.com>
Verify that ValidateManagementAccess() does not report an error when
the host has no boot MAC and the BMC does not require one.

Signed-off-by: Doug Hellmann <dhellmann@redhat.com>
Add CreateNodes() method to IronicMock to simulate creating a node.

Add a test for ValidateManagementAccess that triggers creating a node
and verifies that the host status is updated with the UUID of the new
node.

Signed-off-by: Doug Hellmann <dhellmann@redhat.com>
Look at the node struct we're given and register the responses for
both UUID and Name, based on which values are filled in.

Signed-off-by: Doug Hellmann <dhellmann@redhat.com>
@dhellmann dhellmann force-pushed the unit-test-validate-management-access branch from f1d8c9d to c167d52 Compare October 15, 2020 13:11
@dhellmann
Copy link
Copy Markdown
Member Author

/test-integration

Rebased to get the make docker fix from #647

@dhellmann dhellmann requested a review from andfasano October 15, 2020 13:12
@dhellmann
Copy link
Copy Markdown
Member Author

/cc @asalkeld

if node.UUID != "" {
m.ResponseJSON("/v1/nodes/"+node.UUID, node)
}
if node.Name != "" {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I have a couple of question on this change:

  • Is it a valid case to have the UUID unset and Name set?
  • When both UUID and Name are set, will the ServeMux.Handle panic?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

A real ironic service wouldn't have a node without a UUID, but in the tests we sometimes want the node to only be available via one or the other value to simulate the node having settings different from what the provisioner expects.

I'm not sure why the handler would panic? The endpoints are different (one looks up by UUID, the other by name).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In case Name == UUID, but I think it's a trivial case

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ah, yes, I didn't consider that. I think it's OK for the test to panic in that situation, since that doesn't seem like something we would expect to encounter in real data. I could add a test to protect against it, if you think it's worth it?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't think it's worth it, and agree it's fine to panic in such situation

Copy link
Copy Markdown
Contributor

@asalkeld asalkeld left a comment

Choose a reason for hiding this comment

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

/lgtm

@metal3-io-bot
Copy link
Copy Markdown
Contributor

@asalkeld: adding LGTM is restricted to approvers and reviewers in OWNERS files.

Details

In response to this:

/lgtm

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

@andfasano
Copy link
Copy Markdown
Member

I'm also fine with the changes

func init() {
bmc.RegisterFactory("test", newTestBMCAccessDetails, []string{})
bmc.RegisterFactory("test-needs-mac", newTestBMCAccessDetails, []string{})
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would it be safer to register these explicitly in tests rather than it happening as a side-effect here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Probably. On the other hand, all of the rest of the registry stuff expects to be invoked from an init() function like this, the registry is global state without a way to reset right now, and I'm not sure what happens if the same name is registered more than once.

I would be happy to consider making the registry more accepting of dynamic use in a separate PR.

@zaneb
Copy link
Copy Markdown
Member

zaneb commented Oct 20, 2020

/lgtm

@metal3-io-bot metal3-io-bot added the lgtm Indicates that a PR is ready to be merged. label Oct 20, 2020
@metal3-io-bot metal3-io-bot merged commit d055c59 into metal3-io:master Oct 20, 2020
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 Indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants