Merge pull request #11304 from daehyeok/copy_node
Implement target node option for cp commandpull/11421/head
commit
2a2ffeb380
|
@ -25,8 +25,11 @@ import (
|
|||
"strings"
|
||||
|
||||
"k8s.io/minikube/pkg/minikube/assets"
|
||||
"k8s.io/minikube/pkg/minikube/command"
|
||||
"k8s.io/minikube/pkg/minikube/exit"
|
||||
"k8s.io/minikube/pkg/minikube/machine"
|
||||
"k8s.io/minikube/pkg/minikube/mustload"
|
||||
"k8s.io/minikube/pkg/minikube/node"
|
||||
"k8s.io/minikube/pkg/minikube/out"
|
||||
"k8s.io/minikube/pkg/minikube/reason"
|
||||
)
|
||||
|
@ -35,14 +38,16 @@ import (
|
|||
var (
|
||||
srcPath string
|
||||
dstPath string
|
||||
dstNode string
|
||||
)
|
||||
|
||||
// cpCmd represents the cp command, similar to docker cp
|
||||
var cpCmd = &cobra.Command{
|
||||
Use: "cp <source file path> <target file absolute path>",
|
||||
Use: "cp <source file path> <target node name>:<target file absolute path>",
|
||||
Short: "Copy the specified file into minikube",
|
||||
Long: "Copy the specified file into minikube, it will be saved at path <target file absolute path> in your minikube.\n" +
|
||||
"Example Command : \"minikube cp a.txt /home/docker/b.txt\"\n",
|
||||
"Example Command : \"minikube cp a.txt /home/docker/b.txt\"\n" +
|
||||
" \"minikube cp a.txt minikube-m02:/home/docker/b.txt\"\n",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if len(args) != 2 {
|
||||
exit.Message(reason.Usage, `Please specify the path to copy:
|
||||
|
@ -51,16 +56,47 @@ var cpCmd = &cobra.Command{
|
|||
|
||||
srcPath = args[0]
|
||||
dstPath = args[1]
|
||||
|
||||
// if destination path is not a absolute path, trying to parse with <node>:<abs path> format
|
||||
if !strings.HasPrefix(dstPath, "/") {
|
||||
if sp := strings.SplitN(dstPath, ":", 2); len(sp) == 2 {
|
||||
dstNode = sp[0]
|
||||
dstPath = sp[1]
|
||||
}
|
||||
}
|
||||
|
||||
validateArgs(srcPath, dstPath)
|
||||
|
||||
co := mustload.Running(ClusterFlagValue())
|
||||
fa, err := assets.NewFileAsset(srcPath, pt.Dir(dstPath), pt.Base(dstPath), "0644")
|
||||
if err != nil {
|
||||
out.ErrLn("%v", errors.Wrap(err, "getting file asset"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err = co.CP.Runner.Copy(fa); err != nil {
|
||||
co := mustload.Running(ClusterFlagValue())
|
||||
var runner command.Runner
|
||||
if dstNode == "" {
|
||||
runner = co.CP.Runner
|
||||
} else {
|
||||
n, _, err := node.Retrieve(*co.Config, dstNode)
|
||||
if err != nil {
|
||||
exit.Message(reason.GuestNodeRetrieve, "Node {{.nodeName}} does not exist.", out.V{"nodeName": dstNode})
|
||||
}
|
||||
|
||||
h, err := machine.GetHost(co.API, *co.Config, *n)
|
||||
if err != nil {
|
||||
out.ErrLn("%v", errors.Wrap(err, "getting host"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
runner, err = machine.CommandRunner(h)
|
||||
if err != nil {
|
||||
out.ErrLn("%v", errors.Wrap(err, "getting command runner"))
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
if err = runner.Copy(fa); err != nil {
|
||||
out.ErrLn("%v", errors.Wrap(err, "copying file"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,8 @@ import (
|
|||
"k8s.io/minikube/pkg/minikube/config"
|
||||
)
|
||||
|
||||
func getHost(api libmachine.API, cc config.ClusterConfig, n config.Node) (*host.Host, error) {
|
||||
// GetHost find node's host information by name in the given cluster.
|
||||
func GetHost(api libmachine.API, cc config.ClusterConfig, n config.Node) (*host.Host, error) {
|
||||
machineName := config.MachineName(cc, n)
|
||||
host, err := LoadHost(api, machineName)
|
||||
if err != nil {
|
||||
|
@ -49,7 +50,7 @@ func getHost(api libmachine.API, cc config.ClusterConfig, n config.Node) (*host.
|
|||
|
||||
// CreateSSHShell creates a new SSH shell / client
|
||||
func CreateSSHShell(api libmachine.API, cc config.ClusterConfig, n config.Node, args []string, native bool) error {
|
||||
host, err := getHost(api, cc, n)
|
||||
host, err := GetHost(api, cc, n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -70,7 +71,7 @@ func CreateSSHShell(api libmachine.API, cc config.ClusterConfig, n config.Node,
|
|||
|
||||
// GetSSHHostAddrPort returns the host address and port for ssh
|
||||
func GetSSHHostAddrPort(api libmachine.API, cc config.ClusterConfig, n config.Node) (string, int, error) {
|
||||
host, err := getHost(api, cc, n)
|
||||
host, err := GetHost(api, cc, n)
|
||||
if err != nil {
|
||||
return "", 0, err
|
||||
}
|
||||
|
|
|
@ -13,10 +13,11 @@ Copy the specified file into minikube
|
|||
|
||||
Copy the specified file into minikube, it will be saved at path <target file absolute path> in your minikube.
|
||||
Example Command : "minikube cp a.txt /home/docker/b.txt"
|
||||
"minikube cp a.txt minikube-m02:/home/docker/b.txt"
|
||||
|
||||
|
||||
```shell
|
||||
minikube cp <source file path> <target file absolute path> [flags]
|
||||
minikube cp <source file path> <target node name>:<target file absolute path> [flags]
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
|
|
@ -241,6 +241,9 @@ uses the minikube node add command to add a node to an existing cluster
|
|||
#### validateProfileListWithMultiNode
|
||||
make sure minikube profile list outputs correct with multinode clusters
|
||||
|
||||
#### validateCopyFileWithMultiNode
|
||||
validateProfileListWithMultiNode make sure minikube profile list outputs correct with multinode clusters
|
||||
|
||||
#### validateStopRunningNode
|
||||
tests the minikube node stop command
|
||||
|
||||
|
|
|
@ -1452,16 +1452,18 @@ func cpTestLocalPath() string {
|
|||
return filepath.Join(*testdataDir, "cp-test.txt")
|
||||
}
|
||||
|
||||
// validateCpCmd asserts basic "cp" command functionality
|
||||
func validateCpCmd(ctx context.Context, t *testing.T, profile string) {
|
||||
if NoneDriver() {
|
||||
t.Skipf("skipping: cp is unsupported by none driver")
|
||||
}
|
||||
|
||||
func testCpCmd(ctx context.Context, t *testing.T, profile string, node string) {
|
||||
srcPath := cpTestLocalPath()
|
||||
dstPath := cpTestMinikubePath()
|
||||
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "cp", srcPath, dstPath))
|
||||
cpArgv := []string{"-p", profile, "cp", srcPath}
|
||||
if node == "" {
|
||||
cpArgv = append(cpArgv, dstPath)
|
||||
} else {
|
||||
cpArgv = append(cpArgv, fmt.Sprintf("%s:%s", node, dstPath))
|
||||
}
|
||||
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), cpArgv...))
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
t.Errorf("failed to run command by deadline. exceeded timeout : %s", rr.Command())
|
||||
}
|
||||
|
@ -1469,7 +1471,13 @@ func validateCpCmd(ctx context.Context, t *testing.T, profile string) {
|
|||
t.Errorf("failed to run an cp command. args %q : %v", rr.Command(), err)
|
||||
}
|
||||
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "ssh", fmt.Sprintf("sudo cat %s", dstPath)))
|
||||
sshArgv := []string{"-p", profile, "ssh"}
|
||||
if node != "" {
|
||||
sshArgv = append(sshArgv, "-n", node)
|
||||
}
|
||||
sshArgv = append(sshArgv, fmt.Sprintf("sudo cat %s", dstPath))
|
||||
|
||||
rr, err = Run(t, exec.CommandContext(ctx, Target(), sshArgv...))
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
t.Errorf("failed to run command by deadline. exceeded timeout : %s", rr.Command())
|
||||
}
|
||||
|
@ -1487,6 +1495,15 @@ func validateCpCmd(ctx context.Context, t *testing.T, profile string) {
|
|||
}
|
||||
}
|
||||
|
||||
// validateCpCmd asserts basic "cp" command functionality
|
||||
func validateCpCmd(ctx context.Context, t *testing.T, profile string) {
|
||||
if NoneDriver() {
|
||||
t.Skipf("skipping: cp is unsupported by none driver")
|
||||
}
|
||||
|
||||
testCpCmd(ctx, t, profile, "")
|
||||
}
|
||||
|
||||
// validateMySQL validates a minimalist MySQL deployment
|
||||
func validateMySQL(ctx context.Context, t *testing.T, profile string) {
|
||||
if arm64Platform() {
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/minikube/cmd/minikube/cmd"
|
||||
"k8s.io/minikube/pkg/minikube/config"
|
||||
)
|
||||
|
||||
|
@ -49,6 +50,7 @@ func TestMultiNode(t *testing.T) {
|
|||
{"DeployApp2Nodes", validateDeployAppToMultiNode},
|
||||
{"AddNode", validateAddNodeToMultiNode},
|
||||
{"ProfileList", validateProfileListWithMultiNode},
|
||||
{"CopyFile", validateCopyFileWithMultiNode},
|
||||
{"StopNode", validateStopRunningNode},
|
||||
{"StartAfterStop", validateStartNodeAfterStop},
|
||||
{"DeleteNode", validateDeleteNodeFromMultiNode},
|
||||
|
@ -157,6 +159,31 @@ func validateProfileListWithMultiNode(ctx context.Context, t *testing.T, profile
|
|||
|
||||
}
|
||||
|
||||
// validateProfileListWithMultiNode make sure minikube profile list outputs correct with multinode clusters
|
||||
func validateCopyFileWithMultiNode(ctx context.Context, t *testing.T, profile string) {
|
||||
if NoneDriver() {
|
||||
t.Skipf("skipping: cp is unsupported by none driver")
|
||||
}
|
||||
|
||||
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "status", "--output", "json", "--alsologtostderr"))
|
||||
if err != nil && rr.ExitCode != 7 {
|
||||
t.Fatalf("failed to run minikube status. args %q : %v", rr.Command(), err)
|
||||
}
|
||||
|
||||
var statuses []cmd.Status
|
||||
if err = json.Unmarshal(rr.Stdout.Bytes(), &statuses); err != nil {
|
||||
t.Errorf("failed to decode json from status: args %q: %v", rr.Command(), err)
|
||||
}
|
||||
|
||||
for _, s := range statuses {
|
||||
if s.Worker {
|
||||
testCpCmd(ctx, t, profile, s.Name)
|
||||
} else {
|
||||
testCpCmd(ctx, t, profile, "")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validateStopRunningNode tests the minikube node stop command
|
||||
func validateStopRunningNode(ctx context.Context, t *testing.T, profile string) {
|
||||
// Run minikube node stop on that node
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
"Consider increasing Docker Desktop's memory size.": "",
|
||||
"Continuously listing/getting the status with optional interval duration.": "",
|
||||
"Copy the specified file into minikube": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n \\\"minikube cp a.txt minikube-m02:/home/docker/b.txt\\\"\\n": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "",
|
||||
"Could not process error from failed deletion": "",
|
||||
|
|
|
@ -100,7 +100,7 @@
|
|||
"Consider increasing Docker Desktop's memory size.": "Considera incrementar la memoria asignada a Docker Desktop",
|
||||
"Continuously listing/getting the status with optional interval duration.": "",
|
||||
"Copy the specified file into minikube": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n \\\"minikube cp a.txt minikube-m02:/home/docker/b.txt\\\"\\n": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "No se pudo determinar un proyecto de Google Cloud que podría estar bien.",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "No se puedo encontrar ninguna credencial de GCP. Corre `gcloud auth application-default login` o establezca la variable de entorno GOOGLE_APPLICATION_CREDENTIALS en la ruta de su archivo de credentiales.",
|
||||
"Could not process error from failed deletion": "No se pudo procesar el error de la eliminación fallida",
|
||||
|
|
|
@ -101,7 +101,7 @@
|
|||
"Consider increasing Docker Desktop's memory size.": "",
|
||||
"Continuously listing/getting the status with optional interval duration.": "",
|
||||
"Copy the specified file into minikube": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n \\\"minikube cp a.txt minikube-m02:/home/docker/b.txt\\\"\\n": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "",
|
||||
"Could not process error from failed deletion": "",
|
||||
|
|
|
@ -98,7 +98,7 @@
|
|||
"Consider increasing Docker Desktop's memory size.": "",
|
||||
"Continuously listing/getting the status with optional interval duration.": "",
|
||||
"Copy the specified file into minikube": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n \\\"minikube cp a.txt minikube-m02:/home/docker/b.txt\\\"\\n": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "",
|
||||
"Could not process error from failed deletion": "",
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
"Consider increasing Docker Desktop's memory size.": "",
|
||||
"Continuously listing/getting the status with optional interval duration.": "",
|
||||
"Copy the specified file into minikube": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n \\\"minikube cp a.txt minikube-m02:/home/docker/b.txt\\\"\\n": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "",
|
||||
"Could not process error from failed deletion": "",
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
"Consider increasing Docker Desktop's memory size.": "",
|
||||
"Continuously listing/getting the status with optional interval duration.": "",
|
||||
"Copy the specified file into minikube": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n \\\"minikube cp a.txt minikube-m02:/home/docker/b.txt\\\"\\n": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "",
|
||||
"Could not process error from failed deletion": "",
|
||||
|
|
|
@ -95,7 +95,7 @@
|
|||
"Consider increasing Docker Desktop's memory size.": "",
|
||||
"Continuously listing/getting the status with optional interval duration.": "",
|
||||
"Copy the specified file into minikube": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n \\\"minikube cp a.txt minikube-m02:/home/docker/b.txt\\\"\\n": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "",
|
||||
"Could not process error from failed deletion": "",
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
"Consider increasing Docker Desktop's memory size.": "",
|
||||
"Continuously listing/getting the status with optional interval duration.": "",
|
||||
"Copy the specified file into minikube": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n": "",
|
||||
"Copy the specified file into minikube, it will be saved at path \u003ctarget file absolute path\u003e in your minikube.\\nExample Command : \\\"minikube cp a.txt /home/docker/b.txt\\\"\\n \\\"minikube cp a.txt minikube-m02:/home/docker/b.txt\\\"\\n": "",
|
||||
"Could not determine a Google Cloud project, which might be ok.": "",
|
||||
"Could not find any GCP credentials. Either run `gcloud auth application-default login` or set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of your credentials file.": "",
|
||||
"Could not get profile flag": "无法获取配置文件标志",
|
||||
|
|
Loading…
Reference in New Issue