... | ... |
@@ -9,6 +9,7 @@ import ( |
9 | 9 |
kapi "k8s.io/kubernetes/pkg/api" |
10 | 10 |
"k8s.io/kubernetes/pkg/api/errors" |
11 | 11 |
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
12 |
+ "k8s.io/kubernetes/pkg/kubectl/resource" |
|
12 | 13 |
|
13 | 14 |
buildapi "github.com/openshift/origin/pkg/build/api" |
14 | 15 |
"github.com/openshift/origin/pkg/cmd/util/clientcmd" |
... | ... |
@@ -68,11 +69,20 @@ func RunCancelBuild(f *clientcmd.Factory, out io.Writer, cmd *cobra.Command, arg |
68 | 68 |
return err |
69 | 69 |
} |
70 | 70 |
buildClient := client.Builds(namespace) |
71 |
- build, err := buildClient.Get(buildName) |
|
71 |
+ |
|
72 |
+ mapper, typer := f.Object() |
|
73 |
+ obj, err := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()). |
|
74 |
+ NamespaceParam(namespace). |
|
75 |
+ ResourceNames("builds", buildName). |
|
76 |
+ SingleResourceType(). |
|
77 |
+ Do().Object() |
|
72 | 78 |
if err != nil { |
73 | 79 |
return err |
74 | 80 |
} |
75 |
- |
|
81 |
+ build, ok := obj.(*buildapi.Build) |
|
82 |
+ if !ok { |
|
83 |
+ return fmt.Errorf("%q is not a valid build", buildName) |
|
84 |
+ } |
|
76 | 85 |
if !isBuildCancellable(build) { |
77 | 86 |
return nil |
78 | 87 |
} |
... | ... |
@@ -120,7 +120,7 @@ func NewCmdDeploy(fullName string, f *clientcmd.Factory, out io.Writer) *cobra.C |
120 | 120 |
|
121 | 121 |
func (o *DeployOptions) Complete(f *clientcmd.Factory, args []string, out io.Writer) error { |
122 | 122 |
if len(args) > 1 { |
123 |
- return errors.New("only one deploymentConfig name is supported as argument.") |
|
123 |
+ return errors.New("only one deployment config name is supported as argument.") |
|
124 | 124 |
} |
125 | 125 |
var err error |
126 | 126 |
|
... | ... |
@@ -139,11 +139,7 @@ func (o *DeployOptions) Complete(f *clientcmd.Factory, args []string, out io.Wri |
139 | 139 |
o.out = out |
140 | 140 |
|
141 | 141 |
if len(args) > 0 { |
142 |
- name := args[0] |
|
143 |
- if strings.Index(name, "/") == -1 { |
|
144 |
- name = fmt.Sprintf("dc/%s", name) |
|
145 |
- } |
|
146 |
- o.deploymentConfigName = name |
|
142 |
+ o.deploymentConfigName = args[0] |
|
147 | 143 |
} |
148 | 144 |
|
149 | 145 |
return nil |
... | ... |
@@ -151,7 +147,7 @@ func (o *DeployOptions) Complete(f *clientcmd.Factory, args []string, out io.Wri |
151 | 151 |
|
152 | 152 |
func (o DeployOptions) Validate() error { |
153 | 153 |
if len(o.deploymentConfigName) == 0 { |
154 |
- return errors.New("a deploymentConfig name is required.") |
|
154 |
+ return errors.New("a deployment config name is required.") |
|
155 | 155 |
} |
156 | 156 |
numOptions := 0 |
157 | 157 |
if o.deployLatest { |
... | ... |
@@ -175,7 +171,7 @@ func (o DeployOptions) Validate() error { |
175 | 175 |
func (o DeployOptions) RunDeploy() error { |
176 | 176 |
r := o.builder. |
177 | 177 |
NamespaceParam(o.namespace). |
178 |
- ResourceTypeOrNameArgs(false, o.deploymentConfigName). |
|
178 |
+ ResourceNames("deploymentconfigs", o.deploymentConfigName). |
|
179 | 179 |
SingleResourceType(). |
180 | 180 |
Do() |
181 | 181 |
resultObj, err := r.Object() |
... | ... |
@@ -184,7 +180,7 @@ func (o DeployOptions) RunDeploy() error { |
184 | 184 |
} |
185 | 185 |
config, ok := resultObj.(*deployapi.DeploymentConfig) |
186 | 186 |
if !ok { |
187 |
- return fmt.Errorf("%s is not a valid deploymentconfig", o.deploymentConfigName) |
|
187 |
+ return fmt.Errorf("%s is not a valid deployment config", o.deploymentConfigName) |
|
188 | 188 |
} |
189 | 189 |
|
190 | 190 |
switch { |
... | ... |
@@ -27,6 +27,7 @@ import ( |
27 | 27 |
|
28 | 28 |
buildapi "github.com/openshift/origin/pkg/build/api" |
29 | 29 |
osclient "github.com/openshift/origin/pkg/client" |
30 |
+ osutil "github.com/openshift/origin/pkg/cmd/util" |
|
30 | 31 |
"github.com/openshift/origin/pkg/cmd/util/clientcmd" |
31 | 32 |
"github.com/openshift/origin/pkg/generate/git" |
32 | 33 |
"github.com/openshift/source-to-image/pkg/tar" |
... | ... |
@@ -129,15 +130,37 @@ func RunStartBuild(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra |
129 | 129 |
return cmdutil.UsageError(cmd, "Must pass a name of a build config or specify build name with '--from-build' flag") |
130 | 130 |
} |
131 | 131 |
|
132 |
- name := buildName |
|
133 |
- isBuild := true |
|
132 |
+ namespace, _, err := f.DefaultNamespace() |
|
133 |
+ if err != nil { |
|
134 |
+ return err |
|
135 |
+ } |
|
136 |
+ |
|
137 |
+ var ( |
|
138 |
+ name = buildName |
|
139 |
+ resource = "builds" |
|
140 |
+ ) |
|
141 |
+ |
|
142 |
+ if len(name) == 0 && len(args) > 0 && len(args[0]) > 0 { |
|
143 |
+ mapper, _ := f.Object() |
|
144 |
+ resource, name, err = osutil.ResolveResource("buildconfigs", args[0], mapper) |
|
145 |
+ if err != nil { |
|
146 |
+ return err |
|
147 |
+ } |
|
148 |
+ switch resource { |
|
149 |
+ case "buildconfigs": |
|
150 |
+ // no special handling required |
|
151 |
+ case "builds": |
|
152 |
+ return fmt.Errorf("use --from-build to rerun your builds") |
|
153 |
+ default: |
|
154 |
+ return fmt.Errorf("invalid resource provided: %s", resource) |
|
155 |
+ } |
|
156 |
+ } |
|
134 | 157 |
if len(name) == 0 { |
135 |
- name = args[0] |
|
136 |
- isBuild = false |
|
158 |
+ return fmt.Errorf("a resource name is required either as an argument or by using --from-build") |
|
137 | 159 |
} |
138 | 160 |
|
139 | 161 |
if webhooks.Provided() { |
140 |
- return RunListBuildWebHooks(f, out, cmd.Out(), name, isBuild, webhooks.String()) |
|
162 |
+ return RunListBuildWebHooks(f, out, cmd.Out(), name, resource, webhooks.String()) |
|
141 | 163 |
} |
142 | 164 |
|
143 | 165 |
client, _, err := f.Clients() |
... | ... |
@@ -145,11 +168,6 @@ func RunStartBuild(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra |
145 | 145 |
return err |
146 | 146 |
} |
147 | 147 |
|
148 |
- namespace, _, err := f.DefaultNamespace() |
|
149 |
- if err != nil { |
|
150 |
- return err |
|
151 |
- } |
|
152 |
- |
|
153 | 148 |
request := &buildapi.BuildRequest{ |
154 | 149 |
ObjectMeta: kapi.ObjectMeta{Name: name}, |
155 | 150 |
} |
... | ... |
@@ -166,7 +184,7 @@ func RunStartBuild(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra |
166 | 166 |
|
167 | 167 |
var newBuild *buildapi.Build |
168 | 168 |
switch { |
169 |
- case !isBuild && (len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0): |
|
169 |
+ case len(args) > 0 && (len(fromFile) > 0 || len(fromDir) > 0 || len(fromRepo) > 0): |
|
170 | 170 |
request := &buildapi.BinaryBuildRequestOptions{ |
171 | 171 |
ObjectMeta: kapi.ObjectMeta{ |
172 | 172 |
Name: name, |
... | ... |
@@ -177,16 +195,16 @@ func RunStartBuild(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra |
177 | 177 |
if newBuild, err = streamPathToBuild(git, in, cmd.Out(), client.BuildConfigs(namespace), fromDir, fromFile, fromRepo, request); err != nil { |
178 | 178 |
return err |
179 | 179 |
} |
180 |
- |
|
181 |
- case isBuild: |
|
180 |
+ case resource == "builds": |
|
182 | 181 |
if newBuild, err = client.Builds(namespace).Clone(request); err != nil { |
183 | 182 |
return err |
184 | 183 |
} |
185 |
- |
|
186 |
- default: |
|
184 |
+ case resource == "buildconfigs": |
|
187 | 185 |
if newBuild, err = client.BuildConfigs(namespace).Instantiate(request); err != nil { |
188 | 186 |
return err |
189 | 187 |
} |
188 |
+ default: |
|
189 |
+ return fmt.Errorf("invalid resource provided: %s", resource) |
|
190 | 190 |
} |
191 | 191 |
|
192 | 192 |
fmt.Fprintln(out, newBuild.Name) |
... | ... |
@@ -240,7 +258,7 @@ func RunStartBuild(f *clientcmd.Factory, in io.Reader, out io.Writer, cmd *cobra |
240 | 240 |
} |
241 | 241 |
|
242 | 242 |
// RunListBuildWebHooks prints the webhooks for the provided build config. |
243 |
-func RunListBuildWebHooks(f *clientcmd.Factory, out, errOut io.Writer, name string, isBuild bool, webhookFilter string) error { |
|
243 |
+func RunListBuildWebHooks(f *clientcmd.Factory, out, errOut io.Writer, name, resource, webhookFilter string) error { |
|
244 | 244 |
generic, github := false, false |
245 | 245 |
prefix := false |
246 | 246 |
switch webhookFilter { |
... | ... |
@@ -263,7 +281,10 @@ func RunListBuildWebHooks(f *clientcmd.Factory, out, errOut io.Writer, name stri |
263 | 263 |
return err |
264 | 264 |
} |
265 | 265 |
|
266 |
- if isBuild { |
|
266 |
+ switch resource { |
|
267 |
+ case "buildconfigs": |
|
268 |
+ // no special handling required |
|
269 |
+ case "builds": |
|
267 | 270 |
build, err := client.Builds(namespace).Get(name) |
268 | 271 |
if err != nil { |
269 | 272 |
return err |
... | ... |
@@ -276,7 +297,10 @@ func RunListBuildWebHooks(f *clientcmd.Factory, out, errOut io.Writer, name stri |
276 | 276 |
namespace = ref.Namespace |
277 | 277 |
} |
278 | 278 |
name = ref.Name |
279 |
+ default: |
|
280 |
+ return fmt.Errorf("invalid resource provided: %s", resource) |
|
279 | 281 |
} |
282 |
+ |
|
280 | 283 |
config, err := client.BuildConfigs(namespace).Get(name) |
281 | 284 |
if err != nil { |
282 | 285 |
return err |
... | ... |
@@ -162,7 +162,7 @@ func (o AddSecretOptions) Validate() error { |
162 | 162 |
func (o AddSecretOptions) AddSecrets() error { |
163 | 163 |
r := resource.NewBuilder(o.Mapper, o.Typer, o.ClientMapper). |
164 | 164 |
NamespaceParam(o.Namespace). |
165 |
- ResourceTypeOrNameArgs(false, o.TargetName). |
|
165 |
+ ResourceNames("serviceaccounts", o.TargetName). |
|
166 | 166 |
SingleResourceType(). |
167 | 167 |
Do() |
168 | 168 |
if r.Err() != nil { |
... | ... |
@@ -223,7 +223,7 @@ func (o AddSecretOptions) addSecretsToServiceAccount(serviceaccount *kapi.Servic |
223 | 223 |
func (o AddSecretOptions) getSecrets() ([]*kapi.Secret, error) { |
224 | 224 |
r := resource.NewBuilder(o.Mapper, o.Typer, o.ClientMapper). |
225 | 225 |
NamespaceParam(o.Namespace). |
226 |
- ResourceTypeOrNameArgs(false, o.SecretNames...). |
|
226 |
+ ResourceNames("secrets", o.SecretNames...). |
|
227 | 227 |
SingleResourceType(). |
228 | 228 |
Do() |
229 | 229 |
if r.Err() != nil { |
... | ... |
@@ -14,6 +14,7 @@ import ( |
14 | 14 |
|
15 | 15 |
"github.com/openshift/origin/pkg/client" |
16 | 16 |
"github.com/openshift/origin/pkg/cmd/cli/describe" |
17 |
+ osutil "github.com/openshift/origin/pkg/cmd/util" |
|
17 | 18 |
"github.com/openshift/origin/pkg/cmd/util/clientcmd" |
18 | 19 |
imageapi "github.com/openshift/origin/pkg/image/api" |
19 | 20 |
imagegraph "github.com/openshift/origin/pkg/image/graph/nodes" |
... | ... |
@@ -43,7 +44,6 @@ const BuildChainRecommendedCommandName = "build-chain" |
43 | 43 |
// BuildChainOptions contains all the options needed for build-chain |
44 | 44 |
type BuildChainOptions struct { |
45 | 45 |
name string |
46 |
- tag string |
|
47 | 46 |
|
48 | 47 |
defaultNamespace string |
49 | 48 |
namespaces sets.String |
... | ... |
@@ -62,7 +62,7 @@ func NewCmdBuildChain(name, fullName string, f *clientcmd.Factory, out io.Writer |
62 | 62 |
namespaces: sets.NewString(), |
63 | 63 |
} |
64 | 64 |
cmd := &cobra.Command{ |
65 |
- Use: "build-chain [IMAGESTREAM:TAG]", |
|
65 |
+ Use: "build-chain IMAGESTREAMTAG", |
|
66 | 66 |
Short: "Output the inputs and dependencies of your builds", |
67 | 67 |
Long: buildChainLong, |
68 | 68 |
Example: fmt.Sprintf(buildChainExample, fullName), |
... | ... |
@@ -84,7 +84,7 @@ func NewCmdBuildChain(name, fullName string, f *clientcmd.Factory, out io.Writer |
84 | 84 |
// Complete completes the required options for build-chain |
85 | 85 |
func (o *BuildChainOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, args []string, out io.Writer) error { |
86 | 86 |
if len(args) != 1 { |
87 |
- return cmdutil.UsageError(cmd, "Must pass an image stream name and optionally a tag. In case of an empty tag, 'latest' will be used.") |
|
87 |
+ return cmdutil.UsageError(cmd, "Must pass an image stream tag. If only an image stream name is specified, 'latest' will be used for the tag.") |
|
88 | 88 |
} |
89 | 89 |
|
90 | 90 |
// Setup client |
... | ... |
@@ -94,12 +94,20 @@ func (o *BuildChainOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, a |
94 | 94 |
} |
95 | 95 |
o.c, o.t = oc, oc |
96 | 96 |
|
97 |
- // Parse user input |
|
98 |
- o.name, o.tag, err = buildChainInput(args[0]) |
|
97 |
+ resource := "" |
|
98 |
+ mapper, _ := f.Object() |
|
99 |
+ resource, o.name, err = osutil.ResolveResource("imagestreamtags", args[0], mapper) |
|
99 | 100 |
if err != nil { |
100 |
- return cmdutil.UsageError(cmd, err.Error()) |
|
101 |
+ return err |
|
102 |
+ } |
|
103 |
+ |
|
104 |
+ switch resource { |
|
105 |
+ case "imagestreamtags": |
|
106 |
+ o.name = imageapi.NormalizeImageStreamTag(o.name) |
|
107 |
+ glog.V(4).Infof("Using %q as the image stream tag to look dependencies for", o.name) |
|
108 |
+ default: |
|
109 |
+ return fmt.Errorf("invalid resource provided: %s", resource) |
|
101 | 110 |
} |
102 |
- glog.V(4).Infof("Using '%s:%s' as the image stream tag to look dependencies for", o.name, o.tag) |
|
103 | 111 |
|
104 | 112 |
// Setup namespace |
105 | 113 |
if o.allNamespaces { |
... | ... |
@@ -120,7 +128,7 @@ func (o *BuildChainOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, a |
120 | 120 |
} |
121 | 121 |
|
122 | 122 |
o.defaultNamespace = namespace |
123 |
- glog.V(4).Infof("Using %q as the namespace for '%s:%s'", o.defaultNamespace, o.name, o.tag) |
|
123 |
+ glog.V(4).Infof("Using %q as the namespace for %q", o.defaultNamespace, o.name) |
|
124 | 124 |
o.namespaces.Insert(namespace) |
125 | 125 |
glog.V(4).Infof("Will look for deps in %s", strings.Join(o.namespaces.List(), ",")) |
126 | 126 |
|
... | ... |
@@ -130,10 +138,7 @@ func (o *BuildChainOptions) Complete(f *clientcmd.Factory, cmd *cobra.Command, a |
130 | 130 |
// Validate returns validation errors regarding build-chain |
131 | 131 |
func (o *BuildChainOptions) Validate() error { |
132 | 132 |
if len(o.name) == 0 { |
133 |
- return fmt.Errorf("image stream name cannot be empty") |
|
134 |
- } |
|
135 |
- if len(o.tag) == 0 { |
|
136 |
- o.tag = imageapi.DefaultImageTag |
|
133 |
+ return fmt.Errorf("image stream tag cannot be empty") |
|
137 | 134 |
} |
138 | 135 |
if len(o.defaultNamespace) == 0 { |
139 | 136 |
return fmt.Errorf("default namespace cannot be empty") |
... | ... |
@@ -153,15 +158,17 @@ func (o *BuildChainOptions) Validate() error { |
153 | 153 |
// RunBuildChain contains all the necessary functionality for the OpenShift |
154 | 154 |
// experimental build-chain command |
155 | 155 |
func (o *BuildChainOptions) RunBuildChain() error { |
156 |
- ist := imagegraph.MakeImageStreamTagObjectMeta(o.defaultNamespace, o.name, o.tag) |
|
156 |
+ ist := imagegraph.MakeImageStreamTagObjectMeta2(o.defaultNamespace, o.name) |
|
157 |
+ |
|
157 | 158 |
desc, err := describe.NewChainDescriber(o.c, o.namespaces, o.output).Describe(ist, !o.triggerOnly) |
158 | 159 |
if err != nil { |
159 | 160 |
if _, isNotFoundErr := err.(describe.NotFoundErr); isNotFoundErr { |
161 |
+ name, tag, _ := imageapi.SplitImageStreamTag(o.name) |
|
160 | 162 |
// Try to get the imageStreamTag via a direct GET |
161 |
- if _, getErr := o.t.ImageStreamTags(o.defaultNamespace).Get(o.name, o.tag); getErr != nil { |
|
163 |
+ if _, getErr := o.t.ImageStreamTags(o.defaultNamespace).Get(name, tag); getErr != nil { |
|
162 | 164 |
return getErr |
163 | 165 |
} |
164 |
- fmt.Printf("Image stream tag '%s:%s' in %q doesn't have any dependencies.\n", o.name, o.tag, o.defaultNamespace) |
|
166 |
+ fmt.Printf("Image stream tag %q in %q doesn't have any dependencies.\n", o.name, o.defaultNamespace) |
|
165 | 167 |
return nil |
166 | 168 |
} |
167 | 169 |
return err |
... | ... |
@@ -171,26 +178,3 @@ func (o *BuildChainOptions) RunBuildChain() error { |
171 | 171 |
|
172 | 172 |
return nil |
173 | 173 |
} |
174 |
- |
|
175 |
-// buildChainInput parses user input and returns a stream name, a tag |
|
176 |
-// and an error if any |
|
177 |
-func buildChainInput(input string) (string, string, error) { |
|
178 |
- // Split name and tag |
|
179 |
- name, tag, _ := imageapi.SplitImageStreamTag(input) |
|
180 |
- |
|
181 |
- // Support resource type/name syntax |
|
182 |
- // TODO: Use the RESTMapper to resolve this |
|
183 |
- resource := strings.Split(name, "/") |
|
184 |
- switch len(resource) { |
|
185 |
- case 1: |
|
186 |
- case 2: |
|
187 |
- resourceType := resource[0] |
|
188 |
- if resourceType != "istag" && resourceType != "imagestreamtag" { |
|
189 |
- return "", "", fmt.Errorf("invalid resource type %q", resourceType) |
|
190 |
- } |
|
191 |
- default: |
|
192 |
- return "", "", fmt.Errorf("invalid image stream name %q", name) |
|
193 |
- } |
|
194 |
- |
|
195 |
- return name, tag, nil |
|
196 |
-} |
... | ... |
@@ -1,6 +1,7 @@ |
1 | 1 |
package util |
2 | 2 |
|
3 | 3 |
import ( |
4 |
+ "errors" |
|
4 | 5 |
"fmt" |
5 | 6 |
"io" |
6 | 7 |
"path/filepath" |
... | ... |
@@ -8,6 +9,7 @@ import ( |
8 | 8 |
|
9 | 9 |
"github.com/spf13/cobra" |
10 | 10 |
|
11 |
+ "k8s.io/kubernetes/pkg/api/meta" |
|
11 | 12 |
kcmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" |
12 | 13 |
) |
13 | 14 |
|
... | ... |
@@ -31,3 +33,30 @@ func GetDisplayFilename(filename string) string { |
31 | 31 |
|
32 | 32 |
return filename |
33 | 33 |
} |
34 |
+ |
|
35 |
+// ResolveResource returns the resource type and name of the resourceString. |
|
36 |
+// If the resource string has no specified type, defaultResource will be returned. |
|
37 |
+func ResolveResource(defaultResource, resourceString string, mapper meta.RESTMapper) (string, string, error) { |
|
38 |
+ if mapper == nil { |
|
39 |
+ return "", "", errors.New("mapper cannot be nil") |
|
40 |
+ } |
|
41 |
+ |
|
42 |
+ var name string |
|
43 |
+ parts := strings.Split(resourceString, "/") |
|
44 |
+ switch len(parts) { |
|
45 |
+ case 1: |
|
46 |
+ name = parts[0] |
|
47 |
+ case 2: |
|
48 |
+ _, kind, err := mapper.VersionAndKindForResource(parts[0]) |
|
49 |
+ if err != nil { |
|
50 |
+ return "", "", err |
|
51 |
+ } |
|
52 |
+ name = parts[1] |
|
53 |
+ resource, _ := meta.KindToResource(kind, false) |
|
54 |
+ return resource, name, nil |
|
55 |
+ default: |
|
56 |
+ return "", "", fmt.Errorf("invalid resource format: %s", resourceString) |
|
57 |
+ } |
|
58 |
+ |
|
59 |
+ return defaultResource, name, nil |
|
60 |
+} |
34 | 61 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,181 @@ |
0 |
+package util_test |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "testing" |
|
4 |
+ |
|
5 |
+ "k8s.io/kubernetes/pkg/kubectl" |
|
6 |
+ |
|
7 |
+ "github.com/openshift/origin/pkg/api/latest" |
|
8 |
+ "github.com/openshift/origin/pkg/cmd/util" |
|
9 |
+ "github.com/openshift/origin/pkg/cmd/util/clientcmd" |
|
10 |
+) |
|
11 |
+ |
|
12 |
+func TestResolveResource(t *testing.T) { |
|
13 |
+ mapper := clientcmd.ShortcutExpander{RESTMapper: kubectl.ShortcutExpander{RESTMapper: latest.RESTMapper}} |
|
14 |
+ |
|
15 |
+ tests := []struct { |
|
16 |
+ name string |
|
17 |
+ defaultResource string |
|
18 |
+ resourceString string |
|
19 |
+ expectedResource string |
|
20 |
+ expectedName string |
|
21 |
+ expectedErr bool |
|
22 |
+ }{ |
|
23 |
+ { |
|
24 |
+ name: "invalid case #1", |
|
25 |
+ defaultResource: "", |
|
26 |
+ resourceString: "a/b/c", |
|
27 |
+ expectedResource: "", |
|
28 |
+ expectedName: "", |
|
29 |
+ expectedErr: true, |
|
30 |
+ }, |
|
31 |
+ { |
|
32 |
+ name: "invalid case #2", |
|
33 |
+ defaultResource: "", |
|
34 |
+ resourceString: "foo/bar", |
|
35 |
+ expectedResource: "", |
|
36 |
+ expectedName: "", |
|
37 |
+ expectedErr: true, |
|
38 |
+ }, |
|
39 |
+ { |
|
40 |
+ name: "empty resource string case #1", |
|
41 |
+ defaultResource: "", |
|
42 |
+ resourceString: "", |
|
43 |
+ expectedResource: "", |
|
44 |
+ expectedName: "", |
|
45 |
+ expectedErr: false, |
|
46 |
+ }, |
|
47 |
+ { |
|
48 |
+ name: "empty resource string case #2", |
|
49 |
+ defaultResource: "", |
|
50 |
+ resourceString: "bar", |
|
51 |
+ expectedResource: "", |
|
52 |
+ expectedName: "bar", |
|
53 |
+ expectedErr: false, |
|
54 |
+ }, |
|
55 |
+ { |
|
56 |
+ name: "empty resource string case #3", |
|
57 |
+ defaultResource: "foo", |
|
58 |
+ resourceString: "bar", |
|
59 |
+ expectedResource: "foo", |
|
60 |
+ expectedName: "bar", |
|
61 |
+ expectedErr: false, |
|
62 |
+ }, |
|
63 |
+ { |
|
64 |
+ name: "(KUBE) short name", |
|
65 |
+ defaultResource: "foo", |
|
66 |
+ resourceString: "rc/bar", |
|
67 |
+ expectedResource: "replicationcontrollers", |
|
68 |
+ expectedName: "bar", |
|
69 |
+ expectedErr: false, |
|
70 |
+ }, |
|
71 |
+ { |
|
72 |
+ name: "(KUBE) long name, case insensitive #1", |
|
73 |
+ defaultResource: "foo", |
|
74 |
+ resourceString: "replicationcontroller/bar", |
|
75 |
+ expectedResource: "replicationcontrollers", |
|
76 |
+ expectedName: "bar", |
|
77 |
+ expectedErr: false, |
|
78 |
+ }, |
|
79 |
+ { |
|
80 |
+ name: "(KUBE) long name, case insensitive #2", |
|
81 |
+ defaultResource: "foo", |
|
82 |
+ resourceString: "replicationcontrollers/bar", |
|
83 |
+ expectedResource: "replicationcontrollers", |
|
84 |
+ expectedName: "bar", |
|
85 |
+ expectedErr: false, |
|
86 |
+ }, |
|
87 |
+ { |
|
88 |
+ name: "(KUBE) long name, case insensitive #3", |
|
89 |
+ defaultResource: "foo", |
|
90 |
+ resourceString: "ReplicationControllers/bar", |
|
91 |
+ expectedResource: "replicationcontrollers", |
|
92 |
+ expectedName: "bar", |
|
93 |
+ expectedErr: false, |
|
94 |
+ }, |
|
95 |
+ { |
|
96 |
+ name: "(KUBE) long name, case insensitive #4", |
|
97 |
+ defaultResource: "foo", |
|
98 |
+ resourceString: "ReplicationControllers/bar", |
|
99 |
+ expectedResource: "replicationcontrollers", |
|
100 |
+ expectedName: "bar", |
|
101 |
+ expectedErr: false, |
|
102 |
+ }, |
|
103 |
+ { |
|
104 |
+ name: "(KUBE) long name, case insensitive #5", |
|
105 |
+ defaultResource: "foo", |
|
106 |
+ resourceString: "ReplicationControllers/Bar", |
|
107 |
+ expectedResource: "replicationcontrollers", |
|
108 |
+ expectedName: "Bar", |
|
109 |
+ expectedErr: false, |
|
110 |
+ }, |
|
111 |
+ { |
|
112 |
+ name: "(ORIGIN) short name", |
|
113 |
+ defaultResource: "foo", |
|
114 |
+ resourceString: "bc/bar", |
|
115 |
+ expectedResource: "buildconfigs", |
|
116 |
+ expectedName: "bar", |
|
117 |
+ expectedErr: false, |
|
118 |
+ }, |
|
119 |
+ { |
|
120 |
+ name: "(ORIGIN) long name, case insensitive #1", |
|
121 |
+ defaultResource: "foo", |
|
122 |
+ resourceString: "buildconfig/bar", |
|
123 |
+ expectedResource: "buildconfigs", |
|
124 |
+ expectedName: "bar", |
|
125 |
+ expectedErr: false, |
|
126 |
+ }, |
|
127 |
+ { |
|
128 |
+ name: "(ORIGIN) long name, case insensitive #2", |
|
129 |
+ defaultResource: "foo", |
|
130 |
+ resourceString: "buildconfigs/bar", |
|
131 |
+ expectedResource: "buildconfigs", |
|
132 |
+ expectedName: "bar", |
|
133 |
+ expectedErr: false, |
|
134 |
+ }, |
|
135 |
+ { |
|
136 |
+ name: "(ORIGIN) long name, case insensitive #3", |
|
137 |
+ defaultResource: "foo", |
|
138 |
+ resourceString: "BuildConfigs/bar", |
|
139 |
+ expectedResource: "buildconfigs", |
|
140 |
+ expectedName: "bar", |
|
141 |
+ expectedErr: false, |
|
142 |
+ }, |
|
143 |
+ { |
|
144 |
+ name: "(ORIGIN) long name, case insensitive #4", |
|
145 |
+ defaultResource: "foo", |
|
146 |
+ resourceString: "BuildConfigs/bar", |
|
147 |
+ expectedResource: "buildconfigs", |
|
148 |
+ expectedName: "bar", |
|
149 |
+ expectedErr: false, |
|
150 |
+ }, |
|
151 |
+ { |
|
152 |
+ name: "(ORIGIN) long name, case insensitive #5", |
|
153 |
+ defaultResource: "foo", |
|
154 |
+ resourceString: "BuildConfigs/Bar", |
|
155 |
+ expectedResource: "buildconfigs", |
|
156 |
+ expectedName: "Bar", |
|
157 |
+ expectedErr: false, |
|
158 |
+ }, |
|
159 |
+ } |
|
160 |
+ |
|
161 |
+ for _, test := range tests { |
|
162 |
+ gotResource, gotName, gotErr := util.ResolveResource(test.defaultResource, test.resourceString, mapper) |
|
163 |
+ if gotErr != nil && !test.expectedErr { |
|
164 |
+ t.Errorf("%s: expected no error, got %v", test.name, gotErr) |
|
165 |
+ continue |
|
166 |
+ } |
|
167 |
+ if gotErr == nil && test.expectedErr { |
|
168 |
+ t.Errorf("%s: expected error but got none", test.name) |
|
169 |
+ continue |
|
170 |
+ } |
|
171 |
+ if gotResource != test.expectedResource { |
|
172 |
+ t.Errorf("%s: expected resource type %s, got %s", test.name, test.expectedResource, gotResource) |
|
173 |
+ continue |
|
174 |
+ } |
|
175 |
+ if gotName != test.expectedName { |
|
176 |
+ t.Errorf("%s: expected resource name %s, got %s", test.name, test.expectedName, gotName) |
|
177 |
+ continue |
|
178 |
+ } |
|
179 |
+ } |
|
180 |
+} |
... | ... |
@@ -210,6 +210,16 @@ func JoinImageStreamTag(name, tag string) string { |
210 | 210 |
return fmt.Sprintf("%s:%s", name, tag) |
211 | 211 |
} |
212 | 212 |
|
213 |
+// NormalizeImageStreamTag normalizes an image stream tag by defaulting to 'latest' |
|
214 |
+// if no tag has been specified. |
|
215 |
+func NormalizeImageStreamTag(name string) string { |
|
216 |
+ if !strings.Contains(name, ":") { |
|
217 |
+ // Default to latest |
|
218 |
+ return JoinImageStreamTag(name, DefaultImageTag) |
|
219 |
+ } |
|
220 |
+ return name |
|
221 |
+} |
|
222 |
+ |
|
213 | 223 |
// ImageWithMetadata returns a copy of image with the DockerImageMetadata filled in |
214 | 224 |
// from the raw DockerImageManifest data stored in the image. |
215 | 225 |
func ImageWithMetadata(image Image) (*Image, error) { |
... | ... |
@@ -173,6 +173,9 @@ echo "registry: ok" |
173 | 173 |
|
174 | 174 |
# Test building a dependency tree |
175 | 175 |
oc process -f examples/sample-app/application-template-stibuild.json -l build=sti | oc create -f - |
176 |
+# Test both the type/name resource syntax and the fact that istag/origin-ruby-sample:latest is still |
|
177 |
+# not created but due to a buildConfig pointing to it, we get back its graph of deps. |
|
178 |
+[ "$(oadm build-chain istag/origin-ruby-sample | grep 'imagestreamtag/origin-ruby-sample:latest')" ] |
|
176 | 179 |
[ "$(oadm build-chain ruby-20-centos7 -o dot | grep 'graph')" ] |
177 | 180 |
oc delete all -l build=sti |
178 | 181 |
echo "ex build-chain: ok" |
... | ... |
@@ -26,16 +26,16 @@ oc get buildConfigs |
26 | 26 |
oc get bc |
27 | 27 |
oc get builds |
28 | 28 |
|
29 |
-REAL_OUTPUT_TO=$(oc get bc/ruby-sample-build -t '{{ .spec.output.to.name }}') |
|
29 |
+REAL_OUTPUT_TO=$(oc get bc/ruby-sample-build --template='{{ .spec.output.to.name }}') |
|
30 | 30 |
oc patch bc/ruby-sample-build -p '{"spec":{"output":{"to":{"name":"different:tag1"}}}}' |
31 |
-oc get bc/ruby-sample-build -t '{{ .spec.output.to.name }}' | grep 'different' |
|
31 |
+oc get bc/ruby-sample-build --template='{{ .spec.output.to.name }}' | grep 'different' |
|
32 | 32 |
oc patch bc/ruby-sample-build -p "{\"spec\":{\"output\":{\"to\":{\"name\":\"${REAL_OUTPUT_TO}\"}}}}" |
33 | 33 |
echo "patchAnonFields: ok" |
34 | 34 |
|
35 | 35 |
[ "$(oc describe buildConfigs ruby-sample-build | grep --text "Webhook GitHub" | grep -F "${url}/oapi/v1/namespaces/${project}/buildconfigs/ruby-sample-build/webhooks/secret101/github")" ] |
36 | 36 |
[ "$(oc describe buildConfigs ruby-sample-build | grep --text "Webhook Generic" | grep -F "${url}/oapi/v1/namespaces/${project}/buildconfigs/ruby-sample-build/webhooks/secret101/generic")" ] |
37 | 37 |
oc start-build --list-webhooks='all' ruby-sample-build |
38 |
-[ "$(oc start-build --list-webhooks='all' ruby-sample-build | grep --text "generic")" ] |
|
38 |
+[ "$(oc start-build --list-webhooks='all' bc/ruby-sample-build | grep --text "generic")" ] |
|
39 | 39 |
[ "$(oc start-build --list-webhooks='all' ruby-sample-build | grep --text "github")" ] |
40 | 40 |
[ "$(oc start-build --list-webhooks='github' ruby-sample-build | grep --text "secret101")" ] |
41 | 41 |
[ ! "$(oc start-build --list-webhooks='blah')" ] |
... | ... |
@@ -50,11 +50,15 @@ oc create -f test/integration/fixtures/test-buildcli.json |
50 | 50 |
# the build should use the image field as defined in the buildconfig |
51 | 51 |
started=$(oc start-build ruby-sample-build-invalidtag) |
52 | 52 |
oc describe build ${started} | grep openshift/ruby-20-centos7$ |
53 |
+frombuild=$(oc start-build --from-build="${started}") |
|
54 |
+oc describe build ${frombuild} | grep openshift/ruby-20-centos7$ |
|
53 | 55 |
echo "start-build: ok" |
54 | 56 |
|
55 | 57 |
oc cancel-build "${started}" --dump-logs --restart |
58 |
+oc delete all --all |
|
59 |
+oc process -f examples/sample-app/application-template-dockerbuild.json -l build=docker | oc create -f - |
|
60 |
+tryuntil oc get build/ruby-sample-build-1 |
|
61 |
+# Uses type/name resource syntax |
|
62 |
+oc cancel-build build/ruby-sample-build-1 |
|
63 |
+oc delete all --all |
|
56 | 64 |
echo "cancel-build: ok" |
57 |
- |
|
58 |
-[ "$(oc delete is/ruby-20-centos7-buildcli | grep 'imagestream "ruby-20-centos7-buildcli" deleted')" ] |
|
59 |
-[ "$(oc delete bc/ruby-sample-build-validtag -o name | grep 'buildconfig/ruby-sample-build-validtag')" ] |
|
60 |
-[ "$(oc delete bc/ruby-sample-build-invalidtag | grep 'buildconfig "ruby-sample-build-invalidtag" deleted')" ] |
... | ... |
@@ -31,6 +31,7 @@ oc describe deploymentConfigs test-deployment-config |
31 | 31 |
[ "$(oc env dc/test-deployment-config TEST=bar OTHER=baz BAR-)" ] |
32 | 32 |
|
33 | 33 |
oc deploy test-deployment-config |
34 |
+oc deploy dc/test-deployment-config |
|
34 | 35 |
oc delete deploymentConfigs test-deployment-config |
35 | 36 |
echo "deploymentConfigs: ok" |
36 | 37 |
|
... | ... |
@@ -24,11 +24,11 @@ oc secrets new from-file .dockercfg=${HOME}/dockerconfig |
24 | 24 |
|
25 | 25 |
# attach secrets to service account |
26 | 26 |
# single secret with prefix |
27 |
-oc secrets add serviceaccounts/deployer secrets/dockercfg |
|
27 |
+oc secrets add deployer dockercfg |
|
28 | 28 |
# don't add the same secret twice |
29 |
-oc secrets add serviceaccounts/deployer secrets/dockercfg secrets/from-file |
|
29 |
+oc secrets add serviceaccounts/deployer dockercfg secrets/from-file |
|
30 | 30 |
# make sure we can add as as pull secret |
31 |
-oc secrets add serviceaccounts/deployer secrets/dockercfg secrets/from-file --for=pull |
|
31 |
+oc secrets add deployer dockercfg from-file --for=pull |
|
32 | 32 |
# make sure we can add as as pull secret and mount secret at once |
33 | 33 |
oc secrets add serviceaccounts/deployer secrets/dockercfg secrets/from-file --for=pull,mount |
34 | 34 |
|