Skip to content

Commit 2c2445d

Browse files
Ark-kunk8s-ci-robot
authored andcommitted
Enable pipeline packages with multiple files (#939)
* Enable pipeline packages with multiple files * Added tests * Initialize the variables to nil * Trying to read the archive file entry immediately * Fixed the pipeline packages used by the `TestPipelineAPI` test. Also added a failing test case. Will disable it in next commit. * Disabling the test for the UploadFile bug I've discovered * Fixed the pipeline name. * Removed the disabled extra test. * Addressed the feedback. * Removed the "header == nil" check (feedback). * Fixed typo * Addressed the PR feedback Added space before comment. Checking for the error again.
1 parent 825f64d commit 2c2445d

File tree

11 files changed

+114
-11
lines changed

11 files changed

+114
-11
lines changed
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name: whalesay
2+
inputs:
3+
- name: param1
4+
- name: param2
5+
implementation:
6+
container:
7+
image: docker/whalesay:latest
8+
command: [cowsay]
9+
args: [{inputValue: param1}, {inputValue: param2}]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Copyright 2018 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
apiVersion: argoproj.io/v1alpha1
16+
kind: Workflow
17+
metadata:
18+
generateName: arguments-parameters-
19+
spec:
20+
entrypoint: whalesay
21+
arguments:
22+
parameters:
23+
- name: param1
24+
value: hello
25+
- name: param2
26+
27+
templates:
28+
- name: whalesay
29+
inputs:
30+
parameters:
31+
- name: param1
32+
- name: param2
33+
container:
34+
image: docker/whalesay:latest
35+
command: [cowsay]
36+
args: ["{{inputs.parameters.param1}}-{{inputs.parameters.param2}}"]

backend/src/apiserver/server/util.go

+45-5
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ func isYamlFile(fileName string) bool {
6262
return strings.HasSuffix(fileName, ".yaml") || strings.HasSuffix(fileName, ".yml")
6363
}
6464

65+
func isPipelineYamlFile(fileName string) bool {
66+
return fileName == "pipeline.yaml"
67+
}
68+
6569
func isZipFile(compressedFile []byte) bool {
6670
return len(compressedFile) > 2 && compressedFile[0] == '\x50' && compressedFile[1] == '\x4B' //Signature of zip file is "PK"
6771
}
@@ -75,13 +79,38 @@ func DecompressPipelineTarball(compressedFile []byte) ([]byte, error) {
7579
if err != nil {
7680
return nil, util.NewInvalidInputErrorWithDetails(err, "Error extracting pipeline from the tarball file. Not a valid tarball file.")
7781
}
82+
// New behavior: searching for the "pipeline.yaml" file.
7883
tarReader := tar.NewReader(gzipReader)
84+
for {
85+
header, err := tarReader.Next()
86+
if err == io.EOF {
87+
tarReader = nil
88+
break
89+
}
90+
if err != nil {
91+
return nil, util.NewInvalidInputErrorWithDetails(err, "Error extracting pipeline from the tarball file. Not a valid tarball file.")
92+
}
93+
if isPipelineYamlFile(header.Name) {
94+
//Found the pipeline file.
95+
break
96+
}
97+
}
98+
// Old behavior - taking the first file in the archive
99+
if tarReader == nil {
100+
// Resetting the reader
101+
gzipReader, err = gzip.NewReader(bytes.NewReader(compressedFile))
102+
if err != nil {
103+
return nil, util.NewInvalidInputErrorWithDetails(err, "Error extracting pipeline from the tarball file. Not a valid tarball file.")
104+
}
105+
tarReader = tar.NewReader(gzipReader)
106+
}
107+
79108
header, err := tarReader.Next()
80-
if err != nil || header == nil {
109+
if err != nil {
81110
return nil, util.NewInvalidInputErrorWithDetails(err, "Error extracting pipeline from the tarball file. Not a valid tarball file.")
82111
}
83112
if !isYamlFile(header.Name) {
84-
return nil, util.NewInvalidInputError("Error extracting pipeline from the tarball file. Expecting a YAML file inside the tarball. Got: %v", header.Name)
113+
return nil, util.NewInvalidInputError("Error extracting pipeline from the tarball file. Expecting a pipeline.yaml file inside the tarball. Got: %v", header.Name)
85114
}
86115
decompressedFile, err := ioutil.ReadAll(tarReader)
87116
if err != nil {
@@ -98,10 +127,21 @@ func DecompressPipelineZip(compressedFile []byte) ([]byte, error) {
98127
if len(reader.File) < 1 {
99128
return nil, util.NewInvalidInputErrorWithDetails(err, "Error extracting pipeline from the zip file. Empty zip file.")
100129
}
101-
if !isYamlFile(reader.File[0].Name) {
102-
return nil, util.NewInvalidInputError("Error extracting pipeline from the zip file. Expecting a YAML file inside the zip. Got: %v", reader.File[0].Name)
130+
131+
// Old behavior - taking the first file in the archive
132+
pipelineYamlFile := reader.File[0]
133+
// New behavior: searching for the "pipeline.yaml" file.
134+
for _, file := range reader.File {
135+
if isPipelineYamlFile(file.Name) {
136+
pipelineYamlFile = file
137+
break
138+
}
139+
}
140+
141+
if !isYamlFile(pipelineYamlFile.Name) {
142+
return nil, util.NewInvalidInputError("Error extracting pipeline from the zip file. Expecting a pipeline.yaml file inside the zip. Got: %v", pipelineYamlFile.Name)
103143
}
104-
rc, err := reader.File[0].Open()
144+
rc, err := pipelineYamlFile.Open()
105145
if err != nil {
106146
return nil, util.NewInvalidInputErrorWithDetails(err, "Error extracting pipeline from the zip file. Failed to read the content.")
107147
}

backend/src/apiserver/server/util_test.go

+18
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ func TestReadPipelineFile_Zip_AnyExtension(t *testing.T) {
148148
assert.Equal(t, expectedPipelineFile, pipelineFile)
149149
}
150150

151+
func TestReadPipelineFile_MultifileZip(t *testing.T) {
152+
file, _ := os.Open("test/pipeline_plus_component/pipeline_plus_component.zip")
153+
pipelineFile, err := ReadPipelineFile("pipeline_plus_component.ai-hub-package", file, MaxFileLength)
154+
assert.Nil(t, err)
155+
156+
expectedPipelineFile, _ := ioutil.ReadFile("test/pipeline_plus_component/pipeline.yaml")
157+
assert.Equal(t, expectedPipelineFile, pipelineFile)
158+
}
159+
151160
func TestReadPipelineFile_Tarball(t *testing.T) {
152161
file, _ := os.Open("test/arguments_tarball/arguments.tar.gz")
153162
pipelineFile, err := ReadPipelineFile("arguments.tar.gz", file, MaxFileLength)
@@ -166,6 +175,15 @@ func TestReadPipelineFile_Tarball_AnyExtension(t *testing.T) {
166175
assert.Equal(t, expectedPipelineFile, pipelineFile)
167176
}
168177

178+
func TestReadPipelineFile_MultifileTarball(t *testing.T) {
179+
file, _ := os.Open("test/pipeline_plus_component/pipeline_plus_component.tar.gz")
180+
pipelineFile, err := ReadPipelineFile("pipeline_plus_component.ai-hub-package", file, MaxFileLength)
181+
assert.Nil(t, err)
182+
183+
expectedPipelineFile, _ := ioutil.ReadFile("test/pipeline_plus_component/pipeline.yaml")
184+
assert.Equal(t, expectedPipelineFile, pipelineFile)
185+
}
186+
169187
func TestReadPipelineFile_UnknownFileFormat(t *testing.T) {
170188
file, _ := os.Open("test/unknown_format.foo")
171189
_, err := ReadPipelineFile("unknown_format.foo", file, MaxFileLength)

backend/test/integration/pipeline_api_test.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -80,17 +80,17 @@ func (s *PipelineApiTest) TestPipelineAPI() {
8080
/* ---------- Upload pipelines zip ---------- */
8181
time.Sleep(1 * time.Second)
8282
argumentUploadPipeline, err := s.pipelineUploadClient.UploadFile(
83-
"../resources/zip-arguments.zip", &uploadParams.UploadPipelineParams{Name: util.StringPointer("zip-arguments-parameters")})
83+
"../resources/arguments.pipeline.zip", &uploadParams.UploadPipelineParams{Name: util.StringPointer("zip-arguments-parameters")})
8484
assert.Nil(t, err)
8585
assert.Equal(t, "zip-arguments-parameters", argumentUploadPipeline.Name)
8686

8787
/* ---------- Import pipeline tarball by URL ---------- */
8888
time.Sleep(1 * time.Second)
8989
argumentUrlPipeline, err := s.pipelineClient.Create(&params.CreatePipelineParams{
9090
Body: &pipeline_model.APIPipeline{URL: &pipeline_model.APIURL{
91-
PipelineURL: "https://storage.googleapis.com/ml-pipeline-dataset/arguments.zip"}}})
91+
PipelineURL: "https://storage.googleapis.com/ml-pipeline-dataset/arguments.pipeline.zip"}}})
9292
assert.Nil(t, err)
93-
assert.Equal(t, "arguments.zip", argumentUrlPipeline.Name)
93+
assert.Equal(t, "arguments.pipeline.zip", argumentUrlPipeline.Name)
9494

9595
/* ---------- Verify list pipeline works ---------- */
9696
pipelines, totalSize, _, err := s.pipelineClient.List(params.NewListPipelinesParams())
@@ -111,7 +111,7 @@ func (s *PipelineApiTest) TestPipelineAPI() {
111111
assert.Equal(t, 2, len(listFirstPagePipelines))
112112
assert.Equal(t, 4, totalSize)
113113
assert.Equal(t, "arguments-parameters.yaml", listFirstPagePipelines[0].Name)
114-
assert.Equal(t, "arguments.zip", listFirstPagePipelines[1].Name)
114+
assert.Equal(t, "arguments.pipeline.zip", listFirstPagePipelines[1].Name)
115115
assert.NotEmpty(t, nextPageToken)
116116

117117
listSecondPagePipelines, totalSize, nextPageToken, err := s.pipelineClient.List(
@@ -139,7 +139,7 @@ func (s *PipelineApiTest) TestPipelineAPI() {
139139
assert.Equal(t, 2, len(listSecondPagePipelines))
140140
assert.Equal(t, 4, totalSize)
141141
assert.Equal(t, "zip-arguments-parameters", listSecondPagePipelines[0].Name)
142-
assert.Equal(t, "arguments.zip", listSecondPagePipelines[1].Name)
142+
assert.Equal(t, "arguments.pipeline.zip", listSecondPagePipelines[1].Name)
143143
assert.Empty(t, nextPageToken)
144144

145145
/* ---------- List pipelines sort by unsupported description field. Should fail. ---------- */
@@ -162,7 +162,7 @@ func (s *PipelineApiTest) TestPipelineAPI() {
162162
assert.Nil(t, err)
163163
assert.Equal(t, 2, len(listSecondPagePipelines))
164164
assert.Equal(t, 4, totalSize)
165-
assert.Equal(t, "arguments.zip", listSecondPagePipelines[0].Name)
165+
assert.Equal(t, "arguments.pipeline.zip", listSecondPagePipelines[0].Name)
166166
assert.Equal(t, "arguments-parameters.yaml", listSecondPagePipelines[1].Name)
167167
assert.Empty(t, nextPageToken)
168168

767 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)