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

Services: use ServiceStatus on API v1.41 and up #2157

Merged
merged 4 commits into from
Oct 29, 2019

Conversation

thaJeztah
Copy link
Member

@thaJeztah thaJeztah commented Oct 23, 2019

depends on:

Services: use ServiceStatus on API v1.41 and up

API v1.41 adds a new option to get the number of desired and running tasks when listing services. This patch enables this functionality, and provides a fallback mechanism when the ServiceStatus is not available, which would be when using an older API version.

Now that the swarm.Service struct captures this information, the ListInfo type is no longer needed, so it is removed, and the related list- and formatting functions have been modified accordingly.

To reduce repetition, sorting the services has been moved to the formatter. This is a slight change in behavior, but all calls to the formatter performed this sort first, so the change will not lead to user-facing changes.

@thaJeztah
Copy link
Member Author

thaJeztah commented Oct 24, 2019

taking care of the breaking changes in the homedir package first, in #2158 done

return fmt.Sprintf("%d/%d", running, desired)
}

func (c *serviceContext) maxReplicas() uint64 {
Copy link
Member Author

Choose a reason for hiding this comment

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

I want to export this one, so that it can be used in --format, but keeping that separate to reduce the changes a bit

02_bar bar replicated 2/4 *:80->8090/udp
01_baz baz global 1/3 *:80->8080/tcp
04_qux2 qux2 replicated 3/3 (max 2 per node)
03_qux10 qux10 replicated 2/3 (max 1 per node)
Copy link
Member Author

Choose a reason for hiding this comment

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

Added test-cases to test the max X per node output

`,
},
}

for _, testcase := range cases {
services := []swarm.Service{
{
ID: "id_baz",
ID: "01_baz",
Copy link
Member Author

Choose a reason for hiding this comment

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

prefixing the ID's with numbers, so that we verify the list is sorted by the service name not the service ID

bar replicated
baz global
qux2 replicated
qux10 replicated
Copy link
Member Author

Choose a reason for hiding this comment

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

Sorting moved to the formatter (see the PR description), which is why these tests now have their output in a different order. I added services named qux2 and qux10 to verify the formatter uses naturalsort (otherwise qux2 would come after qux10)

},
Endpoint: swarm.Endpoint{
Ports: []swarm.PortConfig{
{
PublishMode: "ingress",
PublishedPort: 80,
TargetPort: 8080,
Protocol: "tcp",
TargetPort: 8090,
Copy link
Member Author

@thaJeztah thaJeztah Oct 26, 2019

Choose a reason for hiding this comment

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

Not an important change, but multiple services cannot map to the same host-port, so this is just making the test-case more realistic/correct.

id_bar bar replicated 2/4 *:80->8080/tcp
`ID NAME MODE REPLICAS IMAGE PORTS
02_bar bar replicated 2/4 *:80->8090/udp
01_baz baz global 1/3 *:80->8080/tcp
Copy link
Member Author

Choose a reason for hiding this comment

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

changed the replica-count to be unique for each service, to verify we're showing the correct status

@thaJeztah thaJeztah force-pushed the servicestatus branch 7 times, most recently from 79b154b to f9bd3f8 Compare October 28, 2019 10:29
if err != nil {
return nil, err
}
if len(tasks) == 0 {
Copy link
Member Author

Choose a reason for hiding this comment

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

This optimisation just tipped the function over Gocyclo 16, requiring me to add a //nolint 😞 not sure if it's worth factoring these lines out to a separate function just for that

@thaJeztah thaJeztah marked this pull request as ready for review October 28, 2019 10:39
}
}
if len(status) == 0 {
// All services have their ServiceStatus set, so we're done
Copy link
Member Author

Choose a reason for hiding this comment

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

Theoretically, we could skip this whole function based on API version, but in situations where the API version is unknown/not set, we would not be propagating ServiceStatus (which happens, e.g., in our unit tests). To be on the safe side, the loop above, and this check, make sure that we always check if ServiceStatus is present, and otherwise fall back to the old behaviour of fetching tasks and nodes to get this information.

@thaJeztah thaJeztah force-pushed the servicestatus branch 2 times, most recently from 53a41cc to 66bcac6 Compare October 28, 2019 10:53
@@ -22,7 +29,315 @@ func TestServiceListOrder(t *testing.T) {
},
})
cmd := newListCommand(cli)
cmd.SetArgs([]string{})
Copy link
Member Author

Choose a reason for hiding this comment

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

This was to allow running the test separately in my IDE; when pre-compiling the test and running it, this test would otherwise pick-up the -test.run flags as arguments, and fail the test;

go test -c -o /tmp/foo.test github.com/docker/cli/cli/command/service \
go tool test2json -t /tmp/foo.test -test.v -test.run '^TestServiceListOrder$'

...
list_test.go:34: assertion failed: error is not nil: \"ls\" accepts no arguments.\n"}

@thaJeztah
Copy link
Member Author

okay, cleaned up the commits; this should be ready for review

ping @silvin-lubecki @dperny @rumpl @vdemeester PTAL

id_baz baz global 2/4 *:80->8080/tcp
id_bar bar replicated 2/4 *:80->8080/tcp
`ID NAME MODE REPLICAS IMAGE PORTS
02_bar bar replicated 2/4 *:80->8090/udp
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be sorted by service name? 🤔

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok just saw your comment below 👍

@dperny
Copy link
Contributor

dperny commented Oct 28, 2019

LGTM, thanks! Adding this functionality was actually on my todo list for the sprint, so I'm sorry I didn't communicate that.

@thaJeztah
Copy link
Member Author

@dperny no worries; it could've waited, but #2131 came up, where I looked at the changes, and thought: better make use of this new feature, so that we don't have to change the interface / exported functions multiple times.

And with this change, that refactor became quite a bit more simple (last commit on this PR: #2167)

return swarm.Service{
func withMode(mode string, replicas uint64) func(*swarm.Service) {
return func(service *swarm.Service) {
// service.Spec.Mode = swarm.ServiceMode{
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: commented code?

Copy link
Member Author

Choose a reason for hiding this comment

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

arf; good catch; I'll update

Copy link
Contributor

@silvin-lubecki silvin-lubecki left a comment

Choose a reason for hiding this comment

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

LGTM, that's a quite good feature there 🤗

@rumpl
Copy link
Member

rumpl commented Oct 29, 2019

LGTM! Thanks @thaJeztah !!

This patch:

- Adds new GlobalService and ServiceStatus options
- Makes the NodeList() function functional
- Minor improvment to the `newService()` function to allow passing options

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This also sets the services to have a Mode set, otherwise
they would be invalid.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
API v1.41 adds a new option to get the number of desired
and running tasks when listing services. This patch enables
this functionality, and provides a fallback mechanism when
the ServiceStatus is not available, which would be when
using an older API version.

Now that the swarm.Service struct captures this information,
the `ListInfo` type is no longer needed, so it is removed,
and the related list- and formatting functions have been
modified accordingly.

To reduce repetition, sorting the services has been moved
to the formatter. This is a slight change in behavior, but
all calls to the formatter performed this sort first, so
the change will not lead to user-facing changes.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
@thaJeztah
Copy link
Member Author

removed the stray comment; should be good to go now once CI finishes 👍

@thaJeztah
Copy link
Member Author

All nice and shiny green; I'll go ahead and merge 👍

@thaJeztah thaJeztah merged commit b3cde35 into docker:master Oct 29, 2019
@thaJeztah thaJeztah deleted the servicestatus branch October 29, 2019 14:57
@thaJeztah thaJeztah added this to the next milestone Feb 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants