Skip to content

Commit c1aac1c

Browse files
Merge pull request #17137 from juanvallejo/jvallejo/allow-resource-kind-format-rsync
Automatic merge from submit-queue. allow rsrs/kind format in oc rsync Fixes #15076 Updates `oc rsync` to allow a pod to be passed with the `<kind>/<name>` format. cc @openshift/cli-review
2 parents 13add52 + 09bb51a commit c1aac1c

File tree

2 files changed

+69
-6
lines changed

2 files changed

+69
-6
lines changed

pkg/oc/cli/cmd/rsync/pathspec.go

+53-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"strings"
88

99
kvalidation "k8s.io/kubernetes/pkg/api/validation"
10+
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
1011
)
1112

1213
// pathSpec represents a path (remote or local) given as a source or destination
@@ -46,10 +47,21 @@ func (s *pathSpec) Validate() error {
4647
return nil
4748
}
4849

50+
// isPathForPod receives a path and returns true
51+
// if it matches a <podName>:/path format
52+
func isPathForPod(path string) bool {
53+
parts := strings.SplitN(path, ":", 2)
54+
if len(parts) == 1 || (isWindows() && len(parts[0]) == 1) {
55+
return false
56+
}
57+
58+
return true
59+
}
60+
4961
// parsePathSpec parses a string argument into a pathSpec object
5062
func parsePathSpec(path string) (*pathSpec, error) {
5163
parts := strings.SplitN(path, ":", 2)
52-
if len(parts) == 1 || (isWindows() && len(parts[0]) == 1) {
64+
if !isPathForPod(path) {
5365
return &pathSpec{
5466
Path: path,
5567
}, nil
@@ -63,6 +75,46 @@ func parsePathSpec(path string) (*pathSpec, error) {
6375
}, nil
6476
}
6577

78+
// resolveResourceKindPath determines if a given path contains a resource
79+
// formatted as resource/kind, and returns the resource name without the
80+
// <kind/> segment, ensuring that the resource is of type Pod, if it exists.
81+
func resolveResourceKindPath(f kcmdutil.Factory, path, namespace string) (string, error) {
82+
parts := strings.SplitN(path, ":", 2)
83+
if !isPathForPod(path) {
84+
return path, nil
85+
}
86+
87+
podName := parts[0]
88+
89+
// if the specified pod name is given in the <kind>/<name> format
90+
// validate the podName without the <kind/> segment.
91+
if podSegs := strings.Split(podName, "/"); len(podSegs) > 1 {
92+
podName = podSegs[1]
93+
}
94+
95+
r := f.NewBuilder(true).
96+
NamespaceParam(namespace).
97+
SingleResourceType().
98+
ResourceNames("pods", podName).
99+
Do()
100+
101+
if err := r.Err(); err != nil {
102+
return "", err
103+
}
104+
infos, err := r.Infos()
105+
if err != nil {
106+
return "", err
107+
}
108+
109+
// if there were no errors, we should expect
110+
// one resource to exist
111+
if len(infos) == 0 || infos[0].Mapping.Resource != "pods" {
112+
return "", fmt.Errorf("error: expected resource to be of type pod, got %q", infos[0].Mapping.Resource)
113+
}
114+
115+
return fmt.Sprintf("%s:%s", podName, parts[1]), nil
116+
}
117+
66118
// convertWindowsPath converts a windows native path to a path that can be used by
67119
// the rsync command in windows.
68120
// It can take one of three forms:

pkg/oc/cli/cmd/rsync/rsync.go

+16-5
Original file line numberDiff line numberDiff line change
@@ -186,22 +186,33 @@ func (o *RsyncOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args [
186186
return kcmdutil.UsageError(cmd, "only SOURCE_DIR and POD:DESTINATION_DIR should be specified as arguments")
187187
}
188188

189-
// Set main command arguments
190189
var err error
191-
o.Source, err = parsePathSpec(args[0])
190+
namespace, _, err := f.DefaultNamespace()
192191
if err != nil {
193192
return err
194193
}
195-
o.Destination, err = parsePathSpec(args[1])
194+
o.Namespace = namespace
195+
196+
// allow and parse resources specified in the <kind>/<name> format
197+
parsedSourcePath, err := resolveResourceKindPath(f, args[0], namespace)
196198
if err != nil {
197199
return err
198200
}
199201

200-
namespace, _, err := f.DefaultNamespace()
202+
parsedDestPath, err := resolveResourceKindPath(f, args[1], namespace)
203+
if err != nil {
204+
return err
205+
}
206+
207+
// Set main command arguments
208+
o.Source, err = parsePathSpec(parsedSourcePath)
209+
if err != nil {
210+
return err
211+
}
212+
o.Destination, err = parsePathSpec(parsedDestPath)
201213
if err != nil {
202214
return err
203215
}
204-
o.Namespace = namespace
205216

206217
o.Strategy, err = o.determineStrategy(f, cmd, o.StrategyName)
207218
if err != nil {

0 commit comments

Comments
 (0)