Skip to content

Commit 2e1635b

Browse files
author
anencore94
committed
[Feature] Add minikube cp command
- add new feature represents cp local file into minikube - add functional test for cp command Signed-off-by: anencore94 <[email protected]>
1 parent 828769b commit 2e1635b

File tree

5 files changed

+141
-0
lines changed

5 files changed

+141
-0
lines changed

cmd/minikube/cmd/cp.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
Copyright 2016 The Kubernetes Authors All rights reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package cmd
18+
19+
import (
20+
"os"
21+
22+
"github.com/pkg/errors"
23+
"github.com/spf13/cobra"
24+
25+
"k8s.io/minikube/pkg/minikube/assets"
26+
"k8s.io/minikube/pkg/minikube/exit"
27+
"k8s.io/minikube/pkg/minikube/mustload"
28+
"k8s.io/minikube/pkg/minikube/out"
29+
"k8s.io/minikube/pkg/minikube/reason"
30+
)
31+
32+
// placeholders for flag values
33+
var (
34+
srcPath string
35+
dstPath string
36+
)
37+
38+
// cpCmd represents the cp command, similar to docker cp
39+
var cpCmd = &cobra.Command{
40+
Use: "cp <source file path> <target file path followed by '/home/docker/'>",
41+
Short: "Copy the specified file into minikube",
42+
Long: "Copy the specified file into minikube, it will be saved at path \"/home/docker/<target file path>\" in your minikube.\n" +
43+
"Example Command : \"minikube cp a.txt b.txt\"\n",
44+
Run: func(cmd *cobra.Command, args []string) {
45+
// validate args
46+
if len(args) != 2 {
47+
exit.Message(reason.Usage, `Please specify the path to copy:
48+
minikube cp <source file path> <target file path> (example: "minikube cp a/b/c/d.txt a.txt")`)
49+
}
50+
srcPath = args[0]
51+
dstPath = args[1]
52+
53+
co := mustload.Running(ClusterFlagValue())
54+
fa, err := assets.NewFileAsset(srcPath, "/home/docker/", dstPath, "0644")
55+
if err != nil {
56+
out.ErrLn("%v", errors.Wrap(err, "getting file asset"))
57+
os.Exit(1)
58+
}
59+
if err = co.CP.Runner.Copy(fa); err != nil {
60+
out.ErrLn("%v", errors.Wrap(err, "copying file"))
61+
os.Exit(1)
62+
}
63+
},
64+
}
65+
66+
func init() {
67+
}

cmd/minikube/cmd/root.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ func init() {
243243
sshCmd,
244244
kubectlCmd,
245245
nodeCmd,
246+
cpCmd,
246247
},
247248
},
248249
{
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
title: "cp"
3+
description: >
4+
Copy the specified file into minikube
5+
---
6+
7+
8+
## minikube cp
9+
10+
Copy the specified file into minikube
11+
12+
### Synopsis
13+
14+
Copy the specified file into minikube, it will be saved at path "/home/docker/<target file path>" in your minikube.
15+
Example Command : "minikube cp a.txt b.txt"
16+
17+
18+
```shell
19+
minikube cp <source file path> <target file path followed by '/home/docker/'> [flags]
20+
```
21+
22+
### Options inherited from parent commands
23+
24+
```
25+
--add_dir_header If true, adds the file directory to the header of the log messages
26+
--alsologtostderr log to standard error as well as files
27+
-b, --bootstrapper string The name of the cluster bootstrapper that will set up the Kubernetes cluster. (default "kubeadm")
28+
-h, --help
29+
--log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0)
30+
--log_dir string If non-empty, write log files in this directory
31+
--log_file string If non-empty, use this log file
32+
--log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800)
33+
--logtostderr log to standard error instead of files
34+
--one_output If true, only write logs to their native severity level (vs also writing to each lower severity level
35+
-p, --profile string The name of the minikube VM being used. This can be set to allow having multiple instances of minikube independently. (default "minikube")
36+
--skip_headers If true, avoid header prefixes in the log messages
37+
--skip_log_headers If true, avoid headers when opening log files
38+
--stderrthreshold severity logs at or above this threshold go to stderr (default 2)
39+
--user string Specifies the user executing the operation. Useful for auditing operations executed by 3rd party tools. Defaults to the operating system username.
40+
-v, --v Level number for the log level verbosity
41+
--vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging
42+
```
43+

test/integration/functional_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ func TestFunctional(t *testing.T) {
123123
{"PersistentVolumeClaim", validatePersistentVolumeClaim},
124124
{"TunnelCmd", validateTunnelCmd},
125125
{"SSHCmd", validateSSHCmd},
126+
{"CpCmd", validateCpCmd},
126127
{"MySQL", validateMySQL},
127128
{"FileSync", validateFileSync},
128129
{"CertSync", validateCertSync},
@@ -1143,6 +1144,34 @@ func validateSSHCmd(ctx context.Context, t *testing.T, profile string) {
11431144
}
11441145
}
11451146

1147+
// validateCpCmd asserts basic "cp" command functionality
1148+
func validateCpCmd(ctx context.Context, t *testing.T, profile string) {
1149+
if NoneDriver() {
1150+
t.Skipf("skipping: cp is unsupported by none driver")
1151+
}
1152+
1153+
cpPath := filepath.Join(*testdataDir, "cp-test.txt")
1154+
rr, err := Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "cp", cpPath, "hello_cp.txt"))
1155+
if ctx.Err() == context.DeadlineExceeded {
1156+
t.Errorf("failed to run command by deadline. exceeded timeout : %s", rr.Command())
1157+
}
1158+
if err != nil {
1159+
t.Errorf("failed to run an cp command. args %q : %v", rr.Command(), err)
1160+
}
1161+
1162+
expected := "Test file for checking file cp process"
1163+
rr, err = Run(t, exec.CommandContext(ctx, Target(), "-p", profile, "ssh", "cat hello_cp.txt"))
1164+
if ctx.Err() == context.DeadlineExceeded {
1165+
t.Errorf("failed to run command by deadline. exceeded timeout : %s", rr.Command())
1166+
}
1167+
if err != nil {
1168+
t.Errorf("failed to run an cp command. args %q : %v", rr.Command(), err)
1169+
}
1170+
if diff := cmp.Diff(expected, rr.Stdout.String()); diff != "" {
1171+
t.Errorf("/testdata/cp-test.txt content mismatch (-want +got):\n%s", diff)
1172+
}
1173+
}
1174+
11461175
// validateMySQL validates a minimalist MySQL deployment
11471176
func validateMySQL(ctx context.Context, t *testing.T, profile string) {
11481177
if arm64Platform() {
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Test file for checking file cp process

0 commit comments

Comments
 (0)