Skip to content

Commit 5956298

Browse files
author
urcan
committed
upload file backend is implemented
1 parent 9d11013 commit 5956298

File tree

6 files changed

+122
-43
lines changed

6 files changed

+122
-43
lines changed

src/app/backend/apihandler.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -206,13 +206,12 @@ func (apiHandler *ApiHandler) handleDeployFromFile(request *restful.Request, res
206206
handleInternalError(response, err)
207207
return
208208
}
209-
if err := DeployAppFromFile(deploymentSpec, apiHandler.client); err != nil {
209+
if err := DeployAppFromFile(deploymentSpec); err != nil {
210210
handleInternalError(response, err)
211211
return
212212
}
213213

214214
response.WriteHeaderAndEntity(http.StatusCreated, deploymentSpec)
215-
216215
}
217216

218217
// Handles app name validation API call.

src/app/backend/deploy.go

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,14 @@ package main
1616

1717
import (
1818
"fmt"
19-
ioutil "io/ioutil"
2019
"log"
21-
"os"
2220
"strings"
2321

2422
"k8s.io/kubernetes/pkg/api"
2523
"k8s.io/kubernetes/pkg/api/resource"
26-
create "k8s.io/kubernetes/pkg/kubectl/cmd"
27-
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
2824
client "k8s.io/kubernetes/pkg/client/unversioned"
25+
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
26+
kubectlResource "k8s.io/kubernetes/pkg/kubectl/resource"
2927
"k8s.io/kubernetes/pkg/util/intstr"
3028
)
3129

@@ -246,26 +244,36 @@ func getLabelsMap(labels []Label) map[string]string {
246244
}
247245

248246
// Deploys an app based on the given yaml or json file.
249-
func DeployAppFromFile(spec *AppDeploymentFromFileSpec, client *client.Client) error {
250-
// Creates temp file to use it in kubectl command
251-
file, err := ioutil.TempFile("", spec.Name)
252-
if err != nil {
253-
return err
254-
}
255-
_,err = file.WriteString(spec.Content)
247+
func DeployAppFromFile(spec *AppDeploymentFromFileSpec) error {
248+
const (
249+
validate = true
250+
emptyCacheDir = ""
251+
)
252+
253+
factory := cmdutil.NewFactory(nil)
254+
schema, err := factory.Validator(validate, emptyCacheDir)
256255
if err != nil {
257256
return err
258257
}
259-
// Runs kubectl create command with the temp file
260-
options := &create.CreateOptions{
261-
Filenames: []string {file.Name()},
262-
}
263-
cmd := create.NewCmdCreate(cmdutil.NewFactory(nil), os.Stdout)
264-
cmd.Flags().Set("filename", file.Name())
265-
cmd.Flags().Set("output", "name")
266-
err = create.RunCreate(cmdutil.NewFactory(nil), cmd, os.Stdout, options)
267-
268-
// Removes the created temp file after using it
269-
os.Remove(file.Name())
270-
return err
258+
259+
mapper, typer := factory.Object()
260+
reader := strings.NewReader(spec.Content)
261+
262+
r := kubectlResource.NewBuilder(mapper, typer, factory.ClientMapperForCommand()).
263+
Schema(schema).
264+
NamespaceParam(api.NamespaceDefault).DefaultNamespace().
265+
Stream(reader, spec.Name).
266+
Flatten().
267+
Do()
268+
269+
return r.Visit(func(info *kubectlResource.Info, err error) error {
270+
// creates an object from input info
271+
_, err = kubectlResource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object)
272+
if err != nil {
273+
return err
274+
}
275+
log.Printf("%s is deployed", info.Name)
276+
return nil
277+
})
271278
}
279+

src/app/frontend/common/errorhandling/errordialog_service.js

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,4 @@ export default class ErrorDialog {
4141
alert.ok('Close');
4242
this.mdDialog_.show(alert);
4343
}
44-
45-
/**
46-
* Opens a pop-up window that displays the error message with title
47-
*
48-
* @param {string} title
49-
* @param {string} message
50-
* @export
51-
*/
52-
openWithDetail(title, message) {
53-
let alert = this.mdDialog_.alert();
54-
alert.title(title);
55-
alert.textContent(message);
56-
alert.ok('Close');
57-
this.mdDialog_.show(alert);
58-
}
5944
}

src/app/frontend/deploy/deployfromfile_controller.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ export default class DeployFromFileController {
7676
let defer = this.q_.defer();
7777

7878
/** @type {!angular.Resource<!backendApi.AppDeploymentFromFileSpec>} */
79-
let resource = this.resource_('/api/appdeploymentfromfile');
79+
let resource = this.resource_('api/appdeploymentfromfile');
8080
resource.save(
81-
deploymentSpec,
81+
deploymentSpec,
8282
(savedConfig) => {
8383
defer.resolve(savedConfig); // Progress ends
8484
this.log_.info('Successfully deployed application: ', savedConfig);
@@ -87,7 +87,7 @@ export default class DeployFromFileController {
8787
(err) => {
8888
defer.reject(err); // Progress ends
8989
this.log_.error('Error deploying application:', err);
90-
this.errorDialog_.openWithDetail('File upload failed' ,err.data);
90+
this.errorDialog_.open('Deploying file has failed', err.data);
9191
});
9292
return defer.promise;
9393
}

src/test/backend/deploy_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,35 @@ func TestGetAvailableProtocols(t *testing.T) {
159159
expected, actual)
160160
}
161161
}
162+
163+
func TestDeployAppFromFileWithValidContent(t *testing.T) {
164+
validContent := "{\"kind\": \"Namespace\"," +
165+
"\"apiVersion\": \"v1\"," +
166+
"\"metadata\": {" +
167+
"\"name\": \"development\"," +
168+
"\"labels\": {\"name\": \"development\"}}}"
169+
170+
spec := &AppDeploymentFromFileSpec{
171+
Name: "foo-name",
172+
Content: validContent,
173+
}
174+
175+
err := DeployAppFromFile(spec)
176+
177+
if err != nil {
178+
t.Errorf("Expected return value to be %#v but got %#v", nil, err)
179+
}
180+
}
181+
182+
func TestDeployAppFromFileWithInvalidContent(t *testing.T) {
183+
spec := &AppDeploymentFromFileSpec{
184+
Name: "foo-name",
185+
Content: "foo-content-invalid",
186+
}
187+
188+
err := DeployAppFromFile(spec)
189+
190+
if err == nil {
191+
t.Errorf("Expected return value to be an error but got %#v", nil)
192+
}
193+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// Copyright 2015 Google Inc. All Rights Reserved.
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+
import DeployFromFileController from 'deploy/deployfromfile_controller';
16+
import deployModule from 'deploy/deploy_module';
17+
18+
describe('DeployFromFile controller', () => {
19+
/** @type {!DeployFromFileController} */
20+
let ctrl;
21+
/** @type {!angular.$resource} */
22+
let mockResource;
23+
/** @type {!angular.FormController} */
24+
let form;
25+
26+
beforeEach(() => {
27+
angular.mock.module(deployModule.name);
28+
29+
angular.mock.inject(($controller) => {
30+
mockResource = jasmine.createSpy('$resource');
31+
ctrl = $controller(DeployFromFileController, {$resource: mockResource}, {form: form});
32+
});
33+
});
34+
35+
it('should deploy with file name and content', () => {
36+
// given
37+
let resourceObject = {
38+
save: jasmine.createSpy('save'),
39+
};
40+
ctrl.file.name = "test.yaml";
41+
ctrl.file.content = "test_content";
42+
mockResource.and.returnValue(resourceObject);
43+
resourceObject.save.and.callFake((spec) => {
44+
// then
45+
expect(spec.name).toBe("test.yaml");
46+
expect(spec.content).toBe('test_content');
47+
});
48+
// when
49+
ctrl.deploy();
50+
51+
// then
52+
expect(resourceObject.save).toHaveBeenCalled();
53+
});
54+
55+
});

0 commit comments

Comments
 (0)