Compare commits
24 Commits
bb03307b9e
...
feature/mu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cb2e4f6028 | ||
|
|
35facf1b74 | ||
|
|
24e0137444 | ||
|
|
ba940bfc80 | ||
|
|
063d57d9e7 | ||
|
|
484c742c31 | ||
|
|
cc3b2a6cfc | ||
|
|
8e8d0d3e01 | ||
|
|
03f81c66f9 | ||
|
|
be721059e5 | ||
| e4f0f6f4ca | |||
| cf92b46ce6 | |||
| aa42f5f49c | |||
|
|
98c54eb080 | ||
| afe442d17f | |||
|
|
46b7713404 | ||
| d5ad32e2e4 | |||
|
|
e4ecb8c1db | ||
| cca59faeab | |||
| 2cf8923d95 | |||
| 47ed1b4562 | |||
| 063f47c87b | |||
| 4bfb16cba6 | |||
| b08e6a1e70 |
@@ -1,3 +1,5 @@
|
|||||||
|
ARG KUBERNETES_HOST=${KUBERNETES_HOST:-"127.0.0.1"}
|
||||||
|
|
||||||
FROM golang:alpine AS deps
|
FROM golang:alpine AS deps
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
@@ -28,7 +30,7 @@ RUN export CGO_ENABLED=0 && \
|
|||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN sed -i '/replace/d' go.mod
|
RUN sed -i '/replace/d' go.mod
|
||||||
RUN if [ ! -f swagger/index.html ]; then timeout 15 bee run --gendoc=true --downdoc=true; fi
|
RUN if [ ! -f swagger/index.html ]; then timeout 15 bee run -gendoc=true -downdoc=true; fi
|
||||||
RUN bee generate routers
|
RUN bee generate routers
|
||||||
RUN bee generate docs
|
RUN bee generate docs
|
||||||
RUN bee pack
|
RUN bee pack
|
||||||
@@ -39,6 +41,8 @@ RUN sed -i 's/http:\/\/127.0.0.1:8080\/swagger\/swagger.json/swagger.json/g' /ap
|
|||||||
|
|
||||||
FROM golang:alpine
|
FROM golang:alpine
|
||||||
|
|
||||||
|
ENV KUBERNETES_SERVICE_HOST=$KUBERNETES_HOST
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /app/extracted/oc-datacenter /usr/bin/
|
COPY --from=builder /app/extracted/oc-datacenter /usr/bin/
|
||||||
COPY --from=builder /app/extracted/swagger /app/swagger
|
COPY --from=builder /app/extracted/swagger /app/swagger
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
jwt "github.com/golang-jwt/jwt/v5"
|
jwt "github.com/golang-jwt/jwt/v5"
|
||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type KubeInfo struct {
|
type KubeInfo struct {
|
||||||
@@ -117,12 +120,12 @@ func (c *AdmiraltyController) GetOneTarget() {
|
|||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Title CreateSource
|
// @Title CreateAdmiraltySource
|
||||||
// @Description Create an Admiralty Source on remote cluster
|
// @Description Create an Admiralty Source on remote cluster
|
||||||
// @Param execution path string true "execution id of the workflow"
|
// @Param execution path string true "execution id of the workflow"
|
||||||
// @Success 201
|
// @Success 201
|
||||||
// @router /source/:execution [post]
|
// @router /source/:execution [post]
|
||||||
func (c *AdmiraltyController) CreateSource() {
|
func (c *AdmiraltyController) CreateAdmiraltySource() {
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
execution := c.Ctx.Input.Param(":execution")
|
||||||
fmt.Println("execution :: ", execution)
|
fmt.Println("execution :: ", execution)
|
||||||
@@ -139,6 +142,12 @@ func (c *AdmiraltyController) CreateSource() {
|
|||||||
|
|
||||||
res, err := serv.CreateAdmiraltySource(c.Ctx.Request.Context(),execution)
|
res, err := serv.CreateAdmiraltySource(c.Ctx.Request.Context(),execution)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if apierrors.IsAlreadyExists(err) {
|
||||||
|
c.Ctx.Output.SetStatus(409)
|
||||||
|
c.Data["json"] = map[string]string{"info" : "A source already exists for this namespace : " + execution}
|
||||||
|
c.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
// change code to 500
|
// change code to 500
|
||||||
c.Ctx.Output.SetStatus(500)
|
c.Ctx.Output.SetStatus(500)
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
c.Data["json"] = map[string]string{"error": err.Error()}
|
||||||
@@ -159,13 +168,21 @@ func (c *AdmiraltyController) CreateSource() {
|
|||||||
// @Title CreateAdmiraltyTarget
|
// @Title CreateAdmiraltyTarget
|
||||||
// @Description Create an Admiralty Target in the namespace associated to the executionID
|
// @Description Create an Admiralty Target in the namespace associated to the executionID
|
||||||
// @Param execution path string true "execution id of the workflow"
|
// @Param execution path string true "execution id of the workflow"
|
||||||
|
// @Param peer path string true "peerId of the peer the target points to"
|
||||||
// @Success 201
|
// @Success 201
|
||||||
// @router /target/:execution [post]
|
// @router /target/:execution/:peer [post]
|
||||||
func (c *AdmiraltyController) CreateAdmiraltyTarget(){
|
func (c *AdmiraltyController) CreateAdmiraltyTarget(){
|
||||||
var data map[string]interface{}
|
var data map[string]interface{}
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
execution := c.Ctx.Input.Param(":execution")
|
||||||
|
peerId := c.Ctx.Input.Param(":peer")
|
||||||
|
|
||||||
|
if execution == "" || peerId == "" {
|
||||||
|
c.Ctx.Output.SetStatus(400)
|
||||||
|
c.Data["json"] = map[string]string{"error" : "parameters can be empty " + "execution: " + execution + " peer: " + peerId}
|
||||||
|
c.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
serv, err := infrastructure.NewService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -176,7 +193,7 @@ func (c *AdmiraltyController) CreateAdmiraltyTarget(){
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := serv.CreateAdmiraltyTarget(c.Ctx.Request.Context(),execution)
|
resp, err := serv.CreateAdmiraltyTarget(c.Ctx.Request.Context(),execution, peerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// change code to 500
|
// change code to 500
|
||||||
c.Ctx.Output.SetStatus(500)
|
c.Ctx.Output.SetStatus(500)
|
||||||
@@ -210,14 +227,16 @@ func (c *AdmiraltyController) CreateAdmiraltyTarget(){
|
|||||||
|
|
||||||
// @Title GetKubeSecret
|
// @Title GetKubeSecret
|
||||||
// @Description Retrieve the secret created from a Kubeconfig that will be associated to an Admiralty Target
|
// @Description Retrieve the secret created from a Kubeconfig that will be associated to an Admiralty Target
|
||||||
|
|
||||||
// @Param execution path string true "execution id of the workflow"
|
// @Param execution path string true "execution id of the workflow"
|
||||||
|
// @Param peer path string true "UUID of the peer to which the resource is linked"
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @router /secret/:execution [get]
|
// @router /secret/:execution/:peer [get]
|
||||||
func(c *AdmiraltyController) GetKubeSecret() {
|
func(c *AdmiraltyController) GetKubeSecret() {
|
||||||
var data map[string]interface{}
|
var data map[string]interface{}
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
execution := c.Ctx.Input.Param(":execution")
|
||||||
|
peerId := c.Ctx.Input.Param(":peer")
|
||||||
|
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
serv, err := infrastructure.NewService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -228,7 +247,7 @@ func(c *AdmiraltyController) GetKubeSecret() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(),execution)
|
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(),execution, peerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// change code to 500
|
// change code to 500
|
||||||
c.Ctx.Output.SetStatus(500)
|
c.Ctx.Output.SetStatus(500)
|
||||||
@@ -260,9 +279,10 @@ func(c *AdmiraltyController) GetKubeSecret() {
|
|||||||
// @Description Creat a secret from a Kubeconfig that will be associated to an Admiralty Target
|
// @Description Creat a secret from a Kubeconfig that will be associated to an Admiralty Target
|
||||||
|
|
||||||
// @Param execution path string true "execution id of the workflow"
|
// @Param execution path string true "execution id of the workflow"
|
||||||
|
// @Param peer path string true "UUID of the peer to which the resource is linked"
|
||||||
// @Param kubeconfig body controllers.RemoteKubeconfig true "Kubeconfig to use when creating secret"
|
// @Param kubeconfig body controllers.RemoteKubeconfig true "Kubeconfig to use when creating secret"
|
||||||
// @Success 201
|
// @Success 201
|
||||||
// @router /secret/:execution [post]
|
// @router /secret/:execution/:peer [post]
|
||||||
func (c *AdmiraltyController) CreateKubeSecret() {
|
func (c *AdmiraltyController) CreateKubeSecret() {
|
||||||
var kubeconfig RemoteKubeconfig
|
var kubeconfig RemoteKubeconfig
|
||||||
var respData map[string]interface{}
|
var respData map[string]interface{}
|
||||||
@@ -279,9 +299,8 @@ func (c *AdmiraltyController) CreateKubeSecret() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
execution := c.Ctx.Input.Param(":execution")
|
||||||
|
peerId := c.Ctx.Input.Param(":peer")
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
serv, err := infrastructure.NewService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -292,7 +311,7 @@ func (c *AdmiraltyController) CreateKubeSecret() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := serv.CreateKubeconfigSecret(c.Ctx.Request.Context(),*kubeconfig.Data,execution)
|
resp, err := serv.CreateKubeconfigSecret(c.Ctx.Request.Context(),*kubeconfig.Data,execution, peerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// change code to 500
|
// change code to 500
|
||||||
c.Ctx.Output.SetStatus(500)
|
c.Ctx.Output.SetStatus(500)
|
||||||
@@ -311,13 +330,13 @@ func (c *AdmiraltyController) CreateKubeSecret() {
|
|||||||
// @name GetAdmiraltyNodes
|
// @name GetAdmiraltyNodes
|
||||||
// @description Allows user to test if an admiralty connection has already been established : Target and valid Secret set up on the local host and Source set up on remote host
|
// @description Allows user to test if an admiralty connection has already been established : Target and valid Secret set up on the local host and Source set up on remote host
|
||||||
// @Param execution path string true "execution id of the workflow"
|
// @Param execution path string true "execution id of the workflow"
|
||||||
|
// @Param peer path string true "UUID of the peer to which the resource is linked"
|
||||||
// @Success 200
|
// @Success 200
|
||||||
// @router /node/:execution [get]
|
// @router /node/:execution/:peer [get]
|
||||||
func (c *AdmiraltyController) GetNodeReady(){
|
func (c *AdmiraltyController) GetNodeReady(){
|
||||||
var secret v1.Secret
|
var secret v1.Secret
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
execution := c.Ctx.Input.Param(":execution")
|
||||||
|
peerId := c.Ctx.Input.Param(":peer")
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
serv, err := infrastructure.NewService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -339,13 +358,15 @@ func (c *AdmiraltyController) GetNodeReady(){
|
|||||||
if node == nil {
|
if node == nil {
|
||||||
c.Ctx.Output.SetStatus(404)
|
c.Ctx.Output.SetStatus(404)
|
||||||
c.Data["json"] = map[string]string{
|
c.Data["json"] = map[string]string{
|
||||||
"error" : "the node for " + execution + " can't be found, make sure both target and source resources are set up on local and remote hosts",
|
"node" : "the node for " + execution + " can't be found, make sure both target and source resources are set up on local and remote hosts",
|
||||||
}
|
}
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(),execution)
|
|
||||||
|
|
||||||
|
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(),execution, peerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// change code to 500
|
// change code to 500
|
||||||
c.Ctx.Output.SetStatus(500)
|
c.Ctx.Output.SetStatus(500)
|
||||||
@@ -360,7 +381,6 @@ func (c *AdmiraltyController) GetNodeReady(){
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Extract JWT token RS265 encoded
|
// Extract JWT token RS265 encoded
|
||||||
var editedKubeconfig map[string]interface{}
|
var editedKubeconfig map[string]interface{}
|
||||||
json.Unmarshal(resp,&secret)
|
json.Unmarshal(resp,&secret)
|
||||||
@@ -393,14 +413,15 @@ func (c *AdmiraltyController) GetNodeReady(){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if *isExpired {
|
if *isExpired {
|
||||||
c.Data["json"] = map[string]string{
|
c.Data["json"] = map[string]interface{}{
|
||||||
"token" : "token in the secret is expired and must be regenerated",
|
"token" : "token in the secret is expired and must be regenerated",
|
||||||
|
"node": node,
|
||||||
}
|
}
|
||||||
c.Ctx.Output.SetStatus(410)
|
c.Ctx.Output.SetStatus(410)
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Data["json"] = map[string]bool{"ok": true}
|
c.Data["json"] = map[string]interface{}{"node": node,"token": true}
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -426,6 +447,8 @@ func retrieveTokenFromKonfig(editedKubeconfig map[string]interface{}) (string,er
|
|||||||
}
|
}
|
||||||
|
|
||||||
func isTokenExpired(token string) (*bool, error){
|
func isTokenExpired(token string) (*bool, error){
|
||||||
|
logger := oclib.GetLogger()
|
||||||
|
|
||||||
t, _, err := new(jwt.Parser).ParseUnverified(token, jwt.MapClaims{})
|
t, _, err := new(jwt.Parser).ParseUnverified(token, jwt.MapClaims{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("couldn't decode token")
|
fmt.Println("couldn't decode token")
|
||||||
@@ -437,7 +460,11 @@ func isTokenExpired(token string) (*bool, error){
|
|||||||
fmt.Println("Error while checking token's expiration time")
|
fmt.Println("Error while checking token's expiration time")
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
fmt.Println("Expiration date : " + expiration.UTC().Format("2006-01-02T15:04:05"))
|
|
||||||
|
logger.Debug().Msg("Expiration date : " + expiration.UTC().Format("2006-01-02T15:04:05"))
|
||||||
|
logger.Debug().Msg(fmt.Sprint("Now : ", time.Now().Unix()))
|
||||||
|
logger.Debug().Msg(fmt.Sprint("Token : ", expiration.Unix()))
|
||||||
|
|
||||||
|
|
||||||
expired := expiration.Unix() < time.Now().Unix()
|
expired := expiration.Unix() < time.Now().Unix()
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"oc-datacenter/infrastructure"
|
"oc-datacenter/infrastructure"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
oclib "cloud.o-forge.io/core/oc-lib"
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
@@ -247,19 +246,11 @@ func (o *BookingController) Post() {
|
|||||||
o.ServeJSON()
|
o.ServeJSON()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := o.createNamespace(resp.ExecutionsID); err != nil {
|
if err := o.createNamespace(resp.ExecutionsID); err != nil {
|
||||||
if strings.Contains(err.Error(), "already exists") {
|
fmt.Println(err.Error())
|
||||||
err = nil
|
|
||||||
} else {
|
|
||||||
o.Data["json"] = map[string]interface{}{
|
|
||||||
"data": nil,
|
|
||||||
"code": 500,
|
|
||||||
"error": err.Error(),
|
|
||||||
}
|
|
||||||
o.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
o.Data["json"] = map[string]interface{}{
|
o.Data["json"] = map[string]interface{}{
|
||||||
"data": []interface{}{b},
|
"data": []interface{}{b},
|
||||||
"code": 200,
|
"code": 200,
|
||||||
|
|||||||
@@ -3,8 +3,5 @@
|
|||||||
"NATS_URL": "nats://localhost:4222",
|
"NATS_URL": "nats://localhost:4222",
|
||||||
"MONGO_DATABASE": "DC_myDC",
|
"MONGO_DATABASE": "DC_myDC",
|
||||||
"KUBERNETES_SERVICE_HOST": "172.16.0.183",
|
"KUBERNETES_SERVICE_HOST": "172.16.0.183",
|
||||||
"port": "8092",
|
"port": "8092"
|
||||||
"KUBE_CA": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTXpnNE5UazJNVFl3SGhjTk1qVXdNakEyTVRZek16TTJXaGNOTXpVd01qQTBNVFl6TXpNMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTXpnNE5UazJNVFl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSbi9jVmNUb1orekZUdWZSL29qbG5JMnVpZXJYeTkxcWhxYWpHdWVobXYKV1A4NVQ1dXpkcE1rcFhrNnB5bTlFU0RlRjk1WDFkeTJqdjVFR3paZzZ2WWtvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXJRK0xUR2NMNXBENnBxSEozaVh5CmZiMFRQUDR3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUlObXp3ejhOUVRCNFlURlZJd3BudDhpQjJ5alRlQjYKbkZxRUN6SWw0amUzQWlFQW04dzRma1h0UEhzUG1Yc0hhUXFGSkhkUm9SQ1pSa016akU3REdZY1lMNVE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
|
||||||
"KUBE_CERT": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJYVlyeG5xbm54WEl3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOek00T0RVNU5qRTJNQjRYRFRJMU1ESXdOakUyTXpNek5sb1hEVEkyTURJdwpOakUyTXpNek5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJHeDVVb1Ura01obE9xeHgKTjhRV1FOOGF1ekxXRHpjZTBVbnRYWFdHUmFvWHdHdnlYUldkaFlQcVNoU0xJVGttMG5GV2t5cEZlNUdXTXJlVApZd0hReE9talNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCU0ZlbDVtUXNEaW1vMCtEUzZZZWM1QXdDRXFWREFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQWs3U3UrV3RmQks4SmVPazRreVFVdEFtMkxoak8zV25qOW5SdW9HbVpyTGdDSUJwdVNnNU5oMjUrYm1xMgpZQ2xEM3NLTGdQM1ZKUitCYytxS3h3UjVHbmJwCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTXpnNE5UazJNVFl3SGhjTk1qVXdNakEyTVRZek16TTJXaGNOTXpVd01qQTBNVFl6TXpNMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTXpnNE5UazJNVFl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSTDJSZ1U5RHJZazhKUm4xeDlWSVI3eU5hdWVjaFZuK1pRdDVyeDZaalYKeFRSd0RFT0xXZ1MvbkNpYkp6eUVFNmhLUDVzczBPdnp0ZzlxeFZYU1orNzBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWhYcGVaa0xBNHBxTlBnMHVtSG5PClFNQWhLbFF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnS09hYVMyczRSWWgrU3J0TXpXTnVtVHduajlKOTZuWUkKL0prdEhjNU5lQnNDSVFDbTY5a1U3cDA5V3hHYWdkNmRQbUlOQ09Fa2V2bzZoQ0dNQTNpd0ZlZ3BiQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
|
||||||
"KUBE_DATA": "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU0yYUxXTmtPQ2ZGRTJxM2V1VE9kaHd0RXdxTWRaVUZTTlRPOG50OER0K1RvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFYkhsU2hUNlF5R1U2ckhFM3hCWkEzeHE3TXRZUE54N1JTZTFkZFlaRnFoZkFhL0pkRloyRgpnK3BLRklzaE9TYlNjVmFUS2tWN2taWXl0NU5qQWRERTZRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,9 @@ version: '3.4'
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
oc-datacenter:
|
oc-datacenter:
|
||||||
|
env_file:
|
||||||
|
- path: ./env.env
|
||||||
|
required: false
|
||||||
environment:
|
environment:
|
||||||
- MONGO_DATABASE=DC_myDC
|
- MONGO_DATABASE=DC_myDC
|
||||||
image: 'oc-datacenter:latest'
|
image: 'oc-datacenter:latest'
|
||||||
|
|||||||
@@ -1,9 +1,5 @@
|
|||||||
{
|
{
|
||||||
"MONGO_URL":"mongodb://mongo:27017/",
|
"MONGO_URL":"mongodb://mongo:27017/",
|
||||||
"NATS_URL":"nats://nats:4222",
|
"NATS_URL":"nats://nats:4222",
|
||||||
"MONGO_DATABASE":"DC_myDC",
|
"MONGO_DATABASE":"DC_myDC"
|
||||||
"KUBERNETES_SERVICE_HOST" : "172.16.0.181",
|
|
||||||
"KUBE_CA" : "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTXpnNE5UazJNVFl3SGhjTk1qVXdNakEyTVRZek16TTJXaGNOTXpVd01qQTBNVFl6TXpNMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTXpnNE5UazJNVFl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSbi9jVmNUb1orekZUdWZSL29qbG5JMnVpZXJYeTkxcWhxYWpHdWVobXYKV1A4NVQ1dXpkcE1rcFhrNnB5bTlFU0RlRjk1WDFkeTJqdjVFR3paZzZ2WWtvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXJRK0xUR2NMNXBENnBxSEozaVh5CmZiMFRQUDR3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUlObXp3ejhOUVRCNFlURlZJd3BudDhpQjJ5alRlQjYKbkZxRUN6SWw0amUzQWlFQW04dzRma1h0UEhzUG1Yc0hhUXFGSkhkUm9SQ1pSa016akU3REdZY1lMNVE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
|
||||||
"KUBE_CERT":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJYVlyeG5xbm54WEl3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOek00T0RVNU5qRTJNQjRYRFRJMU1ESXdOakUyTXpNek5sb1hEVEkyTURJdwpOakUyTXpNek5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJHeDVVb1Ura01obE9xeHgKTjhRV1FOOGF1ekxXRHpjZTBVbnRYWFdHUmFvWHdHdnlYUldkaFlQcVNoU0xJVGttMG5GV2t5cEZlNUdXTXJlVApZd0hReE9talNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCU0ZlbDVtUXNEaW1vMCtEUzZZZWM1QXdDRXFWREFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQWs3U3UrV3RmQks4SmVPazRreVFVdEFtMkxoak8zV25qOW5SdW9HbVpyTGdDSUJwdVNnNU5oMjUrYm1xMgpZQ2xEM3NLTGdQM1ZKUitCYytxS3h3UjVHbmJwCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTXpnNE5UazJNVFl3SGhjTk1qVXdNakEyTVRZek16TTJXaGNOTXpVd01qQTBNVFl6TXpNMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTXpnNE5UazJNVFl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSTDJSZ1U5RHJZazhKUm4xeDlWSVI3eU5hdWVjaFZuK1pRdDVyeDZaalYKeFRSd0RFT0xXZ1MvbkNpYkp6eUVFNmhLUDVzczBPdnp0ZzlxeFZYU1orNzBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWhYcGVaa0xBNHBxTlBnMHVtSG5PClFNQWhLbFF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnS09hYVMyczRSWWgrU3J0TXpXTnVtVHduajlKOTZuWUkKL0prdEhjNU5lQnNDSVFDbTY5a1U3cDA5V3hHYWdkNmRQbUlOQ09Fa2V2bzZoQ0dNQTNpd0ZlZ3BiQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
|
||||||
"KUBE_DATA": "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU0yYUxXTmtPQ2ZGRTJxM2V1VE9kaHd0RXdxTWRaVUZTTlRPOG50OER0K1RvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFYkhsU2hUNlF5R1U2ckhFM3hCWkEzeHE3TXRZUE54N1JTZTFkZFlaRnFoZkFhL0pkRloyRgpnK3BLRklzaE9TYlNjVmFUS2tWN2taWXl0NU5qQWRERTZRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
|
||||||
}
|
}
|
||||||
4
env.env
Normal file
4
env.env
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
KUBERNETES_SERVICE_HOST=192.168.1.169
|
||||||
|
KUBE_CA="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTVlk3ZHZhNEdYTVdkMy9jMlhLN3JLYjlnWXgyNSthaEE0NmkyNVBkSFAKRktQL2UxSVMyWVF0dzNYZW1TTUQxaStZdzJSaVppNUQrSVZUamNtNHdhcnFvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWtlUVJpNFJiODduME5yRnZaWjZHClc2SU55NnN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnRXA5ck04WmdNclRZSHYxZjNzOW5DZXZZeWVVa3lZUk4KWjUzazdoaytJS1FDSVFDbk05TnVGKzlTakIzNDFacGZ5ays2NEpWdkpSM3BhcmVaejdMd2lhNm9kdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
|
||||||
|
KUBE_CERT="LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJWUxWNkFPQkdrU1F3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekl6TVRFeU1ETTJNQjRYRFRJME1EZ3dPREV3TVRNMU5sb1hEVEkxTURndwpPREV3TVRNMU5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJGQ2Q1MFdPeWdlQ2syQzcKV2FrOWY4MVAvSkJieVRIajRWOXBsTEo0ck5HeHFtSjJOb2xROFYxdUx5RjBtOTQ2Nkc0RmRDQ2dqaXFVSk92Swp3NVRPNnd5alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVFJkOFI5cXVWK2pjeUVmL0ovT1hQSzMyS09XekFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQTArbThqTDBJVldvUTZ0dnB4cFo4NVlMalF1SmpwdXM0aDdnSXRxS3NmUVVDSUI2M2ZNdzFBMm5OVWU1TgpIUGZOcEQwSEtwcVN0Wnk4djIyVzliYlJUNklZCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFRc3hXWk9pbnIrcVp4TmFEQjVGMGsvTDF5cE01VHAxOFRaeU92ektJazQKRTFsZWVqUm9STW0zNmhPeVljbnN3d3JoNnhSUnBpMW5RdGhyMzg0S0Z6MlBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTBYZkVmYXJsZm8zTWhIL3lmemx6Cnl0OWlqbHN3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUxJL2dNYnNMT3MvUUpJa3U2WHVpRVMwTEE2cEJHMXgKcnBlTnpGdlZOekZsQWlFQW1wdjBubjZqN3M0MVI0QzFNMEpSL0djNE53MHdldlFmZWdEVGF1R2p3cFk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K"
|
||||||
|
KUBE_DATA="LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5ZS1BFb1dhd1NKUzJlRW5oWmlYMk5VZlY1ZlhKV2krSVNnV09TNFE5VTlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUozblJZN0tCNEtUWUx0WnFUMS96VS84a0Z2Sk1lUGhYMm1Vc25pczBiR3FZblkyaVZEeApYVzR2SVhTYjNqcm9iZ1YwSUtDT0twUWs2OHJEbE03ckRBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
||||||
@@ -17,9 +17,9 @@ type Infrastructure interface {
|
|||||||
CreateRole(ctx context.Context, ns string, role string, groups [][]string, resources [][]string, verbs [][]string) error
|
CreateRole(ctx context.Context, ns string, role string, groups [][]string, resources [][]string, verbs [][]string) error
|
||||||
GetTargets(ctx context.Context) ([]string,error)
|
GetTargets(ctx context.Context) ([]string,error)
|
||||||
CreateAdmiraltySource(context context.Context, executionId string) ([]byte, error)
|
CreateAdmiraltySource(context context.Context, executionId string) ([]byte, error)
|
||||||
CreateKubeconfigSecret(context context.Context,kubeconfig string, executionId string) ([]byte, error)
|
CreateKubeconfigSecret(context context.Context, kubeconfig string, executionId string, peerId string) ([]byte, error)
|
||||||
GetKubeconfigSecret(context context.Context,executionId string) ([]byte, error)
|
GetKubeconfigSecret(context context.Context, executionId string, peerId string) ([]byte, error)
|
||||||
CreateAdmiraltyTarget(context context.Context,executionId string)([]byte,error)
|
CreateAdmiraltyTarget(context context.Context, executionId string, peerId string)([]byte,error)
|
||||||
GetOneNode(context context.Context, executionID string) (*v1.Node, error)
|
GetOneNode(context context.Context, executionID string) (*v1.Node, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package infrastructure
|
package infrastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
|
||||||
"oc-datacenter/conf"
|
"oc-datacenter/conf"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -16,14 +14,42 @@ import (
|
|||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
apply "k8s.io/client-go/applyconfigurations/core/v1"
|
||||||
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var gvrSources = schema.GroupVersionResource{Group: "multicluster.admiralty.io", Version: "v1alpha1", Resource: "sources"}
|
||||||
|
var gvrTargets = schema.GroupVersionResource{Group: "multicluster.admiralty.io", Version: "v1alpha1", Resource: "targets"}
|
||||||
|
|
||||||
type KubernetesService struct {
|
type KubernetesService struct {
|
||||||
Set *kubernetes.Clientset
|
Set *kubernetes.Clientset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewDynamicClient() (*dynamic.DynamicClient, error) {
|
||||||
|
config := &rest.Config{
|
||||||
|
Host: conf.GetConfig().KubeHost + ":" + conf.GetConfig().KubePort,
|
||||||
|
TLSClientConfig: rest.TLSClientConfig{
|
||||||
|
CAData: []byte(conf.GetConfig().KubeCA),
|
||||||
|
CertData: []byte(conf.GetConfig().KubeCert),
|
||||||
|
KeyData: []byte(conf.GetConfig().KubeData),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
dynamicClient, err := dynamic.NewForConfig(config)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Error creating Dynamic client: " + err.Error())
|
||||||
|
}
|
||||||
|
if dynamicClient == nil {
|
||||||
|
return nil, errors.New("Error creating Dynamic client: dynamicClient is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
return dynamicClient, nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewKubernetesService() (Infrastructure, error) {
|
func NewKubernetesService() (Infrastructure, error) {
|
||||||
config := &rest.Config{
|
config := &rest.Config{
|
||||||
Host: conf.GetConfig().KubeHost + ":" + conf.GetConfig().KubePort,
|
Host: conf.GetConfig().KubeHost + ":" + conf.GetConfig().KubePort,
|
||||||
@@ -33,6 +59,7 @@ func NewKubernetesService() (Infrastructure, error) {
|
|||||||
KeyData: []byte(conf.GetConfig().KubeData),
|
KeyData: []byte(conf.GetConfig().KubeData),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create clientset
|
// Create clientset
|
||||||
clientset, err := kubernetes.NewForConfig(config)
|
clientset, err := kubernetes.NewForConfig(config)
|
||||||
fmt.Println("NewForConfig", clientset, err)
|
fmt.Println("NewForConfig", clientset, err)
|
||||||
@@ -43,6 +70,7 @@ func NewKubernetesService() (Infrastructure, error) {
|
|||||||
return nil, errors.New("Error creating Kubernetes client: clientset is nil")
|
return nil, errors.New("Error creating Kubernetes client: clientset is nil")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return &KubernetesService{
|
return &KubernetesService{
|
||||||
Set: clientset,
|
Set: clientset,
|
||||||
}, nil
|
}, nil
|
||||||
@@ -82,6 +110,9 @@ func (k *KubernetesService) CreateNamespace(ctx context.Context, ns string) erro
|
|||||||
namespace := &v1.Namespace{
|
namespace := &v1.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: ns,
|
Name: ns,
|
||||||
|
Labels: map[string]string{
|
||||||
|
"multicluster-scheduler":"enabled",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Create the namespace
|
// Create the namespace
|
||||||
@@ -195,8 +226,6 @@ func (k *KubernetesService) GenerateToken(ctx context.Context, ns string, durati
|
|||||||
return token.Status.Token, nil
|
return token.Status.Token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Needs refactoring :
|
// Needs refactoring :
|
||||||
// - Retrieving the metada (in a method that Unmarshall the part of the json in a metadata object)
|
// - Retrieving the metada (in a method that Unmarshall the part of the json in a metadata object)
|
||||||
func (k *KubernetesService) GetTargets(ctx context.Context) ([]string, error) {
|
func (k *KubernetesService) GetTargets(ctx context.Context) ([]string, error) {
|
||||||
@@ -251,8 +280,8 @@ func (k *KubernetesService) GetTargets(ctx context.Context) ([]string,error){
|
|||||||
// - have declared the same namespace as the one where the pods are created in the local cluster
|
// - have declared the same namespace as the one where the pods are created in the local cluster
|
||||||
//
|
//
|
||||||
// - have delcared a serviceAccount with sufficient permission to create pods
|
// - have delcared a serviceAccount with sufficient permission to create pods
|
||||||
func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context,executionId string)([]byte,error){
|
func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context, executionId string, peerId string) ([]byte, error) {
|
||||||
exists, err := k.GetKubeconfigSecret(context,executionId)
|
exists, err := k.GetKubeconfigSecret(context, executionId, peerId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error verifying kube-secret before creating target")
|
fmt.Println("Error verifying kube-secret before creating target")
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -263,35 +292,33 @@ func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context,execut
|
|||||||
return nil, nil // Maybe we could create a wrapper for errors and add more info to have
|
return nil, nil // Maybe we could create a wrapper for errors and add more info to have
|
||||||
}
|
}
|
||||||
|
|
||||||
var targetManifest string
|
targetName := "target-" + getConcatenatedName(peerId,executionId)
|
||||||
var tpl bytes.Buffer
|
target := map[string]interface{}{
|
||||||
tmpl, err := template.New("target").
|
"apiVersion": "multicluster.admiralty.io/v1alpha1",
|
||||||
Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Target\", \"metadata\": {\"name\": \"target-{{.ExecutionId}}\"}, \"spec\": { \"kubeconfigSecret\" :{\"name\": \"kube-secret-{{.ExecutionId}}\"}} }")
|
"kind": "Target",
|
||||||
|
"metadata": map[string]interface{}{
|
||||||
|
"name": targetName,
|
||||||
|
"namespace": executionId,
|
||||||
|
"labels": map[string]interface{}{
|
||||||
|
"peer": peerId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"kubeconfigSecret": map[string]string{
|
||||||
|
"name" : "kube-secret-"+ getConcatenatedName(peerId, executionId),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := dynamicClientApply(executionId, targetName, gvrTargets, context, target)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error creating the template for the target Manifest")
|
return nil, errors.New("Error when trying to apply Target definition :" + err.Error())
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tmpl.Execute(&tpl, map[string]string{"ExecutionId":executionId})
|
return res, nil
|
||||||
targetManifest = tpl.String()
|
|
||||||
resp, err := postCDRapiKube(
|
|
||||||
*k.Set,
|
|
||||||
context,
|
|
||||||
"/apis/multicluster.admiralty.io/v1alpha1/namespaces/"+ executionId +"/targets",
|
|
||||||
[]byte(targetManifest),
|
|
||||||
map[string]string{"fieldManager":"kubectl-client-side-apply"},
|
|
||||||
map[string]string{"fieldValidation":"Strict"},
|
|
||||||
)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", resp)
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Admiralty Source allows a cluster to receive pods from a remote cluster
|
// Admiralty Source allows a cluster to receive pods from a remote cluster
|
||||||
//
|
//
|
||||||
// The source must be associated to a serviceAccount, which will execute the pods locally.
|
// The source must be associated to a serviceAccount, which will execute the pods locally.
|
||||||
@@ -301,39 +328,31 @@ func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context,execut
|
|||||||
// to rather contact the oc-datacenter from the remote cluster to create the source
|
// to rather contact the oc-datacenter from the remote cluster to create the source
|
||||||
// locally and retrieve the token for the serviceAccount
|
// locally and retrieve the token for the serviceAccount
|
||||||
func (k *KubernetesService) CreateAdmiraltySource(context context.Context,executionId string) ([]byte, error) {
|
func (k *KubernetesService) CreateAdmiraltySource(context context.Context,executionId string) ([]byte, error) {
|
||||||
var sourceManifest string
|
|
||||||
var tpl bytes.Buffer
|
source := map[string]interface{}{
|
||||||
tmpl, err := template.New("source").
|
"apiVersion": "multicluster.admiralty.io/v1alpha1",
|
||||||
Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Source\", \"metadata\": {\"name\": \"source-{{.ExecutionId}}\"}, \"spec\": {\"serviceAccountName\": \"sa-{{.ExecutionId}}\"} }")
|
"kind": "Source",
|
||||||
if err != nil {
|
"metadata": map[string]interface{}{
|
||||||
fmt.Println("Error creating the template for the source Manifest")
|
"name": "source-"+executionId,
|
||||||
return nil, err
|
"namespace": executionId,
|
||||||
|
},
|
||||||
|
"spec": map[string]interface{}{
|
||||||
|
"serviceAccountName": "sa-"+executionId,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
err = tmpl.Execute(&tpl, map[string]string{"ExecutionId":executionId})
|
|
||||||
sourceManifest = tpl.String()
|
|
||||||
|
|
||||||
resp, err := postCDRapiKube(
|
res, err := dynamicClientApply(executionId, "source-" + executionId,gvrSources, context, source)
|
||||||
*k.Set,
|
|
||||||
context,
|
|
||||||
"/apis/multicluster.admiralty.io/v1alpha1/namespaces/"+ executionId +"/sources",
|
|
||||||
[]byte(sourceManifest),
|
|
||||||
map[string]string{"fieldManager":"kubectl-client-side-apply"},
|
|
||||||
map[string]string{"fieldValidation":"Strict"},
|
|
||||||
)
|
|
||||||
|
|
||||||
// We can add more info to the log with the content of resp if not nil
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", resp)
|
return nil, errors.New("Error when trying to apply Source definition :" + err.Error())
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a secret from a kubeconfing. Use it to create the secret binded to an Admiralty
|
// Create a secret from a kubeconfing. Use it to create the secret binded to an Admiralty
|
||||||
// target, which must contain the serviceAccount's token value
|
// target, which must contain the serviceAccount's token value
|
||||||
func (k *KubernetesService) CreateKubeconfigSecret(context context.Context,kubeconfig string, executionId string) ([]byte, error) {
|
func (k *KubernetesService) CreateKubeconfigSecret(context context.Context, kubeconfig string, executionId string, peerId string) ([]byte, error) {
|
||||||
config, err := base64.StdEncoding.DecodeString(kubeconfig)
|
config, err := base64.StdEncoding.DecodeString(kubeconfig)
|
||||||
// config, err := base64.RawStdEncoding.DecodeString(kubeconfig)
|
// config, err := base64.RawStdEncoding.DecodeString(kubeconfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -342,32 +361,37 @@ func (k *KubernetesService) CreateKubeconfigSecret(context context.Context,kubec
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
secretManifest := &v1.Secret{
|
secretApplyConfig := apply.Secret("kube-secret-" + getConcatenatedName(peerId, executionId),
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
executionId).
|
||||||
Name: "kube-secret-" + executionId,
|
WithData(map[string][]byte{
|
||||||
Namespace: executionId,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"config": config,
|
"config": config,
|
||||||
},
|
},
|
||||||
}
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// exists, err := k.GetKubeconfigSecret(context,executionId)
|
||||||
|
// if err != nil {
|
||||||
|
// fmt.Println("Error verifying if kube secret exists in namespace ", executionId)
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
// if exists != nil {
|
||||||
|
// fmt.Println("kube-secret already exists in namespace", executionId)
|
||||||
|
// fmt.Println("Overriding existing kube-secret with a newer resource")
|
||||||
|
// // TODO : implement DeleteKubeConfigSecret(executionID)
|
||||||
|
// deleted, err := k.DeleteKubeConfigSecret(executionId)
|
||||||
|
// _ = deleted
|
||||||
|
// _ = err
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
exists, err := k.GetKubeconfigSecret(context,executionId)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error verifying if kube secret exists in namespace ", executionId)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if exists != nil {
|
|
||||||
fmt.Println("kube-secret already exists in namespace", executionId)
|
|
||||||
fmt.Println("Overriding existing kube-secret with a newer resource")
|
|
||||||
// TODO : implement DeleteKubeConfigSecret(executionID)
|
|
||||||
deleted, err := k.DeleteKubeConfigSecret(executionId)
|
|
||||||
_ = deleted
|
|
||||||
_ = err
|
|
||||||
}
|
|
||||||
resp, err := k.Set.CoreV1().
|
resp, err := k.Set.CoreV1().
|
||||||
Secrets(executionId).
|
Secrets(executionId).
|
||||||
Create(context,secretManifest,metav1.CreateOptions{})
|
Apply(context,
|
||||||
|
secretApplyConfig,
|
||||||
|
metav1.ApplyOptions{
|
||||||
|
FieldManager: "admiralty-manager",
|
||||||
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error while trying to contact API to get secret kube-secret-" + executionId)
|
fmt.Println("Error while trying to contact API to get secret kube-secret-" + executionId)
|
||||||
@@ -384,13 +408,13 @@ func (k *KubernetesService) CreateKubeconfigSecret(context context.Context,kubec
|
|||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *KubernetesService) GetKubeconfigSecret(context context.Context,executionId string) ([]byte, error) {
|
func (k *KubernetesService) GetKubeconfigSecret(context context.Context, executionId string, peerId string) ([]byte, error) {
|
||||||
resp, err := k.Set.CoreV1().
|
resp, err := k.Set.CoreV1().
|
||||||
Secrets(executionId).
|
Secrets(executionId).
|
||||||
Get(context,"kube-secret-"+executionId,metav1.GetOptions{})
|
Get(context, "kube-secret-"+ getConcatenatedName(peerId, executionId), metav1.GetOptions{})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if(apierrors.IsNotFound(err)){
|
if apierrors.IsNotFound(err) {
|
||||||
fmt.Println("kube-secret not found for execution", executionId)
|
fmt.Println("kube-secret not found for execution", executionId)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
@@ -428,7 +452,40 @@ func getCDRapiKube(client kubernetes.Clientset, ctx context.Context, path string
|
|||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func postCDRapiKube(client kubernetes.Clientset, ctx context.Context, path string, body []byte, params ...map[string]string) ([]byte, error){
|
func dynamicClientApply(executionId string, resourceName string, resourceDefinition schema.GroupVersionResource, ctx context.Context, object map[string]interface{}) ([]byte, error) {
|
||||||
|
cli, err := NewDynamicClient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("Could not retrieve dynamic client when creating Admiralty Source : " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := cli.Resource(resourceDefinition).
|
||||||
|
Namespace(executionId).
|
||||||
|
Apply(ctx,
|
||||||
|
resourceName,
|
||||||
|
&unstructured.Unstructured{Object: object},
|
||||||
|
metav1.ApplyOptions{
|
||||||
|
FieldManager: "kubectl-client-side-apply",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
o, err := json.Marshal(object)
|
||||||
|
fmt.Println("Error from k8s API when applying " + fmt.Sprint(string(o)) + " to " + gvrSources.String() + " : " , err)
|
||||||
|
return nil,err
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// We can add more info to the log with the content of resp if not nil
|
||||||
|
resByte, err := json.Marshal(res)
|
||||||
|
if err != nil {
|
||||||
|
// fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", res)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resByte, nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func putCDRapiKube(client kubernetes.Clientset, ctx context.Context, path string, body []byte, params ...map[string]string) ([]byte, error){
|
||||||
req := client.RESTClient().
|
req := client.RESTClient().
|
||||||
Post().
|
Post().
|
||||||
AbsPath(path).
|
AbsPath(path).
|
||||||
@@ -474,3 +531,14 @@ func (k *KubernetesService) GetOneNode(context context.Context,executionID strin
|
|||||||
|
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Returns a concatenation of the peerId and namespace in order for
|
||||||
|
// kubernetes ressources to have a unique name, under 63 characters
|
||||||
|
// and yet identify which peer they are created for
|
||||||
|
func getConcatenatedName(peerId string, namespace string) string {
|
||||||
|
s := strings.Split(peerId, "-")[:2]
|
||||||
|
p := s[0] + "-" + s[1]
|
||||||
|
|
||||||
|
return p + "-" + namespace
|
||||||
|
}
|
||||||
|
|||||||
3
main.go
3
main.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"oc-datacenter/conf"
|
"oc-datacenter/conf"
|
||||||
_ "oc-datacenter/routers"
|
_ "oc-datacenter/routers"
|
||||||
|
"os"
|
||||||
|
|
||||||
oclib "cloud.o-forge.io/core/oc-lib"
|
oclib "cloud.o-forge.io/core/oc-lib"
|
||||||
"cloud.o-forge.io/core/oc-lib/tools"
|
"cloud.o-forge.io/core/oc-lib/tools"
|
||||||
@@ -20,7 +21,7 @@ func main() {
|
|||||||
// Load the right config file
|
// Load the right config file
|
||||||
o := oclib.GetConfLoader()
|
o := oclib.GetConfLoader()
|
||||||
conf.GetConfig().Mode = o.GetStringDefault("MODE", "kubernetes")
|
conf.GetConfig().Mode = o.GetStringDefault("MODE", "kubernetes")
|
||||||
conf.GetConfig().KubeHost = o.GetStringDefault("KUBERNETES_SERVICE_HOST", "")
|
conf.GetConfig().KubeHost = o.GetStringDefault("KUBERNETES_SERVICE_HOST", os.Getenv("KUBERNETES_SERVICE_HOST"))
|
||||||
conf.GetConfig().KubePort = o.GetStringDefault("KUBERNETES_SERVICE_PORT", "6443")
|
conf.GetConfig().KubePort = o.GetStringDefault("KUBERNETES_SERVICE_PORT", "6443")
|
||||||
|
|
||||||
sDec, err := base64.StdEncoding.DecodeString(o.GetStringDefault("KUBE_CA", ""))
|
sDec, err := base64.StdEncoding.DecodeString(o.GetStringDefault("KUBE_CA", ""))
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func init() {
|
|||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "GetNodeReady",
|
Method: "GetNodeReady",
|
||||||
Router: `/node/:execution`,
|
Router: `/node/:execution/:peer`,
|
||||||
AllowHTTPMethods: []string{"get"},
|
AllowHTTPMethods: []string{"get"},
|
||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
Filters: nil,
|
Filters: nil,
|
||||||
@@ -28,7 +28,7 @@ func init() {
|
|||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "GetKubeSecret",
|
Method: "GetKubeSecret",
|
||||||
Router: `/secret/:execution`,
|
Router: `/secret/:execution/:peer`,
|
||||||
AllowHTTPMethods: []string{"get"},
|
AllowHTTPMethods: []string{"get"},
|
||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
Filters: nil,
|
Filters: nil,
|
||||||
@@ -37,7 +37,7 @@ func init() {
|
|||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "CreateKubeSecret",
|
Method: "CreateKubeSecret",
|
||||||
Router: `/secret/:execution`,
|
Router: `/secret/:execution/:peer`,
|
||||||
AllowHTTPMethods: []string{"post"},
|
AllowHTTPMethods: []string{"post"},
|
||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
Filters: nil,
|
Filters: nil,
|
||||||
@@ -45,7 +45,7 @@ func init() {
|
|||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "CreateSource",
|
Method: "CreateAdmiraltySource",
|
||||||
Router: `/source/:execution`,
|
Router: `/source/:execution`,
|
||||||
AllowHTTPMethods: []string{"post"},
|
AllowHTTPMethods: []string{"post"},
|
||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
@@ -55,7 +55,7 @@ func init() {
|
|||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "CreateAdmiraltyTarget",
|
Method: "CreateAdmiraltyTarget",
|
||||||
Router: `/target/:execution`,
|
Router: `/target/:execution/:peer`,
|
||||||
AllowHTTPMethods: []string{"post"},
|
AllowHTTPMethods: []string{"post"},
|
||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
Filters: nil,
|
Filters: nil,
|
||||||
|
|||||||
Reference in New Issue
Block a user