Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
凌波微步_大先生
dashboard
提交
4a09c269
D
dashboard
项目概览
凌波微步_大先生
/
dashboard
与 Fork 源项目一致
从无法访问的项目Fork
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
dashboard
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4a09c269
编写于
2月 18, 2016
作者:
U
urcan
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
issue 385 solved
上级
a58945db
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
120 addition
and
29 deletion
+120
-29
src/app/backend/apihandler.go
src/app/backend/apihandler.go
+14
-3
src/app/backend/deploy.go
src/app/backend/deploy.go
+28
-12
src/app/frontend/deploy/deployfromfile_controller.js
src/app/frontend/deploy/deployfromfile_controller.js
+6
-3
src/test/backend/deploy_test.go
src/test/backend/deploy_test.go
+14
-10
src/test/frontend/deploy/deployfromfile_controller_test.js
src/test/frontend/deploy/deployfromfile_controller_test.js
+58
-1
未找到文件。
src/app/backend/apihandler.go
浏览文件 @
4a09c269
...
@@ -93,7 +93,7 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient)
...
@@ -93,7 +93,7 @@ func CreateHttpApiHandler(client *client.Client, heapsterClient HeapsterClient)
deployFromFileWs
.
POST
(
""
)
.
deployFromFileWs
.
POST
(
""
)
.
To
(
apiHandler
.
handleDeployFromFile
)
.
To
(
apiHandler
.
handleDeployFromFile
)
.
Reads
(
AppDeploymentFromFileSpec
{})
.
Reads
(
AppDeploymentFromFileSpec
{})
.
Writes
(
AppDeploymentFromFile
Spec
{}))
Writes
(
AppDeploymentFromFile
Response
{}))
wsContainer
.
Add
(
deployFromFileWs
)
wsContainer
.
Add
(
deployFromFileWs
)
replicationControllerWs
:=
new
(
restful
.
WebService
)
replicationControllerWs
:=
new
(
restful
.
WebService
)
...
@@ -205,12 +205,23 @@ func (apiHandler *ApiHandler) handleDeployFromFile(request *restful.Request, res
...
@@ -205,12 +205,23 @@ func (apiHandler *ApiHandler) handleDeployFromFile(request *restful.Request, res
handleInternalError
(
response
,
err
)
handleInternalError
(
response
,
err
)
return
return
}
}
if
err
:=
DeployAppFromFile
(
deploymentSpec
,
CreateObjectFromInfoFn
);
err
!=
nil
{
isDeployed
,
err
:=
DeployAppFromFile
(
deploymentSpec
,
CreateObjectFromInfoFn
)
if
!
isDeployed
{
handleInternalError
(
response
,
err
)
handleInternalError
(
response
,
err
)
return
return
}
}
response
.
WriteHeaderAndEntity
(
http
.
StatusCreated
,
deploymentSpec
)
errorMessage
:=
""
if
err
!=
nil
{
errorMessage
=
err
.
Error
()
}
response
.
WriteHeaderAndEntity
(
http
.
StatusCreated
,
AppDeploymentFromFileResponse
{
Name
:
deploymentSpec
.
Name
,
Content
:
deploymentSpec
.
Content
,
Error
:
errorMessage
,
})
}
}
// Handles app name validation API call.
// Handles app name validation API call.
...
...
src/app/backend/deploy.go
浏览文件 @
4a09c269
...
@@ -90,6 +90,18 @@ type AppDeploymentFromFileSpec struct {
...
@@ -90,6 +90,18 @@ type AppDeploymentFromFileSpec struct {
Content
string
`json:"content"`
Content
string
`json:"content"`
}
}
// Specification for deployment from file
type
AppDeploymentFromFileResponse
struct
{
// Name of the file
Name
string
`json:"name"`
// File content
Content
string
`json:"content"`
// Error after create resource
Error
string
`json:"error"`
}
// Port mapping for an application deployment.
// Port mapping for an application deployment.
type
PortMapping
struct
{
type
PortMapping
struct
{
// Port that will be exposed on the service.
// Port that will be exposed on the service.
...
@@ -264,16 +276,16 @@ func getLabelsMap(labels []Label) map[string]string {
...
@@ -264,16 +276,16 @@ func getLabelsMap(labels []Label) map[string]string {
return
result
return
result
}
}
type
createObjectFromInfo
func
(
info
*
kubectlResource
.
Info
)
error
type
createObjectFromInfo
func
(
info
*
kubectlResource
.
Info
)
(
bool
,
error
)
// Implementation of createObjectFromInfo
// Implementation of createObjectFromInfo
func
CreateObjectFromInfoFn
(
info
*
kubectlResource
.
Info
)
error
{
func
CreateObjectFromInfoFn
(
info
*
kubectlResource
.
Info
)
(
bool
,
error
)
{
_
,
err
:=
kubectlResource
.
NewHelper
(
info
.
Client
,
info
.
Mapping
)
.
Create
(
info
.
Namespace
,
true
,
info
.
Object
)
createdResource
,
err
:=
kubectlResource
.
NewHelper
(
info
.
Client
,
info
.
Mapping
)
.
Create
(
info
.
Namespace
,
true
,
info
.
Object
)
return
err
return
createdResource
!=
nil
,
err
}
}
// Deploys an app based on the given yaml or json file.
// Deploys an app based on the given yaml or json file.
func
DeployAppFromFile
(
spec
*
AppDeploymentFromFileSpec
,
createObjectFromInfoFn
createObjectFromInfo
)
error
{
func
DeployAppFromFile
(
spec
*
AppDeploymentFromFileSpec
,
createObjectFromInfoFn
createObjectFromInfo
)
(
bool
,
error
)
{
const
(
const
(
validate
=
true
validate
=
true
emptyCacheDir
=
""
emptyCacheDir
=
""
...
@@ -282,7 +294,7 @@ func DeployAppFromFile(spec *AppDeploymentFromFileSpec, createObjectFromInfoFn c
...
@@ -282,7 +294,7 @@ func DeployAppFromFile(spec *AppDeploymentFromFileSpec, createObjectFromInfoFn c
factory
:=
cmdutil
.
NewFactory
(
nil
)
factory
:=
cmdutil
.
NewFactory
(
nil
)
schema
,
err
:=
factory
.
Validator
(
validate
,
emptyCacheDir
)
schema
,
err
:=
factory
.
Validator
(
validate
,
emptyCacheDir
)
if
err
!=
nil
{
if
err
!=
nil
{
return
err
return
false
,
err
}
}
mapper
,
typer
:=
factory
.
Object
()
mapper
,
typer
:=
factory
.
Object
()
...
@@ -295,12 +307,16 @@ func DeployAppFromFile(spec *AppDeploymentFromFileSpec, createObjectFromInfoFn c
...
@@ -295,12 +307,16 @@ func DeployAppFromFile(spec *AppDeploymentFromFileSpec, createObjectFromInfoFn c
Flatten
()
.
Flatten
()
.
Do
()
Do
()
return
r
.
Visit
(
func
(
info
*
kubectlResource
.
Info
,
err
error
)
error
{
deployedResourcesCount
:=
0
err
=
createObjectFromInfoFn
(
info
)
if
err
!=
nil
{
err
=
r
.
Visit
(
func
(
info
*
kubectlResource
.
Info
,
err
error
)
error
{
return
err
isDeployed
,
err
:=
createObjectFromInfoFn
(
info
)
if
isDeployed
{
deployedResourcesCount
++
log
.
Printf
(
"%s is deployed"
,
info
.
Name
)
}
}
log
.
Printf
(
"%s is deployed"
,
info
.
Name
)
return
err
return
nil
})
})
return
deployedResourcesCount
>
0
,
err
}
}
src/app/frontend/deploy/deployfromfile_controller.js
浏览文件 @
4a09c269
...
@@ -84,9 +84,12 @@ export default class DeployFromFileController {
...
@@ -84,9 +84,12 @@ export default class DeployFromFileController {
let
resource
=
this
.
resource_
(
'
api/v1/appdeploymentfromfile
'
);
let
resource
=
this
.
resource_
(
'
api/v1/appdeploymentfromfile
'
);
resource
.
save
(
resource
.
save
(
deploymentSpec
,
deploymentSpec
,
(
savedConfig
)
=>
{
(
response
)
=>
{
defer
.
resolve
(
savedConfig
);
// Progress ends
defer
.
resolve
(
response
);
// Progress ends
this
.
log_
.
info
(
'
Successfully deployed application:
'
,
savedConfig
);
this
.
log_
.
info
(
'
Deployment is completed:
'
,
response
);
if
(
response
.
error
.
length
>
0
)
{
this
.
errorDialog_
.
open
(
'
Deployment has been partly completed
'
,
response
.
error
);
}
this
.
state_
.
go
(
replicationcontrollerliststate
);
this
.
state_
.
go
(
replicationcontrollerliststate
);
},
},
(
err
)
=>
{
(
err
)
=>
{
...
...
src/test/backend/deploy_test.go
浏览文件 @
4a09c269
...
@@ -182,23 +182,23 @@ func TestGetAvailableProtocols(t *testing.T) {
...
@@ -182,23 +182,23 @@ func TestGetAvailableProtocols(t *testing.T) {
}
}
func
TestDeployAppFromFileWithValidContent
(
t
*
testing
.
T
)
{
func
TestDeployAppFromFileWithValidContent
(
t
*
testing
.
T
)
{
const
(
testNamespace
=
"test-deployfile-namespace"
)
validContent
:=
"{
\"
kind
\"
:
\"
Namespace
\"
,"
+
validContent
:=
"{
\"
kind
\"
:
\"
Namespace
\"
,"
+
"
\"
apiVersion
\"
:
\"
v1
\"
,"
+
"
\"
apiVersion
\"
:
\"
v1
\"
,"
+
"
\"
metadata
\"
: {"
+
"
\"
metadata
\"
: {"
+
"
\"
name
\"
:
\"
"
+
testNamespace
+
"
\"
,"
+
"
\"
name
\"
:
\"
test-deployfile-namespace
\"
,"
+
"
\"
labels
\"
: {
\"
name
\"
:
\"
development
\"
}}}"
"
\"
labels
\"
: {
\"
name
\"
:
\"
development
\"
}}}"
spec
:=
&
AppDeploymentFromFileSpec
{
spec
:=
&
AppDeploymentFromFileSpec
{
Name
:
"foo-name"
,
Name
:
"foo-name"
,
Content
:
validContent
,
Content
:
validContent
,
}
}
fakeCreateObjectFromInfo
:=
func
(
info
*
kubectlResource
.
Info
)
error
{
return
nil
}
fakeCreateObjectFromInfo
:=
func
(
info
*
kubectlResource
.
Info
)
(
bool
,
error
)
{
return
true
,
nil
}
err
:=
DeployAppFromFile
(
spec
,
fakeCreateObjectFromInfo
)
isDeployed
,
err
:=
DeployAppFromFile
(
spec
,
fakeCreateObjectFromInfo
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Errorf
(
"Expected return value to be %#v but got %#v"
,
nil
,
err
)
t
.
Errorf
(
"Expected return value to have %#v but got %#v"
,
nil
,
err
)
}
if
!
isDeployed
{
t
.
Errorf
(
"Expected return value to have %#v but got %#v"
,
true
,
isDeployed
)
}
}
}
}
...
@@ -207,10 +207,14 @@ func TestDeployAppFromFileWithInvalidContent(t *testing.T) {
...
@@ -207,10 +207,14 @@ func TestDeployAppFromFileWithInvalidContent(t *testing.T) {
Name
:
"foo-name"
,
Name
:
"foo-name"
,
Content
:
"foo-content-invalid"
,
Content
:
"foo-content-invalid"
,
}
}
fakeCreateObjectFromInfo
:=
func
(
info
*
kubectlResource
.
Info
)
error
{
return
nil
}
// return is set to true to check if the validation prior to this function really works
fakeCreateObjectFromInfo
:=
func
(
info
*
kubectlResource
.
Info
)
(
bool
,
error
)
{
return
true
,
nil
}
err
:=
DeployAppFromFile
(
spec
,
fakeCreateObjectFromInfo
)
isDeployed
,
err
:=
DeployAppFromFile
(
spec
,
fakeCreateObjectFromInfo
)
if
err
==
nil
{
if
err
==
nil
{
t
.
Errorf
(
"Expected return value to be an error but got %#v"
,
nil
)
t
.
Errorf
(
"Expected return value to have an error but got %#v"
,
nil
)
}
if
isDeployed
{
t
.
Errorf
(
"Expected return value to have %#v but got %#v"
,
false
,
isDeployed
)
}
}
}
}
src/test/frontend/deploy/deployfromfile_controller_test.js
浏览文件 @
4a09c269
...
@@ -22,7 +22,6 @@ describe('DeployFromFile controller', () => {
...
@@ -22,7 +22,6 @@ describe('DeployFromFile controller', () => {
let
mockResource
;
let
mockResource
;
/** @type {!angular.FormController} */
/** @type {!angular.FormController} */
let
form
;
let
form
;
beforeEach
(()
=>
{
beforeEach
(()
=>
{
angular
.
mock
.
module
(
deployModule
.
name
);
angular
.
mock
.
module
(
deployModule
.
name
);
...
@@ -52,4 +51,62 @@ describe('DeployFromFile controller', () => {
...
@@ -52,4 +51,62 @@ describe('DeployFromFile controller', () => {
expect
(
resourceObject
.
save
).
toHaveBeenCalled
();
expect
(
resourceObject
.
save
).
toHaveBeenCalled
();
});
});
describe
(
'
After deploy
'
,
()
=>
{
let
httpBackend
;
beforeEach
(()
=>
{
angular
.
mock
.
inject
((
$controller
,
$resource
,
$httpBackend
)
=>
{
ctrl
=
$controller
(
DeployFromFileController
,
{
$resource
:
$resource
},
{
form
:
form
});
httpBackend
=
$httpBackend
;
});
});
it
(
'
should open error dialog and redirect the page
'
,
()
=>
{
spyOn
(
ctrl
.
errorDialog_
,
'
open
'
);
spyOn
(
ctrl
.
state_
,
'
go
'
);
let
response
=
{
name
:
'
foo-name
'
,
content
:
'
foo-content
'
,
error
:
'
service already exists
'
,
};
httpBackend
.
expectPOST
(
'
api/v1/appdeploymentfromfile
'
).
respond
(
201
,
response
);
// when
ctrl
.
deploy
();
httpBackend
.
flush
();
// then
expect
(
ctrl
.
errorDialog_
.
open
).
toHaveBeenCalled
();
expect
(
ctrl
.
state_
.
go
).
toHaveBeenCalled
();
});
it
(
'
should redirect the page and not open error dialog
'
,
()
=>
{
spyOn
(
ctrl
.
errorDialog_
,
'
open
'
);
spyOn
(
ctrl
.
state_
,
'
go
'
);
let
response
=
{
name
:
'
foo-name
'
,
content
:
'
foo-content
'
,
error
:
''
,
};
httpBackend
.
expectPOST
(
'
api/v1/appdeploymentfromfile
'
).
respond
(
201
,
response
);
// when
ctrl
.
deploy
();
httpBackend
.
flush
();
// then
expect
(
ctrl
.
errorDialog_
.
open
).
not
.
toHaveBeenCalled
();
expect
(
ctrl
.
state_
.
go
).
toHaveBeenCalled
();
});
it
(
'
should not redirect the page and but open error dialog
'
,
()
=>
{
spyOn
(
ctrl
.
errorDialog_
,
'
open
'
);
spyOn
(
ctrl
.
state_
,
'
go
'
);
httpBackend
.
expectPOST
(
'
api/v1/appdeploymentfromfile
'
).
respond
(
500
,
"
Deployment failed
"
);
// when
ctrl
.
deploy
();
httpBackend
.
flush
();
// then
expect
(
ctrl
.
errorDialog_
.
open
).
toHaveBeenCalled
();
expect
(
ctrl
.
state_
.
go
).
not
.
toHaveBeenCalled
();
});
});
});
});
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录