Skip to content

Commit

Permalink
play: add missed credentials pass methods
Browse files Browse the repository at this point in the history
The patch adds credentials pass via environment variables
and command flags.

Part of tarantool/roadmap-internal#281
  • Loading branch information
oleg-jukovec authored and psergee committed Oct 30, 2023
1 parent c133c92 commit d9597ab
Show file tree
Hide file tree
Showing 5 changed files with 116 additions and 5 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ stdout/stderr and `tt` logs go to `tt.log` file.

- tt completion: added luarocks completions.
- tarantool-ee: search and install development builds.
- ``tt play``: ability to pass username and password via flags and environment
variables.

### Fixed
- ``tt rocks``: broken ``--verbose`` option.
Expand Down
14 changes: 9 additions & 5 deletions cli/checkpoint/lua/play.lua
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,14 @@ local function filter_xlog(gen, param, state, opts, cb)
end
end

local function play(positional_arguments, keyword_arguments)
local opts = keyword_arguments
local function play(positional_arguments, keyword_arguments, opts)
local filter_opts = keyword_arguments
local uri = table.remove(positional_arguments, 1)
if uri == nil then
log.error('Internal error: empty URI is provided')
os.exit(1)
end
local remote = netbox.new(uri)
local remote = netbox.new(uri, opts)
if not remote:wait_connected() then
log.error('Fatal error: no connection to the host "%s"', uri)
os.exit(1)
Expand All @@ -61,7 +61,7 @@ local function play(positional_arguments, keyword_arguments)
print(string.format('• Play is processing file "%s" •', file))
io.stdout:flush()
local gen, param, state = xlog.pairs(file)
filter_xlog(gen, param, state, opts, function(record)
filter_xlog(gen, param, state, filter_opts, function(record)
local sid = record.BODY and record.BODY.space_id
if sid ~= nil then
local args, so = {}, remote.space[sid]
Expand Down Expand Up @@ -137,7 +137,11 @@ local function main()
end
end

play(positional_arguments, keyword_arguments)
local opts = {
user = os.getenv('TT_CLI_PLAY_USERNAME'),
password = os.getenv('TT_CLI_PLAY_PASSWORD'),
}
play(positional_arguments, keyword_arguments, opts)
end

main()
Expand Down
31 changes: 31 additions & 0 deletions cli/cmd/play.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
"encoding/json"
"errors"
"fmt"
"math"
"os"
Expand All @@ -11,6 +12,7 @@ import (
"github.com/spf13/cobra"
"github.com/tarantool/tt/cli/checkpoint"
"github.com/tarantool/tt/cli/cmdcontext"
"github.com/tarantool/tt/cli/connect"
"github.com/tarantool/tt/cli/modules"
"github.com/tarantool/tt/cli/util"
"github.com/tarantool/tt/cli/version"
Expand All @@ -26,6 +28,13 @@ var playFlags = checkpoint.Opts{
ShowSystem: false,
}

var (
// playUsername contains username flag.
playUsername string
// playPassword contains password flag.
playPassword string
)

// NewPlayCmd creates a new play command.
func NewPlayCmd() *cobra.Command {
var playCmd = &cobra.Command{
Expand All @@ -39,6 +48,8 @@ func NewPlayCmd() *cobra.Command {
},
}

playCmd.Flags().StringVarP(&playUsername, "username", "u", "", "username")
playCmd.Flags().StringVarP(&playPassword, "password", "p", "", "password")
playCmd.Flags().Uint64Var(&playFlags.To, "to", playFlags.To,
"Show operations ending with the given lsn")
playCmd.Flags().Uint64Var(&playFlags.From, "from", playFlags.From,
Expand Down Expand Up @@ -68,7 +79,27 @@ func internalPlayModule(cmdCtx *cmdcontext.CmdCtx, args []string) error {
)
}

if connect.IsCredentialsURI(args[0]) {
if playUsername != "" || playPassword != "" {
return errors.New("username and password are specified with" +
" flags and a URI")
}
} else {
if playUsername == "" {
playUsername = os.Getenv(connect.TarantoolUsernameEnv)
}
if playPassword == "" {
playPassword = os.Getenv(connect.TarantoolPasswordEnv)
}
}

os.Setenv("TT_CLI_PLAY_FILES_AND_URI", string(filesAndUriJson))
if playUsername != "" {
os.Setenv("TT_CLI_PLAY_USERNAME", playUsername)
}
if playPassword != "" {
os.Setenv("TT_CLI_PLAY_PASSWORD", playPassword)
}
os.Setenv("TT_CLI_PLAY_SHOW_SYS", strconv.FormatBool(playFlags.ShowSystem))

// List of spaces is passed to lua play script via environment variable in json format.
Expand Down
2 changes: 2 additions & 0 deletions test/integration/play/test_file/remote_instance_cfg.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ local function configure_instance()
)
tester:create_index('primary', {type = 'tree', parts = {'id'}})
box.schema.user.grant('guest', 'read,write', 'space', 'tester')
box.schema.user.create('test_user', { password = 'secret' })
box.schema.user.grant('test_user', 'super')
end

configure_instance()
72 changes: 72 additions & 0 deletions test/integration/play/test_play.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,75 @@ def test_play_test_remote_instance(tt_cmd, tmpdir):
assert re.search(r"[1, 'Roxette', 1986]", output)
assert re.search(r"[2, 'Scorpions', 2015]", output)
assert re.search(r"[3, 'Ace of Base', 1993]", output)


@pytest.mark.parametrize("opts", [
pytest.param({"flags": ["--username=test_user", "--password=4"]}),
pytest.param({"flags": ["--username=fry"]}),
pytest.param({"env": {"TT_CLI_USERNAME": "test_user", "TT_CLI_PASSWORD": "4"}}),
pytest.param({"env": {"TT_CLI_USERNAME": "fry"}}),
pytest.param({"uri": "test_user:4"}),
])
def test_play_wrong_creds(tt_cmd, tmpdir, opts):
# Testing play using remote instance.
test_app_path = os.path.join(os.path.dirname(__file__), "test_file")
# Copy the .xlog file to the "run" directory.
shutil.copy(test_app_path + "/test.xlog", tmpdir)

# Create tarantool instance for testing and start it.
path_to_lua_utils = os.path.join(os.path.dirname(__file__), "test_file/../../../")
test_instance = TarantoolTestInstance(INSTANCE_NAME, test_app_path, path_to_lua_utils, tmpdir)
test_instance.start()

# Play .xlog file to the remote instance.
uri = "127.0.0.1:" + test_instance.port
if "uri" in opts:
uri = opts["uri"] + "@" + uri
if "env" in opts:
env = opts["env"]
else:
env = None
cmd = [tt_cmd, "play", uri, "test.xlog", "--space=999"]
if "flags" in opts:
cmd.extend(opts["flags"])

rc, output = run_command_and_get_output(cmd, cwd=tmpdir, env=env)
test_instance.stop()
assert rc != 0


@pytest.mark.parametrize("opts", [
pytest.param({"flags": ["--username=test_user", "--password=secret"]}),
pytest.param({"env": {
"TT_CLI_USERNAME": "test_user",
"TT_CLI_PASSWORD": "secret",
"PATH": os.getenv("PATH"),
}}),
pytest.param({"uri": "test_user:secret"}),
])
def test_play_creds(tt_cmd, tmpdir, opts):
# Testing play using remote instance.
test_app_path = os.path.join(os.path.dirname(__file__), "test_file")
# Copy the .xlog file to the "run" directory.
shutil.copy(test_app_path + "/test.xlog", tmpdir)

# Create tarantool instance for testing and start it.
path_to_lua_utils = os.path.join(os.path.dirname(__file__), "test_file/../../../")
test_instance = TarantoolTestInstance(INSTANCE_NAME, test_app_path, path_to_lua_utils, tmpdir)
test_instance.start()

# Play .xlog file to the remote instance.
uri = "127.0.0.1:" + test_instance.port
if "uri" in opts:
uri = opts["uri"] + "@" + uri
if "env" in opts:
env = opts["env"]
else:
env = None
cmd = [tt_cmd, "play", uri, "test.xlog", "--space=999"]
if "flags" in opts:
cmd.extend(opts["flags"])

rc, output = run_command_and_get_output(cmd, cwd=tmpdir, env=env)
test_instance.stop()
assert rc == 0

0 comments on commit d9597ab

Please sign in to comment.