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

feature: add command for exporting service to peer or partition #15654

Merged
merged 57 commits into from
May 31, 2023

Conversation

nathancoleman
Copy link
Member

Description

Describe why you're making this change, in plain English.

Testing & Reproduction steps

  • In the case of bugs, describe how to replicate
  • If any manual tests were done, document the steps and the conditions to replicate
  • Call out any important/ relevant unit tests, e2e tests or integration tests you have added or are adding

Links

Include any links here that might be helpful for people reviewing your PR (Tickets, GH issues, API docs, external benchmarks, tools docs, etc). If there are none, feel free to delete this section.

Please be mindful not to leak any customer or confidential information. HashiCorp employees may want to use our internal URL shortener to obfuscate links.

PR Checklist

  • updated test coverage
  • external facing docs updated
  • not a security concern

@github-actions github-actions bot added pr/dependencies PR specifically updates dependencies of project theme/cli Flags and documentation for the CLI interface labels Dec 2, 2022
if !serviceExists {
cfg.Services = append(cfg.Services, api.ExportedService{
Name: c.serviceName,
Namespace: c.serviceNamespace,
Copy link
Member Author

@nathancoleman nathancoleman Dec 2, 2022

Choose a reason for hiding this comment

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

Notably, we can assign a namespace here even when using OSS. Discussed in the issue w/ @DanStough that we will want to update the config-entry validation on the server to return an error such as enterprise-only feature in a future PR.

Copy link
Member Author

@nathancoleman nathancoleman left a comment

Choose a reason for hiding this comment

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

One more question for you @DanStough: should we be making API calls to query for the service being exported to ensure that it exists, or should we depend on the server to validate that, or is that up to the user?

command/peering/export/export.go Outdated Show resolved Hide resolved
@DanStough
Copy link
Contributor

DanStough commented Dec 5, 2022

@nathancoleman , w.r.t. checking if the service exists, I would say no. Generally, design things in the CLI to support eventual consistency, so you don't need to worry about the order in which these things are created. It would be cool to have a -verify flag to add the check, but there isn't any precedent for this.

@DanStough
Copy link
Contributor

This looks awesome! One note is this would look almost identical if we made a command for exporting to partitions. I wonder if this should be a new top-level command, and we can create a followup tasks to support both -peers and -partitions?

@nathancoleman
Copy link
Member Author

@DanStough the question of whether this single command supports both peers and partitions or whether we have this command and another parition-specific command elsewhere in the CLI is something I'm expecting an answer from Jared on before we merge

@nathancoleman nathancoleman linked an issue Dec 12, 2022 that may be closed by this pull request
@nathancoleman nathancoleman requested review from DanStough and removed request for a team May 1, 2023 16:53
Copy link
Contributor

@DanStough DanStough left a comment

Choose a reason for hiding this comment

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

🥳 🍾 🎆 :shipit:

Comment on lines +86 to +100
t.Run("initial config entry should be created w/ partitions", func(t *testing.T) {

ui := cli.NewMockUi()
cmd := New(ui)

args := []string{
"-http-addr=" + a.HTTPAddr(),
"-name=testservice",
"-consumer-partitions=a,b",
}

code := cmd.Run(args)
require.Equal(t, 0, code)
require.Contains(t, ui.OutputWriter.String(), "Successfully exported service")
})
Copy link
Contributor

Choose a reason for hiding this comment

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

In a perfect world, we would move the partition test cases to another file export_test_ent.go, but since it looks like we don't have any server-side validation for this, I'm fine leaving it as it is.

Copy link
Contributor

@jkirschner-hashicorp jkirschner-hashicorp left a comment

Choose a reason for hiding this comment

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

Left a few optional suggestions for wording clarifications and some questions. Looks good - nice work team!

.changelog/15654.txt Outdated Show resolved Hide resolved
command/services/export/export.go Outdated Show resolved Hide resolved
command/services/export/export.go Outdated Show resolved Hide resolved
return 1
}

partitionNames, err := c.getPartitionNames()
Copy link
Contributor

Choose a reason for hiding this comment

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

What happens if partitions are specified in OSS?

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 follows the same theme as other enterprise features in this PR. The command with partitions specified will go through even for OSS users, same as if you use $ consul config write today (since this is really all that's happening behind the scenes).

Since the established pattern is to allow Enterprise features in the OSS CLI, the correct thing to do in the longer term IMO is to add server validation for this config entry that returns an error in this case.

Comment on lines +99 to +106
ok, _, err := client.ConfigEntries().CAS(cfg, cfg.GetModifyIndex(), nil)
if err != nil {
c.UI.Error(fmt.Sprintf("Error writing config entry: %s", err))
return 1
} else if !ok {
c.UI.Error(fmt.Sprintf("Config entry was changed during update. Please try again"))
return 1
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nice due diligence in handling this case :)

command/services/export/export.go Outdated Show resolved Hide resolved
if c.partitionNames != "" {
partitionNames = strings.Split(c.partitionNames, ",")
for _, partitionName := range partitionNames {
if partitionName == "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there any other validation of peer or partition names beyond "is it empty" that the backend does?

I guess the possible harm is that someone could write a config entry for a non-existent partition, or one with a mistyped/garbled name?

That said, we output a string like Successfully exported service %q to peers %q afterwards, so that would hopefully show whether something was wrong.

So maybe additional validation isn't important (unless it was really easy to do).

Copy link
Member Author

@nathancoleman nathancoleman May 30, 2023

Choose a reason for hiding this comment

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

@DanStough and I talked at one point about adding validation in the backend for this as a separate PR.

Today, you can write a config entry that exports to a non-existent peer or partition using consul config write - this command is no different since it uses the same config entry mechanism. Based on that, I consider adding more validation on the server side to be outside the scope of this PR. It would be good to get on someone's radar though. Thoughts?

nathancoleman and others added 5 commits May 30, 2023 12:19
Co-authored-by: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com>
Co-authored-by: Jared Kirschner <85913323+jkirschner-hashicorp@users.noreply.github.com>
Copy link
Contributor

@jkirschner-hashicorp jkirschner-hashicorp left a comment

Choose a reason for hiding this comment

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

LGTM :)

@nathancoleman nathancoleman merged commit b438a07 into main May 31, 2023
103 checks passed
@nathancoleman nathancoleman deleted the export-peering-cli branch May 31, 2023 18:27
@nathancoleman nathancoleman changed the title Export peering cli feature: add command for exporting service to peer or partition May 31, 2023
@david-yu
Copy link
Contributor

@nathancoleman Out of curiosity are there docs changes for this features as well? I currently do not see docs for this feature here: https://developer.hashicorp.com/consul/commands/services

@nathancoleman
Copy link
Member Author

nathancoleman commented Jun 29, 2023

@david-yu good catch - meant to get docs done before the 1.16 release and completely forgot. I'll get a PR up today and backport in 1.16.x.

Edit: See #18425

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pr/dependencies PR specifically updates dependencies of project pr/no-backport theme/cli Flags and documentation for the CLI interface
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CLI Peering Export Command
5 participants