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

tests: ducktape test of rpk -X and rpk profile #11048

Merged
merged 6 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/go/rpk/pkg/cli/cloud/auth/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import (

func newListCommand(fs afero.Fs, p *config.Params) *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List rpk cloud auths",
Args: cobra.ExactArgs(0),
Use: "list",
Aliases: []string{"ls"},
Short: "List rpk cloud auths",
Args: cobra.ExactArgs(0),
Run: func(*cobra.Command, []string) {
cfg, err := p.Load(fs)
out.MaybeDie(err, "unable to load config: %v", err)
Expand Down
7 changes: 4 additions & 3 deletions src/go/rpk/pkg/cli/profile/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import (

func newListCommand(fs afero.Fs, p *config.Params) *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List rpk profiles",
Args: cobra.ExactArgs(0),
Use: "list",
Aliases: []string{"ls"},
Short: "List rpk profiles",
Args: cobra.ExactArgs(0),
Run: func(*cobra.Command, []string) {
cfg, err := p.Load(fs)
out.MaybeDie(err, "unable to load config: %v", err)
Expand Down
46 changes: 24 additions & 22 deletions tests/rptest/clients/rpk.py
Original file line number Diff line number Diff line change
Expand Up @@ -833,11 +833,12 @@ def cluster_config_set(self, key: str, value):
]
return self._execute(cmd)

def _execute(self, cmd, stdin=None, timeout=None):
def _execute(self, cmd, stdin=None, timeout=None, log_cmd=True):
if timeout is None:
timeout = DEFAULT_TIMEOUT

self._redpanda.logger.debug("Executing command: %s", cmd)
if log_cmd:
self._redpanda.logger.debug("Executing command: %s", cmd)

p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
Expand All @@ -856,7 +857,8 @@ def _execute(self, cmd, stdin=None, timeout=None):
self._redpanda.logger.error(error)
raise RpkException(
'command %s returned %d, output: %s' %
(' '.join(cmd), p.returncode, output), error, p.returncode)
(' '.join(cmd) if log_cmd else '[redacted]', p.returncode,
output), error, p.returncode)

return output

Expand Down Expand Up @@ -934,26 +936,26 @@ def parse(line):

def _kafka_conn_settings(self):
flags = [
"--brokers",
self._redpanda.brokers(),
"-X",
"brokers=" + self._redpanda.brokers(),
]
if self._username:
flags += [
"--user",
self._username,
"--password",
self._password,
"--sasl-mechanism",
self._sasl_mechanism,
"-X",
"user=" + self._username,
"-X",
"pass=" + self._password,
"-X",
"sasl.mechanism=" + self._sasl_mechanism,
]
if self._tls_cert:
flags += [
"--tls-key",
self._tls_cert.key,
"--tls-cert",
self._tls_cert.crt,
"--tls-truststore",
self._tls_cert.ca.crt,
"-X",
"tls.key=" + self._tls_cert.key,
"-X",
"tls.cert=" + self._tls_cert.crt,
"-X",
"tls.ca=" + self._tls_cert.ca.crt,
]
return flags

Expand Down Expand Up @@ -1023,8 +1025,8 @@ def cluster_metadata_id(self):
because there are already other ways to get at that.
"""
cmd = [
self._rpk_binary(), '--brokers',
self._redpanda.brokers(), 'cluster', 'metadata'
self._rpk_binary(), '-X', "brokers=" + self._redpanda.brokers(),
'cluster', 'metadata'
]
output = self._execute(cmd)
lines = output.strip().split("\n")
Expand All @@ -1043,16 +1045,16 @@ def cluster_metadata_id(self):

def license_set(self, path, license=""):
cmd = [
self._rpk_binary(), "--api-urls",
self._admin_host(), "cluster", "license", "set"
self._rpk_binary(), "-X", "admin.hosts=" + self._admin_host(),
"cluster", "license", "set"
]

if license:
cmd += [license]
if path:
cmd += ["--path", path]

return self._execute(cmd)
return self._execute(cmd, log_cmd=False)

def license_info(self):

Expand Down
75 changes: 73 additions & 2 deletions tests/rptest/clients/rpk_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,79 @@ def _run_config(self, cmd, path=None, timeout=30):

return self._execute(cmd, timeout=timeout)

def _execute(self, cmd, timeout=30):
self._redpanda.logger.debug("Executing command: %s", cmd)
def _run_profile(self, cmd):
cmd = [self._rpk_binary(), "profile"] + cmd
return self._execute(cmd)

def create_profile(self, name):
cmd = ["create", name]
return self._run_profile(cmd)

def create_profile_simple(self, name, cfg_location):
return self._run_profile(
['create', name, "--from-simple", cfg_location])

def use_profile(self, name):
cmd = ["use", name]
return self._run_profile(cmd)

def delete_profile(self, name):
cmd = ["delete", name]
return self._run_profile(cmd)

def rename_profile(self, new_name):
cmd = ["rename-to", new_name]
return self._run_profile(cmd)

def set_profile(self, kv):
cmd = ["set", kv]
return self._run_profile(cmd)

def list_profiles(self):
cmd = ["list"]
out = self._run_profile(cmd)
lines = out.splitlines()
if len(lines) == 1:
return []

def profile_line(line):
parts = line.split()
# We remove the asterisk that denotes that is the selected profile. Not needed here.
return parts[0].strip("*")

for i, line in enumerate(lines):
if line.split() == ["NAME", "DESCRIPTION"]:
return list(map(profile_line, lines[i + 1:]))

def create_topic_no_flags(self, name):
cmd = [self._rpk_binary(), "topic", "create", name]
return self._execute(cmd)

def cloud_login_cc(self, id, secret):

cmd = [
self._rpk_binary(), "cloud", "login", "--client-id", id,
"--client-secret", secret, "--save", "--no-profile"
]

self._redpanda.logger.debug(
"Executing command: %s cloud login --client-id %s --client-secret [redacted]",
self._rpk_binary(), id)

return self._execute(cmd, log_cmd=False)

def cloud_logout(self, clear_credentials=True):

cmd = [self._rpk_binary(), "cloud", "logout"]

if clear_credentials:
cmd += ["--clear-credentials"]

return self._execute(cmd)

def _execute(self, cmd, timeout=30, log_cmd=True):
if log_cmd:
self._redpanda.logger.debug("Executing command: %s", cmd)

return self._node.account.ssh_output(
' '.join(cmd),
Expand Down
3 changes: 3 additions & 0 deletions tests/rptest/services/redpanda.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,6 +693,7 @@ class RedpandaServiceBase(Service):
TRIM_LOGS_KEY = "trim_logs"
DATA_DIR = os.path.join(PERSISTENT_ROOT, "data")
NODE_CONFIG_FILE = "/etc/redpanda/redpanda.yaml"
RPK_CONFIG_FILE = "/root/.config/rpk/rpk.yaml"
CLUSTER_BOOTSTRAP_CONFIG_FILE = "/etc/redpanda/.bootstrap.yaml"
TLS_SERVER_KEY_FILE = "/etc/redpanda/server.key"
TLS_SERVER_CRT_FILE = "/etc/redpanda/server.crt"
Expand Down Expand Up @@ -2840,6 +2841,8 @@ def clean_node(self,
f"{RedpandaService.PERSISTENT_ROOT}/data/*")
if node.account.exists(RedpandaService.NODE_CONFIG_FILE):
node.account.remove(f"{RedpandaService.NODE_CONFIG_FILE}")
if node.account.exists(RedpandaService.RPK_CONFIG_FILE):
node.account.remove(f"{RedpandaService.RPK_CONFIG_FILE}")
if node.account.exists(RedpandaService.CLUSTER_BOOTSTRAP_CONFIG_FILE):
node.account.remove(
f"{RedpandaService.CLUSTER_BOOTSTRAP_CONFIG_FILE}")
Expand Down
64 changes: 64 additions & 0 deletions tests/rptest/tests/rpk_cloud_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright 2023 Redpanda Data, Inc.
#
# Use of this software is governed by the Business Source License
# included in the file licenses/BSL.md
#
# As of the Change Date specified in that file, in accordance with
# the Business Source License, use of this software will be governed
# by the Apache License, Version 2.0

import os

from rptest.services.cluster import cluster

from rptest.utils.rpk_config import read_rpk_cfg
from rptest.tests.redpanda_test import RedpandaTest
from rptest.clients.rpk_remote import RpkRemoteTool


def get_ci_env_var(env_var):
out = os.environ.get(env_var, None)
if out is None:
is_ci = os.environ.get("CI", "false")
if is_ci == "true":
raise RuntimeError(
f"Expected {env_var} variable to be set in this environment")

return out


class RpkCloudTest(RedpandaTest):
def __init__(self, ctx):
super(RpkCloudTest, self).__init__(test_context=ctx)
self._ctx = ctx

@cluster(num_nodes=1)
def test_cloud_login_logout_cc(self):
"""
Test login to cloud via rpk using client
credentials, make sure we store the token and
then delete it when we logout.
"""
id = get_ci_env_var("RPK_TEST_CLIENT_ID")
secret = get_ci_env_var("RPK_TEST_CLIENT_SECRET")
if id is None or secret is None:
self.logger.warn(
"Skipping test, client credentials env vars not found")
return

node = self.redpanda.get_node(0)
rpk = RpkRemoteTool(self.redpanda, node)

output = rpk.cloud_login_cc(id, secret)
assert "Successfully logged in" in output

# Check for a token present in file.
rpk_yaml = read_rpk_cfg(node)
assert rpk_yaml["cloud_auth"][0]["auth_token"] is not None

# Check that the token is not there anymore.
output = rpk.cloud_logout()
assert "You are now logged out" in output
rpk_yaml = read_rpk_cfg(node)

assert "auth_token" not in rpk_yaml["cloud_auth"][0]
Loading