-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from muxiyun/dev-andrew
Dev andrew
- Loading branch information
Showing
71 changed files
with
5,899 additions
and
1,586 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Binaries for programs and plugins | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
|
||
# Test binary, build with `go test -c` | ||
*.test | ||
|
||
# Output of the go coverage tool, specifically when used with LiteIDE | ||
*.out. | ||
.idea/ | ||
.vscode/ | ||
Mae | ||
MAE | ||
log/ | ||
conf/admin.kubeconfig |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,25 @@ | ||
# MAE:Muxi APP Engine | ||
# [muxi application engine(Mae)](https://github.com/muxiyun/Mae/tree/master) | ||
|
||
[![Build Status](https://travis-ci.org/Andrewpqc/MAE.svg?branch=master)](https://travis-ci.org/Andrewpqc/MAE) | ||
PaaS of Muxi-Studio. An easier way to manage Kubernetes cluser. | ||
|
||
An easier way to manipulate Kubernetes cluser. | ||
Click [http://zxc0328.github.io/2017/05/27/mae/](http://zxc0328.github.io/2017/05/27/mae/) to view details. | ||
|
||
The PaaS of Muxi-Studio, Server Part of [Project MAE](http://zxc0328.github.io/2017/05/27/mae/) | ||
|
||
TODO: | ||
- [x] API Design | ||
- [x] Domain UML & Db UML | ||
Code Part: <br> | ||
- [ ] Models | ||
- [ ] 用户系统 | ||
- [ ] 接入Casbin | ||
- [ ] 应用部分 | ||
- [ ] 服务部分 | ||
- [ ] 版本部分 | ||
- [ ] 查看log | ||
- [ ] Nginx反向代理部分 | ||
- [x] api design | ||
- [x] domain UML & database UML | ||
- [x] user system | ||
- [x] casbin access control | ||
- [x] application (abstract entity) | ||
- [x] service (abstract entity) | ||
- [x] version (abstract entity) | ||
- [x] log query | ||
- [x] web terminal | ||
- [x] email notification for admin | ||
NEXT: | ||
|
||
1.现在版本的切换采取的是删除原版本的资源之后创建新版本的资源,后面改为灰度发布 | ||
|
||
2.优化int类型的使用,重构部分代码 | ||
|
||
3.文档 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,227 @@ | ||
//app ,应用增删改查测试文件 | ||
package main | ||
|
||
import ( | ||
"github.com/kataras/iris/httptest" | ||
"github.com/muxiyun/Mae/model" | ||
"testing" | ||
"time" | ||
) | ||
|
||
func TestAppCRUD(t *testing.T) { | ||
e := httptest.New(t, newApp(), httptest.URL("http://127.0.0.1:8080")) | ||
defer model.DB.RWdb.DropTableIfExists("users") | ||
defer model.DB.RWdb.DropTableIfExists("casbin_rule") | ||
defer model.DB.RWdb.DropTableIfExists("apps") | ||
defer model.DB.RWdb.DropTableIfExists("versions") | ||
defer model.DB.RWdb.DropTableIfExists("services") | ||
|
||
CreateUserForTest(e, "andrew", "andrew123", "andrewpqc@mails.ccnu.edu.cn") | ||
CreateAdminForTest(e, "andrewadmin", "andrewadmin123", "3480437308@qq.com") | ||
andrew_token := GetTokenForTest(e, "andrew", "andrew123", 60*60) | ||
andrewadmin_token := GetTokenForTest(e, "andrewadmin", "andrewadmin123", 60*60) | ||
|
||
// Anonymous to create an app | ||
e.POST("/api/v1.0/app").WithJSON(map[string]interface{}{ | ||
"app_name": "学而", | ||
"app_desc": "华师课程挖掘机", | ||
}).Expect().Status(httptest.StatusForbidden) | ||
|
||
//a normal user to create an app | ||
e.POST("/api/v1.0/app").WithJSON(map[string]interface{}{ | ||
"app_name": "学而", | ||
"app_desc": "华师课程挖掘机", | ||
}).WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
//an admin to create an app | ||
e.POST("/api/v1.0/app").WithJSON(map[string]interface{}{ | ||
"app_name": "华师匣子", | ||
"app_desc": "华师校园助手", | ||
}).WithBasicAuth(andrewadmin_token, "").Expect().Body().Contains("OK") | ||
|
||
//Anonymous to get an app | ||
e.GET("/api/v1.0/app/{appname}").WithPath("appname", "学而").Expect().Status(httptest.StatusForbidden) | ||
|
||
//a normal user to get an app | ||
e.GET("/api/v1.0/app/{appname}").WithPath("appname", "学而").WithBasicAuth(andrew_token, ""). | ||
Expect().Body().Contains("OK") | ||
|
||
// an admin user to get an app | ||
e.GET("/api/v1.0/app/{appname}").WithPath("appname", "学而").WithBasicAuth(andrewadmin_token, ""). | ||
Expect().Body().Contains("OK") | ||
|
||
// Anonymous to update a app | ||
e.PUT("/api/v1.0/app/{id}").WithPath("id", 1).WithJSON(map[string]interface{}{ | ||
"app_name": "xueer", | ||
}).Expect().Status(httptest.StatusForbidden) | ||
|
||
//a normal user to update an app | ||
e.PUT("/api/v1.0/app/{id}").WithPath("id", 1).WithJSON(map[string]interface{}{ | ||
"app_name": "Xueer", | ||
"app_desc": "华师课程挖掘机鸡鸡鸡鸡", | ||
}).WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
//an admin user to update an app | ||
e.PUT("/api/v1.0/app/{id}").WithPath("id", 1).WithJSON(map[string]interface{}{ | ||
"app_name": "xueer", | ||
"app_desc": "山东蓝想挖掘机学学校", | ||
}).WithBasicAuth(andrewadmin_token, "").Expect().Body().Contains("OK") | ||
|
||
//anonymous to list apps | ||
e.GET("/api/v1.0/app").Expect().Status(httptest.StatusForbidden) | ||
|
||
//a normal user to list apps | ||
e.GET("/api/v1.0/app").WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
// an admin user to list apps | ||
e.GET("/api/v1.0/app").WithBasicAuth(andrewadmin_token, "").Expect().Body().Contains("OK") | ||
|
||
// anonymous to delete an app | ||
e.DELETE("/api/v1.0/app/{id}").WithPath("id", 1).Expect().Status(httptest.StatusForbidden) | ||
|
||
//a normal user to delete an app | ||
e.DELETE("/api/v1.0/app/{id}").WithPath("id", 1).WithBasicAuth(andrew_token, ""). | ||
Expect().Status(httptest.StatusForbidden) | ||
|
||
//an admin user to delete an app | ||
e.DELETE("/api/v1.0/app/{id}").WithPath("id", 1).WithBasicAuth(andrewadmin_token, ""). | ||
Expect().Body().Contains("OK") | ||
|
||
// anonymous test app_name duplicate checker | ||
e.GET("/api/v1.0/app/duplicate").WithQuery("appname", "华师匣子"). | ||
Expect().Status(httptest.StatusForbidden) | ||
|
||
// a normal user to test app_name duplicate checker | ||
e.GET("/api/v1.0/app/duplicate").WithQuery("appname", "华师匣子"). | ||
WithBasicAuth(andrew_token, "").Expect().Body().NotContains("record not found") | ||
|
||
// an admin user to test app_name duplicate checker | ||
e.GET("/api/v1.0/app/duplicate").WithQuery("appname", "木小犀机器人"). | ||
WithBasicAuth(andrewadmin_token, "").Expect().Body().Contains("record not found") | ||
} | ||
|
||
|
||
|
||
func TestRecursiveDeleteApp(t *testing.T){ | ||
time.Sleep(5*time.Second) | ||
e := httptest.New(t, newApp(), httptest.URL("http://127.0.0.1:8080")) | ||
defer model.DB.RWdb.DropTableIfExists("users") | ||
defer model.DB.RWdb.DropTableIfExists("casbin_rule") | ||
defer model.DB.RWdb.DropTableIfExists("apps") | ||
defer model.DB.RWdb.DropTableIfExists("versions") | ||
defer model.DB.RWdb.DropTableIfExists("services") | ||
|
||
CreateUserForTest(e, "andrew", "andrew123", "andrewpqc@mails.ccnu.edu.cn") | ||
CreateAdminForTest(e, "andrewadmin", "andrewadmin123", "3480437308@qq.com") | ||
andrew_token := GetTokenForTest(e, "andrew", "andrew123", 60*60) | ||
andrewadmin_token := GetTokenForTest(e, "andrewadmin", "andrewadmin123", 60*60) | ||
|
||
//a normal user to create an app | ||
e.POST("/api/v1.0/app").WithJSON(map[string]interface{}{ | ||
"app_name": "学而1", | ||
"app_desc": "华师课程挖掘机", | ||
}).WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
// delete an app which has no service | ||
e.DELETE("/api/v1.0/app/{id}").WithPath("id", 1).WithBasicAuth(andrewadmin_token, ""). | ||
Expect().Body().Contains("OK") | ||
|
||
time.Sleep(3*time.Second) | ||
|
||
//a normal user to create an app | ||
e.POST("/api/v1.0/app").WithJSON(map[string]interface{}{ | ||
"app_name": "学而2", | ||
"app_desc": "华师课程挖掘机", | ||
}).WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
// a normal user to create a service | ||
e.POST("/api/v1.0/service").WithJSON(map[string]interface{}{ | ||
"app_id": 2, | ||
"svc_name": "xueer_be2", | ||
"svc_desc": "the backend part of xueer", | ||
}).WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
// an admin to create a service | ||
e.POST("/api/v1.0/service").WithJSON(map[string]interface{}{ | ||
"app_id": 2, | ||
"svc_name": "xueer_fe2", | ||
"svc_desc": "frontend part of xueer", | ||
}).WithBasicAuth(andrewadmin_token, "").Expect().Body().Contains("OK") | ||
|
||
// delete an app which has two services, but there are no versions of each service | ||
e.DELETE("/api/v1.0/app/{id}").WithPath("id", 2).WithBasicAuth(andrewadmin_token, ""). | ||
Expect().Body().Contains("OK") | ||
|
||
time.Sleep(3*time.Second) | ||
|
||
//a normal user to create an app | ||
e.POST("/api/v1.0/app").WithJSON(map[string]interface{}{ | ||
"app_name": "学而3", | ||
"app_desc": "华师课程挖掘机", | ||
}).WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
// a normal user to create a service | ||
e.POST("/api/v1.0/service").WithJSON(map[string]interface{}{ | ||
"app_id": 3, | ||
"svc_name": "xueer_be3", | ||
"svc_desc": "the backend part of xueer", | ||
}).WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
// an admin to create a service | ||
e.POST("/api/v1.0/service").WithJSON(map[string]interface{}{ | ||
"app_id": 3, | ||
"svc_name": "xueer_fe3", | ||
"svc_desc": "frontend part of xueer", | ||
}).WithBasicAuth(andrewadmin_token, "").Expect().Body().Contains("OK") | ||
|
||
// create a namespace mae-test-g | ||
e.POST("/api/v1.0/ns/{ns}").WithPath("ns", "mae-test-g"). | ||
WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
//create a version which belongs to service xueer_be | ||
e.POST("/api/v1.0/version").WithJSON(map[string]interface{}{ | ||
"svc_id": 3, | ||
"version_name": "xueer-be-v1", | ||
"version_desc": "xueer be version 1", | ||
"version_conf": map[string]interface{}{ | ||
"deployment": map[string]interface{}{ | ||
"deploy_name": "xueer-be-v1-deployment", | ||
"name_space": "mae-test-g", | ||
"replicas": 1, | ||
"labels": map[string]string{"run": "xueer-be"}, | ||
"containers": [](map[string]interface{}){ | ||
map[string]interface{}{ | ||
"ctr_name": "xueer-be-v1-ct", | ||
"image_url": "pqcsdockerhub/kube-test", | ||
"start_cmd": []string{"gunicorn", "app:app", "-b", "0.0.0.0:8080", "--log-level", "DEBUG"}, | ||
"ports": [](map[string]interface{}){ | ||
map[string]interface{}{ | ||
"image_port": 8080, | ||
"target_port": 8090, | ||
"protocol": "TCP", | ||
}, | ||
}, | ||
}, | ||
}, | ||
}, | ||
"svc": map[string]interface{}{ | ||
"svc_name": "xueer-be-v1-service", | ||
"selector": map[string]string{"run": "xueer-be"}, | ||
"labels": map[string]string{"run": "xueer-be"}, | ||
}, | ||
}, | ||
}).WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
//apply version "xueer-be-v1" | ||
e.GET("/api/v1.0/version/apply").WithQuery("version_name", "xueer-be-v1"). | ||
WithBasicAuth(andrew_token, "").Expect().Body().Contains("OK") | ||
|
||
time.Sleep(3*time.Second) | ||
|
||
// to recursive delete the app and the service of the app and the versions of the service. | ||
e.DELETE("/api/v1.0/app/{id}").WithPath("id", 3).WithBasicAuth(andrewadmin_token, ""). | ||
Expect().Body().Contains("OK") | ||
|
||
e.DELETE("/api/v1.0/ns/{ns}").WithPath("ns", "mae-test-g").WithBasicAuth(andrewadmin_token, ""). | ||
Expect().Body().Contains("OK") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
[request_definition] | ||
r = sub, dom, obj, act | ||
|
||
[policy_definition] | ||
p = sub, dom, obj, act | ||
|
||
[role_definition] | ||
g = _, _, _ | ||
|
||
[policy_effect] | ||
e = some(where (p.eft == allow)) | ||
|
||
[matchers] | ||
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && regexMatch(r.obj,p.obj) && r.act == p.act |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
runmode: debug # 开发模式, debug, release, test | ||
addr: :8080 # HTTP绑定端口 | ||
name: mae_apiserver # API Server的名字 | ||
url: http://127.0.0.1:8080 # pingServer函数请求的API服务器的ip:port | ||
max_ping_count: 10 # pingServer函数try的次数 | ||
jwt_secret: Rtg8BPKNEf2mB4mgvKONGPZZQSaJWNLijxR42qRgq0iBb5 | ||
casbinmodel: conf/casbinmodel.conf | ||
kubeconfig: conf/admin.kubeconfig | ||
tls: | ||
addr: :8081 | ||
cert: conf/example.com+4.pem | ||
key: conf/example.com+4-key.pem | ||
log: | ||
writers: file | ||
logger_level: DEBUG | ||
logger_file: log/mae.log | ||
log_format_text: true | ||
rollingPolicy: size | ||
log_rotate_date: 1 | ||
log_rotate_size: 1 | ||
log_backup_count: 7 | ||
db: | ||
name: mae | ||
addr: 127.0.0.1:3306 | ||
username: root | ||
password: pqc19960320 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
-----BEGIN PRIVATE KEY----- | ||
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDRwGEphjEL6gOy | ||
EbLZecjc0ieXl1cIAYcesPfcD/YTlj2ObU2ATyCifr6p3UFcR+DYdhTo8jL1ujbe | ||
Q+qDtL5ZN2OtmuKJsGQj24szd3Ld0uMBzUYzFqEJ6z5jMKk49ctMo1TYgkMnc6Y/ | ||
YFGwY5XTVjc+A0TK98OYAH5HHKFNpLIXiSWOYaNmlz36QVXXVw3xVwkfSMskCpAf | ||
cgzLR9MH5KcYpZvUjSsIFFAsk6qgV/nseNWz0Y3FirOgMKs3rT+Y9UesvQZRUE/P | ||
7+X0vC4bil+e1uQQreK53sqvHqLAvGBW18B/Hyr5wxGQUCg3QNhq6Bq1/6uph1sp | ||
kz1fxKQ3AgMBAAECggEALPAzoOrgLTZI7mi+Ubu23iCkXOUOv2dcZKXzpJFC3nVs | ||
4MvoM9pAGrBe9xOxQi0gLiA2YKYrZtwrjzkr0GXz9jdYwsQRTwCco9YQn8kysfXR | ||
rvwk0yNBA1gEOMofJ1X55YSE1BIsgxJTBvcC6XCck/e/xCh9H6Mvo6xPYbrvkCua | ||
oOdXIo7Qk5QrsF9XUUBVCsjJCasiYp58zGn3hAQMJDKd/vjhJlBkJiZjHcDOcBcP | ||
AWRsIym03toTYAkQ6icMvn1PlWlbujlWmE5DL5rQsemfwwlE9j+9Atp7bBZhcbep | ||
Zg66Ik7/kte4Afq3/e+cnEj0ddxwrGVnGOzD5mD2eQKBgQDepfq8o6v1Z4+T9Bre | ||
JJmQop7iOIPyKCxLxXhtN3IT92KXITFqn98st+5YYJSHFhxUuew/2dYwb1xTo+ZC | ||
GTKuBXqRNbiEE2o++wuuEhbeu0CJMio8UxGE9Y8ODhMIq/8asGTM6z4MHQ5Y8v4W | ||
fjFfoq/v0SlyE42Sn5O5WxML3QKBgQDxK9YilBIUIGGnbNWKOsvQkodK5uliWcRZ | ||
7A6E1LtTKUDzg3GjMNKhxjFbucQGssXKM2qgiw6ZXZDz9P1cm5JFxkYJyqsmTccg | ||
+UR+hQ8pVIp+zmGAbB4oTIQhqYbluaFpNVVbX6Qwtueu5vdF1k/zFh2k6G4ufD+f | ||
U/punGhJIwKBgQDYFbSsohjBOroxOOdek5zqr7mOCpWcTvr2qvc+4GH6GM15qcBh | ||
IDokF3reERX1qTLj0/IC4jMrnNi5YEeX/QafuDeFeOLUZFdoOpPSZEIH9yoiPSqa | ||
k3BcX0pwtJ4qe2tCBtI9w03bydNj5qlNQTo//A/Oq2wTCAENvYxMh6SLjQKBgQCA | ||
Oht/hRTbqJ/jYeVjuoE1Y0MV2xJJnYrdeLn7fBQhUjTbhI6+Aq5rHzKNH4cPPKwX | ||
JyFRPL5FYs84NpEjVP//oz0H5b77/aybZo05a8u04ONGKrsCifm62XwDXdyAdiNR | ||
Ce9ZRs/IquciQmFEu38Es0SNspsqkhtNvlvPxc9Y2wKBgDKy67pIxKQ1iDFO4448 | ||
WyHcbyR9+VWjAYPq6Cmzz4Qt9LpKbL3TuziYiiM15xS9/aGBjsNAg0rzJfZoxGgF | ||
wcJaQSitwsGUtzWw6HIrjGYttiryRp0dxgKmUxIWTVnaOJB/LOqcayXrPsnOK0Gn | ||
oHqmphc5ABcDLxhwPdLkRupL | ||
-----END PRIVATE KEY----- |
Oops, something went wrong.