Compare commits
No commits in common. "main" and "feature/namespace" have entirely different histories.
main
...
feature/na
2
.gitignore
vendored
2
.gitignore
vendored
@ -1 +1 @@
|
|||||||
swagger/
|
oc-datacenter
|
||||||
|
53
Dockerfile
53
Dockerfile
@ -1,49 +1,30 @@
|
|||||||
FROM golang:alpine AS deps
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
COPY go.mod go.sum ./
|
|
||||||
RUN sed -i '/replace/d' go.mod
|
|
||||||
RUN go mod download
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
FROM golang:alpine AS builder
|
FROM golang:alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN apk add git
|
|
||||||
|
|
||||||
RUN go install github.com/beego/bee/v2@latest
|
|
||||||
|
|
||||||
WORKDIR /oc-datacenter
|
|
||||||
|
|
||||||
COPY --from=deps /go/pkg /go/pkg
|
|
||||||
COPY --from=deps /app/go.mod /app/go.sum ./
|
|
||||||
|
|
||||||
RUN export CGO_ENABLED=0 && \
|
|
||||||
export GOOS=linux && \
|
|
||||||
export GOARCH=amd64 && \
|
|
||||||
export BUILD_FLAGS="-ldflags='-w -s'"
|
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
|
||||||
RUN sed -i '/replace/d' go.mod
|
RUN apk add git
|
||||||
RUN if [ ! -f swagger/index.html ]; then timeout 15 bee run --gendoc=true --downdoc=true; fi
|
|
||||||
RUN bee generate routers
|
|
||||||
RUN bee generate docs
|
|
||||||
RUN bee pack
|
|
||||||
RUN mkdir -p /app/extracted && tar -zxvf oc-datacenter.tar.gz -C /app/extracted
|
|
||||||
RUN sed -i 's/http:\/\/127.0.0.1:8080\/swagger\/swagger.json/swagger.json/g' /app/extracted/swagger/index.html
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------------------------------
|
RUN go get github.com/beego/bee/v2 && go install github.com/beego/bee/v2@master
|
||||||
|
|
||||||
FROM golang:alpine
|
RUN timeout 15 bee run -gendoc=true -downdoc=true -runmode=dev || :
|
||||||
|
|
||||||
|
RUN sed -i 's/http:\/\/127.0.0.1:8080\/swagger\/swagger.json/swagger.json/g' swagger/index.html
|
||||||
|
|
||||||
|
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o setup .
|
||||||
|
|
||||||
|
RUN ls /app
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /app/extracted/oc-datacenter /usr/bin/
|
|
||||||
COPY --from=builder /app/extracted/swagger /app/swagger
|
COPY --from=builder /app/setup /usr/bin/setup
|
||||||
COPY --from=builder /app/extracted/docker_datacenter.json /etc/oc/datacenter.json
|
COPY --from=builder /app/swagger /app/swagger
|
||||||
|
|
||||||
|
COPY docker_datacenter.json /etc/oc/datacenter.json
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
|
|
||||||
ENTRYPOINT ["oc-datacenter"]
|
ENTRYPOINT ["setup"]
|
||||||
|
35
Makefile
35
Makefile
@ -1,35 +0,0 @@
|
|||||||
.DEFAULT_GOAL := all
|
|
||||||
|
|
||||||
build: clean
|
|
||||||
bee pack
|
|
||||||
|
|
||||||
run:
|
|
||||||
bee run -gendoc=true -downdoc=true
|
|
||||||
|
|
||||||
purge:
|
|
||||||
lsof -t -i:8092 | xargs kill | true
|
|
||||||
|
|
||||||
run-dev:
|
|
||||||
bee generate routers && bee run -gendoc=true -downdoc=true -runmode=prod
|
|
||||||
|
|
||||||
dev: purge run-dev
|
|
||||||
|
|
||||||
debug:
|
|
||||||
bee run -downdebug -gendebug
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf oc-datacenter.tar.gz
|
|
||||||
|
|
||||||
docker:
|
|
||||||
DOCKER_BUILDKIT=1 docker build -t oc/oc-datacenter:0.0.1 -f Dockerfile .
|
|
||||||
docker tag oc/oc-datacenter:0.0.1 oc/oc-datacenter:latest
|
|
||||||
|
|
||||||
publish-kind:
|
|
||||||
kind load docker-image oc/oc-datacenter:0.0.1 --name opencloud
|
|
||||||
|
|
||||||
publish-registry:
|
|
||||||
@echo "TODO"
|
|
||||||
|
|
||||||
all: docker publish-kind publish-registry
|
|
||||||
|
|
||||||
.PHONY: build run clean docker publish-kind publish-registry
|
|
48
README.md
48
README.md
@ -7,9 +7,6 @@ To build :
|
|||||||
bee generate routers
|
bee generate routers
|
||||||
bee run -gendoc=true -downdoc=true
|
bee run -gendoc=true -downdoc=true
|
||||||
|
|
||||||
OR
|
|
||||||
make dev
|
|
||||||
|
|
||||||
If default Swagger page is displayed instead of tyour api, change url in swagger/index.html file to :
|
If default Swagger page is displayed instead of tyour api, change url in swagger/index.html file to :
|
||||||
|
|
||||||
url: "swagger.json"
|
url: "swagger.json"
|
||||||
@ -17,52 +14,7 @@ If default Swagger page is displayed instead of tyour api, change url in swagger
|
|||||||
Note on particular process :
|
Note on particular process :
|
||||||
- set a bookin delete all related workflow booking before creating new ones. (no update of existing ones)
|
- set a bookin delete all related workflow booking before creating new ones. (no update of existing ones)
|
||||||
|
|
||||||
## Admiralty
|
|
||||||
|
|
||||||
The routes in /admiralty will trigger actions on the DC's Kubernetes API to retrieve information on Admiralty resources.
|
|
||||||
|
|
||||||
### Targets
|
|
||||||
|
|
||||||
Remote clusters that can be used by Admiralty to delegate pods.
|
|
||||||
|
|
||||||
To set up a target Admiralty needs to associate a `secret` which contains an edited version of the target's `kubeconfig`.
|
|
||||||
|
|
||||||
Once the Target is set the remote cluster appears in the output of `kubectl get nodes` under the name `admiralty-<namespace>-<target name>-*`
|
|
||||||
|
|
||||||
**TODO** : We might need a way to test if an IP is associated to an admiralty target
|
|
||||||
|
|
||||||
# Docker Kube Settings
|
# Docker Kube Settings
|
||||||
|
|
||||||
Set up your base64 key from your ~/.kube/config.
|
Set up your base64 key from your ~/.kube/config.
|
||||||
Don't forget to set up your external IP in docker_datacenter.json
|
Don't forget to set up your external IP in docker_datacenter.json
|
||||||
## Admiralty
|
|
||||||
|
|
||||||
The routes in /admiralty will trigger actions on the DC's Kubernetes API to retrieve information on Admiralty resources.
|
|
||||||
|
|
||||||
### Targets
|
|
||||||
|
|
||||||
Remote clusters that can be used by Admiralty to delegate pods.
|
|
||||||
|
|
||||||
To set up a target Admiralty needs to associate a `secret` which contains an edited version of the target's `kubeconfig`.
|
|
||||||
|
|
||||||
Once the Target is set the remote cluster appears in the output of `kubectl get nodes` under the name `admiralty-<namespace>-<target name>-*`
|
|
||||||
|
|
||||||
**TODO** : We might need a way to test if an IP is associated to an admiralty target
|
|
||||||
|
|
||||||
# Docker Kube Settings
|
|
||||||
|
|
||||||
Set up your base64 key from your ~/.kube/config.
|
|
||||||
Don't forget to set up your external IP in docker_datacenter.json
|
|
||||||
## Admiralty
|
|
||||||
|
|
||||||
The routes in /admiralty will trigger actions on the DC's Kubernetes API to retrieve information on Admiralty resources.
|
|
||||||
|
|
||||||
### Targets
|
|
||||||
|
|
||||||
Remote clusters that can be used by Admiralty to delegate pods.
|
|
||||||
|
|
||||||
To set up a target Admiralty needs to associate a `secret` which contains an edited version of the target's `kubeconfig`.
|
|
||||||
|
|
||||||
Once the Target is set the remote cluster appears in the output of `kubectl get nodes` under the name `admiralty-<namespace>-<target name>-*`
|
|
||||||
|
|
||||||
**TODO** : We might need a way to test if an IP is associated to an admiralty target
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
appname = oc-datacenter
|
appname = oc-datacenter
|
||||||
httpport = 8092
|
httpport = 8080
|
||||||
runmode = dev
|
runmode = dev
|
||||||
autorender = false
|
autorender = false
|
||||||
copyrequestbody = true
|
copyrequestbody = true
|
||||||
|
@ -1,545 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"oc-datacenter/conf"
|
|
||||||
"oc-datacenter/infrastructure"
|
|
||||||
"oc-datacenter/models"
|
|
||||||
"slices"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
|
||||||
jwt "github.com/golang-jwt/jwt/v5"
|
|
||||||
"gopkg.in/yaml.v2"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
type KubeInfo struct {
|
|
||||||
Url *string
|
|
||||||
KubeCA *string
|
|
||||||
KubeCert *string
|
|
||||||
KubeKey *string
|
|
||||||
}
|
|
||||||
|
|
||||||
type RemoteKubeconfig struct {
|
|
||||||
Data *string
|
|
||||||
}
|
|
||||||
|
|
||||||
type KubeUser struct {
|
|
||||||
Name string
|
|
||||||
User struct {
|
|
||||||
Token string
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type KubeconfigToken struct {
|
|
||||||
ApiVersion string `yaml:"apiVersion"`
|
|
||||||
Kind string `yaml:"kind"`
|
|
||||||
Preferences string `yaml:"preferences"`
|
|
||||||
CurrentContext string `yaml:"current-context"`
|
|
||||||
Clusters []struct{
|
|
||||||
Cluster struct{
|
|
||||||
CA string `yaml:"certificate-authority-data"`
|
|
||||||
Server string `yaml:"server"`
|
|
||||||
|
|
||||||
} `yaml:"cluster"`
|
|
||||||
Name string `yaml:"name"`
|
|
||||||
} `yaml:"clusters"`
|
|
||||||
Contexts []struct{
|
|
||||||
Context struct{
|
|
||||||
Cluster string `yaml:"cluster"`
|
|
||||||
User string `yaml:"user"`
|
|
||||||
} `yaml:"context"`
|
|
||||||
Name string `yaml:"name"`
|
|
||||||
} `yaml:"contexts"`
|
|
||||||
Users []struct{
|
|
||||||
Name string `yaml:"name"`
|
|
||||||
User struct {
|
|
||||||
Token string `yaml:"token"`
|
|
||||||
} `yaml:"user"`
|
|
||||||
} `yaml:"users"`
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Operations about the admiralty objects of the datacenter
|
|
||||||
type AdmiraltyController struct {
|
|
||||||
beego.Controller
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title GetAllTargets
|
|
||||||
// @Description find all Admiralty Target
|
|
||||||
// @Success 200
|
|
||||||
// @router /targets [get]
|
|
||||||
func (c *AdmiraltyController) GetAllTargets() {
|
|
||||||
serv, err := infrastructure.NewService()
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
HandleControllerErrors(c.Controller,500,&err,nil)
|
|
||||||
// c.Ctx.Output.SetStatus(500)
|
|
||||||
// c.ServeJSON()
|
|
||||||
// c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := serv.GetTargets(c.Ctx.Request.Context())
|
|
||||||
c.Data["json"] = res
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title GetOneTarget
|
|
||||||
// @Description find one Admiralty Target
|
|
||||||
// @Param id path string true "the name of the target to get"
|
|
||||||
// @Success 200
|
|
||||||
// @router /targets/:execution [get]
|
|
||||||
func (c *AdmiraltyController) GetOneTarget() {
|
|
||||||
id := c.Ctx.Input.Param(":execution")
|
|
||||||
serv, err := infrastructure.NewService()
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.ServeJSON()
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := serv.GetTargets(c.Ctx.Request.Context())
|
|
||||||
id = "target-"+id
|
|
||||||
found := slices.Contains(res,id)
|
|
||||||
if !found {
|
|
||||||
c.Ctx.Output.SetStatus(404)
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Data["json"] = id
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title CreateSource
|
|
||||||
// @Description Create an Admiralty Source on remote cluster
|
|
||||||
// @Param execution path string true "execution id of the workflow"
|
|
||||||
// @Success 201
|
|
||||||
// @router /source/:execution [post]
|
|
||||||
func (c *AdmiraltyController) CreateSource() {
|
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
|
||||||
fmt.Println("execution :: ", execution)
|
|
||||||
fmt.Println("input :: ", c.Ctx.Input)
|
|
||||||
serv, err := infrastructure.NewKubernetesService()
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.ServeJSON()
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
res, err := serv.CreateAdmiraltySource(c.Ctx.Request.Context(),execution)
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO : Return a description of the created resource
|
|
||||||
var respData map[string]interface{}
|
|
||||||
err = json.Unmarshal(res,&respData)
|
|
||||||
|
|
||||||
c.Ctx.Output.SetStatus(201)
|
|
||||||
c.Data["json"] = respData
|
|
||||||
c.ServeJSON()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title CreateAdmiraltyTarget
|
|
||||||
// @Description Create an Admiralty Target in the namespace associated to the executionID
|
|
||||||
// @Param execution path string true "execution id of the workflow"
|
|
||||||
// @Success 201
|
|
||||||
// @router /target/:execution [post]
|
|
||||||
func (c *AdmiraltyController) CreateAdmiraltyTarget(){
|
|
||||||
var data map[string]interface{}
|
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
|
||||||
|
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := serv.CreateAdmiraltyTarget(c.Ctx.Request.Context(),execution)
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resp == nil {
|
|
||||||
fmt.Println("Error while trying to create Admiralty target")
|
|
||||||
fmt.Println(resp)
|
|
||||||
fmt.Println(err)
|
|
||||||
c.Ctx.Output.SetStatus(401)
|
|
||||||
c.Data["json"] = map[string]string{"error" : "Could not perform the action" }
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(resp,&data)
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.ServeJSON()
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Ctx.Output.SetStatus(201)
|
|
||||||
c.Data["json"] = data
|
|
||||||
c.ServeJSON()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Title GetKubeSecret
|
|
||||||
// @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"
|
|
||||||
// @Success 200
|
|
||||||
// @router /secret/:execution [get]
|
|
||||||
func(c *AdmiraltyController) GetKubeSecret() {
|
|
||||||
var data map[string]interface{}
|
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(),execution)
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resp == nil {
|
|
||||||
c.Ctx.Output.SetStatus(404)
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(resp,&data)
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.ServeJSON()
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Data["json"] = data
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// @Title CreateKubeSecret
|
|
||||||
// @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 kubeconfig body controllers.RemoteKubeconfig true "Kubeconfig to use when creating secret"
|
|
||||||
// @Success 201
|
|
||||||
// @router /secret/:execution [post]
|
|
||||||
func (c *AdmiraltyController) CreateKubeSecret() {
|
|
||||||
var kubeconfig RemoteKubeconfig
|
|
||||||
var respData map[string]interface{}
|
|
||||||
|
|
||||||
data := c.Ctx.Input.CopyBody(100000)
|
|
||||||
|
|
||||||
err := json.Unmarshal(data, &kubeconfig)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error when retrieving the data for kubeconfig from request")
|
|
||||||
fmt.Println(err)
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
|
||||||
|
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := serv.CreateKubeconfigSecret(c.Ctx.Request.Context(),*kubeconfig.Data,execution)
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(resp,&respData)
|
|
||||||
c.Ctx.Output.SetStatus(201)
|
|
||||||
c.Data["json"] = respData
|
|
||||||
c.ServeJSON()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @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
|
|
||||||
// @Param execution path string true "execution id of the workflow"
|
|
||||||
// @Success 200
|
|
||||||
// @router /node/:execution [get]
|
|
||||||
func (c *AdmiraltyController) GetNodeReady(){
|
|
||||||
var secret v1.Secret
|
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
|
||||||
|
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
node, err := serv.GetOneNode(c.Ctx.Request.Context(),execution)
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if node == nil {
|
|
||||||
c.Ctx.Output.SetStatus(404)
|
|
||||||
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",
|
|
||||||
}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := serv.GetKubeconfigSecret(c.Ctx.Request.Context(),execution)
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if resp == nil {
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": "Nodes was up but the secret can't be found"}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Extract JWT token RS265 encoded
|
|
||||||
var editedKubeconfig map[string]interface{}
|
|
||||||
json.Unmarshal(resp,&secret)
|
|
||||||
byteEditedKubeconfig := secret.Data["config"]
|
|
||||||
err = yaml.Unmarshal(byteEditedKubeconfig,&editedKubeconfig)
|
|
||||||
// err = json.Unmarshal(byteEditedKubeconfig,&editedKubeconfig)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while retrieving the kubeconfig from secret-",execution)
|
|
||||||
fmt.Println(err)
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = err
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
token, err := retrieveTokenFromKonfig(editedKubeconfig)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while trying to retrieve token for kubeconfing")
|
|
||||||
fmt.Println(err)
|
|
||||||
HandleControllerErrors(c.Controller,500,&err,nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode token
|
|
||||||
isExpired, err := isTokenExpired(token)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error veryfing token's expiration")
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = err
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
if *isExpired {
|
|
||||||
c.Data["json"] = map[string]string{
|
|
||||||
"token" : "token in the secret is expired and must be regenerated",
|
|
||||||
}
|
|
||||||
c.Ctx.Output.SetStatus(410)
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
c.Data["json"] = map[string]bool{"ok": true}
|
|
||||||
c.ServeJSON()
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func retrieveTokenFromKonfig(editedKubeconfig map[string]interface{}) (string,error) {
|
|
||||||
var kubeUsers []KubeUser
|
|
||||||
b, err := yaml.Marshal(editedKubeconfig["users"])
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while retrieving the users attribute from the Kubeconfig")
|
|
||||||
fmt.Println(err)
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
err = yaml.Unmarshal(b,&kubeUsers)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while unmarshalling users attribute from kubeconfig")
|
|
||||||
fmt.Println(err)
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
fmt.Println(kubeUsers)
|
|
||||||
token := kubeUsers[0].User.Token
|
|
||||||
|
|
||||||
return token, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func isTokenExpired(token string) (*bool, error){
|
|
||||||
t, _, err := new(jwt.Parser).ParseUnverified(token, jwt.MapClaims{})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("couldn't decode token")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
expiration, err := t.Claims.GetExpirationTime()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while checking token's expiration time")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
fmt.Println("Expiration date : " + expiration.UTC().Format("2006-01-02T15:04:05"))
|
|
||||||
|
|
||||||
expired := expiration.Unix() < time.Now().Unix()
|
|
||||||
|
|
||||||
return &expired, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// @name Get Admiralty Kubeconfig
|
|
||||||
// @description Retrieve a kubeconfig from the host with the token to authenticate as the SA from the namespace identified with execution id
|
|
||||||
|
|
||||||
// @Param execution path string true "execution id of the workflow"
|
|
||||||
// @Success 200
|
|
||||||
// @router /kubeconfig/:execution [get]
|
|
||||||
func (c *AdmiraltyController) GetAdmiraltyKubeconfig() {
|
|
||||||
|
|
||||||
execution := c.Ctx.Input.Param(":execution")
|
|
||||||
|
|
||||||
|
|
||||||
serv, err := infrastructure.NewService()
|
|
||||||
if err != nil {
|
|
||||||
// change code to 500
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
generatedToken, err := serv.GenerateToken(c.Ctx.Request.Context(),execution,3600)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Couldn't generate a token for ns-", execution)
|
|
||||||
fmt.Println(err)
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
kubeconfig, err := NewHostKubeWithToken(generatedToken)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Could not retrieve the Kubeconfig edited with token")
|
|
||||||
fmt.Println(err)
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
b, err := json.Marshal(kubeconfig)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while marshalling kubeconfig")
|
|
||||||
c.Ctx.Output.SetStatus(500)
|
|
||||||
c.Data["json"] = map[string]string{"error": err.Error()}
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
encodedKubeconfig := base64.StdEncoding.EncodeToString(b)
|
|
||||||
c.Data["json"] = map[string]string{
|
|
||||||
"data": encodedKubeconfig,
|
|
||||||
}
|
|
||||||
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
func NewHostKubeWithToken(token string) (*models.KubeConfigValue, error){
|
|
||||||
if len(token) == 0 {
|
|
||||||
return nil, fmt.Errorf("you didn't provide a token to be inserted in the Kubeconfig")
|
|
||||||
}
|
|
||||||
|
|
||||||
encodedCA := base64.StdEncoding.EncodeToString([]byte(conf.GetConfig().KubeCA))
|
|
||||||
|
|
||||||
hostKube := models.KubeConfigValue{
|
|
||||||
APIVersion: "v1",
|
|
||||||
CurrentContext: "default",
|
|
||||||
Kind: "Config",
|
|
||||||
Preferences: struct{}{},
|
|
||||||
Clusters: []models.KubeconfigNamedCluster{
|
|
||||||
{
|
|
||||||
Name: "default",
|
|
||||||
Cluster: models.KubeconfigCluster{
|
|
||||||
Server: "https://" + conf.GetConfig().KubeHost + ":6443",
|
|
||||||
CertificateAuthorityData: encodedCA,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Contexts: []models.KubeconfigNamedContext{
|
|
||||||
{
|
|
||||||
Name: "default",
|
|
||||||
Context: models.KubeconfigContext{
|
|
||||||
Cluster: "default",
|
|
||||||
User: "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Users: []models.KubeconfigUser{
|
|
||||||
models.KubeconfigUser{
|
|
||||||
Name: "default",
|
|
||||||
User: models.KubeconfigUserKeyPair{
|
|
||||||
Token: token,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return &hostKube, nil
|
|
||||||
}
|
|
@ -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"
|
||||||
@ -21,8 +20,6 @@ type BookingController struct {
|
|||||||
beego.Controller
|
beego.Controller
|
||||||
}
|
}
|
||||||
|
|
||||||
var BookingExample booking.Booking
|
|
||||||
|
|
||||||
// @Title Search
|
// @Title Search
|
||||||
// @Description search bookings by execution
|
// @Description search bookings by execution
|
||||||
// @Param id path string true "id execution"
|
// @Param id path string true "id execution"
|
||||||
@ -201,6 +198,7 @@ func (o *BookingController) Check() {
|
|||||||
// @Success 200 {object} models.object
|
// @Success 200 {object} models.object
|
||||||
// @router / [post]
|
// @router / [post]
|
||||||
func (o *BookingController) Post() {
|
func (o *BookingController) Post() {
|
||||||
|
fmt.Println("POST")
|
||||||
/*
|
/*
|
||||||
* This function is used to create a booking.
|
* This function is used to create a booking.
|
||||||
* It takes the following parameters:
|
* It takes the following parameters:
|
||||||
@ -211,13 +209,7 @@ func (o *BookingController) Post() {
|
|||||||
*/
|
*/
|
||||||
var resp booking.Booking
|
var resp booking.Booking
|
||||||
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
user, peerID, groups := oclib.ExtractTokenInfo(*o.Ctx.Request)
|
||||||
err := json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &resp)
|
json.Unmarshal(o.Ctx.Input.CopyBody(10000000), &resp)
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error unmarshalling")
|
|
||||||
fmt.Println(err)
|
|
||||||
fmt.Println(resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
dc_id := resp.ResourceID
|
dc_id := resp.ResourceID
|
||||||
// delete all previous bookings
|
// delete all previous bookings
|
||||||
isDraft := o.Ctx.Input.Query("is_draft")
|
isDraft := o.Ctx.Input.Query("is_draft")
|
||||||
@ -247,19 +239,7 @@ func (o *BookingController) Post() {
|
|||||||
o.ServeJSON()
|
o.ServeJSON()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err := o.createNamespace(resp.ExecutionsID); err != nil {
|
fmt.Println("there was an error creating the namespace", o.createNamespace(resp.ExecutionsID))
|
||||||
if strings.Contains(err.Error(), "already exists") {
|
|
||||||
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,
|
||||||
|
@ -21,12 +21,12 @@ func (o *DatacenterController) GetAll() {
|
|||||||
isDraft := o.Ctx.Input.Query("is_draft")
|
isDraft := o.Ctx.Input.Query("is_draft")
|
||||||
storages := oclib.NewRequest(oclib.LibDataEnum(oclib.STORAGE_RESOURCE), user, peerID, groups, nil).Search(&dbs.Filters{
|
storages := oclib.NewRequest(oclib.LibDataEnum(oclib.STORAGE_RESOURCE), user, peerID, groups, nil).Search(&dbs.Filters{
|
||||||
Or: map[string][]dbs.Filter{
|
Or: map[string][]dbs.Filter{
|
||||||
"abstractinstanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: peerID}},
|
"abstractintanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: peerID}},
|
||||||
},
|
},
|
||||||
}, "", isDraft == "true")
|
}, "", isDraft == "true")
|
||||||
computes := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), user, peerID, groups, nil).Search(&dbs.Filters{
|
computes := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), user, peerID, groups, nil).Search(&dbs.Filters{
|
||||||
Or: map[string][]dbs.Filter{
|
Or: map[string][]dbs.Filter{
|
||||||
"abstractinstanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: peerID}},
|
"abstractintanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: peerID}},
|
||||||
},
|
},
|
||||||
}, "", isDraft == "true")
|
}, "", isDraft == "true")
|
||||||
storages.Data = append(storages.Data, computes.Data...)
|
storages.Data = append(storages.Data, computes.Data...)
|
||||||
@ -49,15 +49,15 @@ func (o *DatacenterController) Get() {
|
|||||||
id := o.Ctx.Input.Param(":id")
|
id := o.Ctx.Input.Param(":id")
|
||||||
storages := oclib.NewRequest(oclib.LibDataEnum(oclib.STORAGE_RESOURCE), user, peerID, groups, nil).Search(&dbs.Filters{
|
storages := oclib.NewRequest(oclib.LibDataEnum(oclib.STORAGE_RESOURCE), user, peerID, groups, nil).Search(&dbs.Filters{
|
||||||
Or: map[string][]dbs.Filter{
|
Or: map[string][]dbs.Filter{
|
||||||
"abstractinstanciatedresource.abstractresource.abstractobject.id": {{Operator: dbs.EQUAL.String(), Value: id}},
|
"abstractintanciatedresource.abstractresource.abstractobject.id": {{Operator: dbs.EQUAL.String(), Value: id}},
|
||||||
"abstractinstanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: peerID}},
|
"abstractintanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: peerID}},
|
||||||
},
|
},
|
||||||
}, "", isDraft == "true")
|
}, "", isDraft == "true")
|
||||||
if len(storages.Data) == 0 {
|
if len(storages.Data) == 0 {
|
||||||
computes := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), user, peerID, groups, nil).Search(&dbs.Filters{
|
computes := oclib.NewRequest(oclib.LibDataEnum(oclib.COMPUTE_RESOURCE), user, peerID, groups, nil).Search(&dbs.Filters{
|
||||||
Or: map[string][]dbs.Filter{
|
Or: map[string][]dbs.Filter{
|
||||||
"abstractinstanciatedresource.abstractresource.abstractobject.id": {{Operator: dbs.EQUAL.String(), Value: id}},
|
"abstractintanciatedresource.abstractresource.abstractobject.id": {{Operator: dbs.EQUAL.String(), Value: id}},
|
||||||
"abstractinstanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: peerID}},
|
"abstractintanciatedresource.abstractresource.abstractobject.creator_id": {{Operator: dbs.EQUAL.String(), Value: peerID}},
|
||||||
},
|
},
|
||||||
}, "", isDraft == "true")
|
}, "", isDraft == "true")
|
||||||
if len(computes.Data) == 0 {
|
if len(computes.Data) == 0 {
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
package controllers
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
|
||||||
)
|
|
||||||
|
|
||||||
func HandleControllerErrors(c beego.Controller, code int, err *error, data *map[string]interface{}, messages ...string) {
|
|
||||||
for _, mess := range messages {
|
|
||||||
fmt.Println(mess)
|
|
||||||
}
|
|
||||||
if data != nil {
|
|
||||||
c.Data["json"] = data
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.Data["json"] = map[string]string{"error": (*err).Error()}
|
|
||||||
}
|
|
||||||
c.Ctx.Output.SetStatus(code)
|
|
||||||
c.ServeJSON()
|
|
||||||
}
|
|
@ -40,7 +40,7 @@ func (o *SessionController) GetToken() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("BLAPO", id, duration)
|
fmt.Println("BLAPO", id, duration)
|
||||||
token, err := serv.GenerateToken(o.Ctx.Request.Context(), id, duration)
|
token, err := serv.GetToken(o.Ctx.Request.Context(), id, duration)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// change code to 500
|
// change code to 500
|
||||||
o.Ctx.Output.SetStatus(500)
|
o.Ctx.Output.SetStatus(500)
|
||||||
|
@ -15,10 +15,7 @@ type VersionController struct {
|
|||||||
// @Success 200
|
// @Success 200
|
||||||
// @router / [get]
|
// @router / [get]
|
||||||
func (c *VersionController) GetAll() {
|
func (c *VersionController) GetAll() {
|
||||||
c.Data["json"] = map[string]string{
|
c.Data["json"] = map[string]string{"version": "1"}
|
||||||
"service": "oc-datacenter",
|
|
||||||
"version": "1",
|
|
||||||
}
|
|
||||||
c.ServeJSON()
|
c.ServeJSON()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
{
|
{
|
||||||
"MONGO_URL": "mongodb://mongo:27017/",
|
"port": 8080,
|
||||||
"NATS_URL": "nats://localhost:4222",
|
"MONGO_URL":"mongodb://localhost:27017/",
|
||||||
"MONGO_DATABASE": "DC_myDC",
|
"MONGO_DATABASE":"DC_myDC"
|
||||||
"KUBERNETES_SERVICE_HOST": "172.16.0.183",
|
|
||||||
"port": "8092",
|
|
||||||
"KUBE_CA": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTXpnNE5UazJNVFl3SGhjTk1qVXdNakEyTVRZek16TTJXaGNOTXpVd01qQTBNVFl6TXpNMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTXpnNE5UazJNVFl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSbi9jVmNUb1orekZUdWZSL29qbG5JMnVpZXJYeTkxcWhxYWpHdWVobXYKV1A4NVQ1dXpkcE1rcFhrNnB5bTlFU0RlRjk1WDFkeTJqdjVFR3paZzZ2WWtvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXJRK0xUR2NMNXBENnBxSEozaVh5CmZiMFRQUDR3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUlObXp3ejhOUVRCNFlURlZJd3BudDhpQjJ5alRlQjYKbkZxRUN6SWw0amUzQWlFQW04dzRma1h0UEhzUG1Yc0hhUXFGSkhkUm9SQ1pSa016akU3REdZY1lMNVE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
|
||||||
"KUBE_CERT": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJYVlyeG5xbm54WEl3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOek00T0RVNU5qRTJNQjRYRFRJMU1ESXdOakUyTXpNek5sb1hEVEkyTURJdwpOakUyTXpNek5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJHeDVVb1Ura01obE9xeHgKTjhRV1FOOGF1ekxXRHpjZTBVbnRYWFdHUmFvWHdHdnlYUldkaFlQcVNoU0xJVGttMG5GV2t5cEZlNUdXTXJlVApZd0hReE9talNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCU0ZlbDVtUXNEaW1vMCtEUzZZZWM1QXdDRXFWREFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQWs3U3UrV3RmQks4SmVPazRreVFVdEFtMkxoak8zV25qOW5SdW9HbVpyTGdDSUJwdVNnNU5oMjUrYm1xMgpZQ2xEM3NLTGdQM1ZKUitCYytxS3h3UjVHbmJwCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTXpnNE5UazJNVFl3SGhjTk1qVXdNakEyTVRZek16TTJXaGNOTXpVd01qQTBNVFl6TXpNMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTXpnNE5UazJNVFl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSTDJSZ1U5RHJZazhKUm4xeDlWSVI3eU5hdWVjaFZuK1pRdDVyeDZaalYKeFRSd0RFT0xXZ1MvbkNpYkp6eUVFNmhLUDVzczBPdnp0ZzlxeFZYU1orNzBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWhYcGVaa0xBNHBxTlBnMHVtSG5PClFNQWhLbFF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnS09hYVMyczRSWWgrU3J0TXpXTnVtVHduajlKOTZuWUkKL0prdEhjNU5lQnNDSVFDbTY5a1U3cDA5V3hHYWdkNmRQbUlOQ09Fa2V2bzZoQ0dNQTNpd0ZlZ3BiQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
|
||||||
"KUBE_DATA": "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU0yYUxXTmtPQ2ZGRTJxM2V1VE9kaHd0RXdxTWRaVUZTTlRPOG50OER0K1RvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFYkhsU2hUNlF5R1U2ckhFM3hCWkEzeHE3TXRZUE54N1JTZTFkZFlaRnFoZkFhL0pkRloyRgpnK3BLRklzaE9TYlNjVmFUS2tWN2taWXl0NU5qQWRERTZRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
|
||||||
}
|
}
|
34
docker-compose.base.yml
Normal file
34
docker-compose.base.yml
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
version: '3.4'
|
||||||
|
|
||||||
|
services:
|
||||||
|
mongo:
|
||||||
|
image: 'mongo:latest'
|
||||||
|
networks:
|
||||||
|
- catalog
|
||||||
|
ports:
|
||||||
|
- 27017:27017
|
||||||
|
container_name: mongo
|
||||||
|
volumes:
|
||||||
|
- oc-catalog-data:/data/db
|
||||||
|
- oc-catalog-data:/data/configdb
|
||||||
|
|
||||||
|
mongo-express:
|
||||||
|
image: "mongo-express:latest"
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
- mongo
|
||||||
|
networks:
|
||||||
|
- catalog
|
||||||
|
ports:
|
||||||
|
- 8081:8081
|
||||||
|
environment:
|
||||||
|
- ME_CONFIG_BASICAUTH_USERNAME=test
|
||||||
|
- ME_CONFIG_BASICAUTH_PASSWORD=test
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
oc-catalog-data:
|
||||||
|
|
||||||
|
networks:
|
||||||
|
catalog:
|
||||||
|
external: true
|
||||||
|
# name: catalog
|
@ -10,17 +10,14 @@ services:
|
|||||||
labels:
|
labels:
|
||||||
- "traefik.enable=true"
|
- "traefik.enable=true"
|
||||||
- "traefik.http.routers.datacenter.entrypoints=web"
|
- "traefik.http.routers.datacenter.entrypoints=web"
|
||||||
- "traefik.http.routers.datacenter.rule=PathPrefix(`/datacenter`)"
|
- "traefik.http.middlewares.auth.forwardauth.address=http://oc-auth:8080/oc/forward"
|
||||||
- "traefik.http.services.datacenter.loadbalancer.server.port=8080"
|
- "traefik.http.routers.workflow.rule=PathPrefix(/datacenter)"
|
||||||
- "traefik.http.middlewares.datacenter-rewrite.replacepathregex.regex=^/datacenter(.*)"
|
- "traefik.http.routers.datacenter.tls=false"
|
||||||
- "traefik.http.middlewares.datacenter-rewrite.replacepathregex.replacement=/oc$$1"
|
- "traefik.http.routers.datacenter.middlewares=auth"
|
||||||
- "traefik.http.routers.datacenter.middlewares=datacenter-rewrite"
|
|
||||||
- "traefik.http.middlewares.datacenter.forwardauth.address=http://oc-auth:8080/oc/forward"
|
|
||||||
container_name: oc-datacenter
|
container_name: oc-datacenter
|
||||||
networks:
|
networks:
|
||||||
- oc
|
- catalog
|
||||||
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
oc:
|
catalog:
|
||||||
external: true
|
external: true
|
@ -2,8 +2,8 @@
|
|||||||
"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",
|
"KUBERNETES_SERVICE_HOST" : "192.168.1.69",
|
||||||
"KUBE_CA" : "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTXpnNE5UazJNVFl3SGhjTk1qVXdNakEyTVRZek16TTJXaGNOTXpVd01qQTBNVFl6TXpNMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTXpnNE5UazJNVFl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSbi9jVmNUb1orekZUdWZSL29qbG5JMnVpZXJYeTkxcWhxYWpHdWVobXYKV1A4NVQ1dXpkcE1rcFhrNnB5bTlFU0RlRjk1WDFkeTJqdjVFR3paZzZ2WWtvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXJRK0xUR2NMNXBENnBxSEozaVh5CmZiMFRQUDR3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUlObXp3ejhOUVRCNFlURlZJd3BudDhpQjJ5alRlQjYKbkZxRUN6SWw0amUzQWlFQW04dzRma1h0UEhzUG1Yc0hhUXFGSkhkUm9SQ1pSa016akU3REdZY1lMNVE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
"KUBE_CA" : "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFTVlk3ZHZhNEdYTVdkMy9jMlhLN3JLYjlnWXgyNSthaEE0NmkyNVBkSFAKRktQL2UxSVMyWVF0dzNYZW1TTUQxaStZdzJSaVppNUQrSVZUamNtNHdhcnFvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWtlUVJpNFJiODduME5yRnZaWjZHClc2SU55NnN3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnRXA5ck04WmdNclRZSHYxZjNzOW5DZXZZeWVVa3lZUk4KWjUzazdoaytJS1FDSVFDbk05TnVGKzlTakIzNDFacGZ5ays2NEpWdkpSM3BhcmVaejdMd2lhNm9kdz09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
||||||
"KUBE_CERT":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJYVlyeG5xbm54WEl3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOek00T0RVNU5qRTJNQjRYRFRJMU1ESXdOakUyTXpNek5sb1hEVEkyTURJdwpOakUyTXpNek5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJHeDVVb1Ura01obE9xeHgKTjhRV1FOOGF1ekxXRHpjZTBVbnRYWFdHUmFvWHdHdnlYUldkaFlQcVNoU0xJVGttMG5GV2t5cEZlNUdXTXJlVApZd0hReE9talNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCU0ZlbDVtUXNEaW1vMCtEUzZZZWM1QXdDRXFWREFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQWs3U3UrV3RmQks4SmVPazRreVFVdEFtMkxoak8zV25qOW5SdW9HbVpyTGdDSUJwdVNnNU5oMjUrYm1xMgpZQ2xEM3NLTGdQM1ZKUitCYytxS3h3UjVHbmJwCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTXpnNE5UazJNVFl3SGhjTk1qVXdNakEyTVRZek16TTJXaGNOTXpVd01qQTBNVFl6TXpNMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTXpnNE5UazJNVFl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSTDJSZ1U5RHJZazhKUm4xeDlWSVI3eU5hdWVjaFZuK1pRdDVyeDZaalYKeFRSd0RFT0xXZ1MvbkNpYkp6eUVFNmhLUDVzczBPdnp0ZzlxeFZYU1orNzBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWhYcGVaa0xBNHBxTlBnMHVtSG5PClFNQWhLbFF3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnS09hYVMyczRSWWgrU3J0TXpXTnVtVHduajlKOTZuWUkKL0prdEhjNU5lQnNDSVFDbTY5a1U3cDA5V3hHYWdkNmRQbUlOQ09Fa2V2bzZoQ0dNQTNpd0ZlZ3BiQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
"KUBE_CERT":"LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJWUxWNkFPQkdrU1F3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOekl6TVRFeU1ETTJNQjRYRFRJME1EZ3dPREV3TVRNMU5sb1hEVEkxTURndwpPREV3TVRNMU5sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJGQ2Q1MFdPeWdlQ2syQzcKV2FrOWY4MVAvSkJieVRIajRWOXBsTEo0ck5HeHFtSjJOb2xROFYxdUx5RjBtOTQ2Nkc0RmRDQ2dqaXFVSk92Swp3NVRPNnd5alNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCVFJkOFI5cXVWK2pjeUVmL0ovT1hQSzMyS09XekFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlFQTArbThqTDBJVldvUTZ0dnB4cFo4NVlMalF1SmpwdXM0aDdnSXRxS3NmUVVDSUI2M2ZNdzFBMm5OVWU1TgpIUGZOcEQwSEtwcVN0Wnk4djIyVzliYlJUNklZCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJlRENDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUzTWpNeE1USXdNell3SGhjTk1qUXdPREE0TVRBeE16VTJXaGNOTXpRd09EQTJNVEF4TXpVMgpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUzTWpNeE1USXdNell3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFRc3hXWk9pbnIrcVp4TmFEQjVGMGsvTDF5cE01VHAxOFRaeU92ektJazQKRTFsZWVqUm9STW0zNmhPeVljbnN3d3JoNnhSUnBpMW5RdGhyMzg0S0Z6MlBvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTBYZkVmYXJsZm8zTWhIL3lmemx6Cnl0OWlqbHN3Q2dZSUtvWkl6ajBFQXdJRFNRQXdSZ0loQUxJL2dNYnNMT3MvUUpJa3U2WHVpRVMwTEE2cEJHMXgKcnBlTnpGdlZOekZsQWlFQW1wdjBubjZqN3M0MVI0QzFNMEpSL0djNE53MHdldlFmZWdEVGF1R2p3cFk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K",
|
||||||
"KUBE_DATA": "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU0yYUxXTmtPQ2ZGRTJxM2V1VE9kaHd0RXdxTWRaVUZTTlRPOG50OER0K1RvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFYkhsU2hUNlF5R1U2ckhFM3hCWkEzeHE3TXRZUE54N1JTZTFkZFlaRnFoZkFhL0pkRloyRgpnK3BLRklzaE9TYlNjVmFUS2tWN2taWXl0NU5qQWRERTZRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
"KUBE_DATA": "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSU5ZS1BFb1dhd1NKUzJlRW5oWmlYMk5VZlY1ZlhKV2krSVNnV09TNFE5VTlvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFVUozblJZN0tCNEtUWUx0WnFUMS96VS84a0Z2Sk1lUGhYMm1Vc25pczBiR3FZblkyaVZEeApYVzR2SVhTYjNqcm9iZ1YwSUtDT0twUWs2OHJEbE03ckRBPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo="
|
||||||
}
|
}
|
@ -1,21 +0,0 @@
|
|||||||
@startuml
|
|
||||||
|
|
||||||
boundary "oc-workflow" as workflow
|
|
||||||
boundary "oc-monitord" as monitord
|
|
||||||
boundary "local oc-datacenter" as locdc
|
|
||||||
boundary "remote oc-datacenter" as rocdc
|
|
||||||
|
|
||||||
workflow --> locdc : POST /booking/ {booking object}
|
|
||||||
locdc --> locdc : create Namespace + ServiceAccount
|
|
||||||
workflow --> rocdc : POST /boking/
|
|
||||||
rocdc --> rocdc : create \nNamespace + \nServiceAccount
|
|
||||||
monitord --> monitord : retrieves a Workflow to execute
|
|
||||||
monitord --> monitord : workflow needs repartited execution
|
|
||||||
' monitord --> rocdc : POST /????? (route that use the same \nmethods as /booking/ to create NS & SA)
|
|
||||||
monitord --> rocdc : POST /admiralty/source
|
|
||||||
monitord --> rocdc : GET /admiralty/kubeconfig/:execution_id
|
|
||||||
rocdc -> monitord : base64 encoded edited kubeconfig with token (**how to make it secure** ???)
|
|
||||||
monitord --> locdc : POST /admiralty/secret/:execution_id
|
|
||||||
monitord --> locdc : POST /admiralty/target/:execution_id
|
|
||||||
monitord --> locdc : GET /admiralty/nodes/:execution_id \n(if the node is up it means ALL GOOD)
|
|
||||||
@enduml
|
|
4
go.mod
4
go.mod
@ -5,11 +5,9 @@ go 1.23.0
|
|||||||
toolchain go1.23.3
|
toolchain go1.23.3
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250213085018-271cc2caa026
|
||||||
github.com/beego/beego/v2 v2.3.1
|
github.com/beego/beego/v2 v2.3.1
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
|
||||||
go.mongodb.org/mongo-driver v1.17.1
|
go.mongodb.org/mongo-driver v1.17.1
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
|
||||||
k8s.io/api v0.32.1
|
k8s.io/api v0.32.1
|
||||||
k8s.io/apimachinery v0.32.1
|
k8s.io/apimachinery v0.32.1
|
||||||
k8s.io/client-go v0.32.1
|
k8s.io/client-go v0.32.1
|
||||||
|
16
go.sum
16
go.sum
@ -1,5 +1,11 @@
|
|||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7 h1:fh6SzBPenzIxufIIzExtx4jEE4OhFposqn3EbHFr92Q=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250205160221-88b7cfe2fd0f h1:6V+Z81ywYoDYSVMnM4PVaJYXFgCN3xSG3ddiUPn4jL8=
|
||||||
cloud.o-forge.io/core/oc-lib v0.0.0-20250219142942-5111c9c8bec7/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250205160221-88b7cfe2fd0f/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250212150815-c7c1535ba91a h1:kfTSMCOxYiVGNJWD4OrV7YYTf6t4geKxWpGz4EucpEA=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250212150815-c7c1535ba91a/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250213072626-4920322d0afb h1:EybP8jPpIiN5RLiBxr3cvvF9KIaC+uWvzM23ga0t1yI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250213072626-4920322d0afb/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250213085018-271cc2caa026 h1:CYwpofGfpAhMDrT6jqvu9NI/tcgxCD8PKJZDKEfTvVI=
|
||||||
|
cloud.o-forge.io/core/oc-lib v0.0.0-20250213085018-271cc2caa026/go.mod h1:2roQbUpv3a6mTIr5oU1ux31WbN8YucyyQvCQ0FqwbcE=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/beego/beego/v2 v2.3.1 h1:7MUKMpJYzOXtCUsTEoXOxsDV/UcHw6CPbaWMlthVNsc=
|
github.com/beego/beego/v2 v2.3.1 h1:7MUKMpJYzOXtCUsTEoXOxsDV/UcHw6CPbaWMlthVNsc=
|
||||||
github.com/beego/beego/v2 v2.3.1/go.mod h1:5cqHsOHJIxkq44tBpRvtDe59GuVRVv/9/tyVDxd5ce4=
|
github.com/beego/beego/v2 v2.3.1/go.mod h1:5cqHsOHJIxkq44tBpRvtDe59GuVRVv/9/tyVDxd5ce4=
|
||||||
@ -50,10 +56,6 @@ github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZ
|
|||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
|
||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
@ -264,8 +266,6 @@ gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
|
|||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
@ -4,23 +4,15 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"oc-datacenter/conf"
|
"oc-datacenter/conf"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Infrastructure interface {
|
type Infrastructure interface {
|
||||||
CreateNamespace(ctx context.Context, ns string) error
|
CreateNamespace(ctx context.Context, ns string) error
|
||||||
DeleteNamespace(ctx context.Context, ns string) error
|
DeleteNamespace(ctx context.Context, ns string) error
|
||||||
GenerateToken(ctx context.Context, ns string, duration int) (string, error)
|
GetToken(ctx context.Context, ns string, duration int) (string, error)
|
||||||
CreateServiceAccount(ctx context.Context, ns string) error
|
CreateServiceAccount(ctx context.Context, ns string) error
|
||||||
CreateRoleBinding(ctx context.Context, ns string, roleBinding string, role string) error
|
CreateRoleBinding(ctx context.Context, ns string, roleBinding string, role string) error
|
||||||
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)
|
|
||||||
CreateAdmiraltySource(context context.Context,executionId string) ([]byte, error)
|
|
||||||
CreateKubeconfigSecret(context context.Context,kubeconfig string, executionId string) ([]byte, error)
|
|
||||||
GetKubeconfigSecret(context context.Context,executionId string) ([]byte, error)
|
|
||||||
CreateAdmiraltyTarget(context context.Context,executionId string)([]byte,error)
|
|
||||||
GetOneNode(context context.Context,executionID string) (*v1.Node, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _service = map[string]func() (Infrastructure, error){
|
var _service = map[string]func() (Infrastructure, error){
|
||||||
@ -34,4 +26,3 @@ func NewService() (Infrastructure, error) {
|
|||||||
}
|
}
|
||||||
return service()
|
return service()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,20 +1,14 @@
|
|||||||
package infrastructure
|
package infrastructure
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"encoding/base64"
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
|
||||||
"oc-datacenter/conf"
|
"oc-datacenter/conf"
|
||||||
"strings"
|
|
||||||
|
|
||||||
authv1 "k8s.io/api/authentication/v1"
|
authv1 "k8s.io/api/authentication/v1"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
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/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
@ -48,37 +42,8 @@ func NewKubernetesService() (Infrastructure, error) {
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRemoteKubernetesService(url string, ca string, cert string, key string) (Infrastructure, error) {
|
|
||||||
decodedCa, _ := base64.StdEncoding.DecodeString(ca)
|
|
||||||
decodedCert, _ := base64.StdEncoding.DecodeString(cert)
|
|
||||||
decodedKey, _ := base64.StdEncoding.DecodeString(key)
|
|
||||||
|
|
||||||
config := &rest.Config{
|
|
||||||
Host: url + ":6443",
|
|
||||||
TLSClientConfig: rest.TLSClientConfig{
|
|
||||||
CAData: decodedCa,
|
|
||||||
CertData: decodedCert,
|
|
||||||
KeyData: decodedKey,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
// Create clientset
|
|
||||||
clientset, err := kubernetes.NewForConfig(config)
|
|
||||||
fmt.Println("NewForConfig", clientset, err)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.New("Error creating Kubernetes client: " + err.Error())
|
|
||||||
}
|
|
||||||
if clientset == nil {
|
|
||||||
return nil, errors.New("Error creating Kubernetes client: clientset is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return &KubernetesService{
|
|
||||||
Set: clientset,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesService) CreateNamespace(ctx context.Context, ns string) error {
|
func (k *KubernetesService) CreateNamespace(ctx context.Context, ns string) error {
|
||||||
// Define the namespace
|
// Define the namespace
|
||||||
fmt.Println("ExecutionID in CreateNamespace() : ", ns)
|
|
||||||
namespace := &v1.Namespace{
|
namespace := &v1.Namespace{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: ns,
|
Name: ns,
|
||||||
@ -174,10 +139,7 @@ func (k *KubernetesService) DeleteNamespace(ctx context.Context, ns string) erro
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the string representing the token generated for the serviceAccount
|
func (k *KubernetesService) GetToken(ctx context.Context, ns string, duration int) (string, error) {
|
||||||
// in the namespace identified by the value `ns` with the name sa-`ns`, which is valid for
|
|
||||||
// `duration` seconds
|
|
||||||
func (k *KubernetesService) GenerateToken(ctx context.Context, ns string, duration int) (string, error) {
|
|
||||||
// Define TokenRequest (valid for 1 hour)
|
// Define TokenRequest (valid for 1 hour)
|
||||||
d := int64(duration)
|
d := int64(duration)
|
||||||
tokenRequest := &authv1.TokenRequest{
|
tokenRequest := &authv1.TokenRequest{
|
||||||
@ -194,283 +156,3 @@ func (k *KubernetesService) GenerateToken(ctx context.Context, ns string, durati
|
|||||||
}
|
}
|
||||||
return token.Status.Token, nil
|
return token.Status.Token, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Needs refactoring :
|
|
||||||
// - 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){
|
|
||||||
|
|
||||||
var listTargets []string
|
|
||||||
resp, err := getCDRapiKube(*k.Set, ctx,"/apis/multicluster.admiralty.io/v1alpha1/targets")
|
|
||||||
if err != nil {
|
|
||||||
return nil,err
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(string(resp))
|
|
||||||
var targetDict map[string]interface{}
|
|
||||||
err = json.Unmarshal(resp,&targetDict)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("TODO: handle the error when unmarshalling k8s API response")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
b, _ := json.MarshalIndent(targetDict,""," ")
|
|
||||||
fmt.Println(string(b))
|
|
||||||
|
|
||||||
data := targetDict["items"].([]interface{})
|
|
||||||
|
|
||||||
for _, item := range data {
|
|
||||||
var metadata metav1.ObjectMeta
|
|
||||||
item := item.(map[string]interface{})
|
|
||||||
byteMetada, err := json.Marshal(item["metadata"])
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while Marshalling metadata field")
|
|
||||||
return nil,err
|
|
||||||
}
|
|
||||||
err = json.Unmarshal(byteMetada,&metadata)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while Unmarshalling metadata field to the library object")
|
|
||||||
return nil,err
|
|
||||||
}
|
|
||||||
|
|
||||||
listTargets = append(listTargets, metadata.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
return listTargets,nil
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Admiralty Target allows a cluster to deploy pods to remote cluster
|
|
||||||
//
|
|
||||||
// The remote cluster must :
|
|
||||||
//
|
|
||||||
// - have declared a Source resource
|
|
||||||
//
|
|
||||||
// - 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
|
|
||||||
func (k *KubernetesService) CreateAdmiraltyTarget(context context.Context,executionId string)([]byte,error){
|
|
||||||
exists, err := k.GetKubeconfigSecret(context,executionId)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error verifying kube-secret before creating target")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if exists == nil {
|
|
||||||
fmt.Println("Target needs to be binded to a secret in namespace ",executionId)
|
|
||||||
return nil, nil // Maybe we could create a wrapper for errors and add more info to have
|
|
||||||
}
|
|
||||||
|
|
||||||
var targetManifest string
|
|
||||||
var tpl bytes.Buffer
|
|
||||||
tmpl, err := template.New("target").
|
|
||||||
Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Target\", \"metadata\": {\"name\": \"target-{{.ExecutionId}}\"}, \"spec\": { \"kubeconfigSecret\" :{\"name\": \"kube-secret-{{.ExecutionId}}\"}} }")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error creating the template for the target Manifest")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tmpl.Execute(&tpl, map[string]string{"ExecutionId":executionId})
|
|
||||||
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
|
|
||||||
//
|
|
||||||
// The source must be associated to a serviceAccount, which will execute the pods locally.
|
|
||||||
// This serviceAccount must have sufficient permission to create and patch pods
|
|
||||||
//
|
|
||||||
// This method is temporary to implement the use of Admiralty, but must be edited
|
|
||||||
// to rather contact the oc-datacenter from the remote cluster to create the source
|
|
||||||
// locally and retrieve the token for the serviceAccount
|
|
||||||
func (k *KubernetesService) CreateAdmiraltySource(context context.Context,executionId string) ([]byte, error) {
|
|
||||||
var sourceManifest string
|
|
||||||
var tpl bytes.Buffer
|
|
||||||
tmpl, err := template.New("source").
|
|
||||||
Parse("{\"apiVersion\": \"multicluster.admiralty.io/v1alpha1\", \"kind\": \"Source\", \"metadata\": {\"name\": \"source-{{.ExecutionId}}\"}, \"spec\": {\"serviceAccountName\": \"sa-{{.ExecutionId}}\"} }")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error creating the template for the source Manifest")
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = tmpl.Execute(&tpl, map[string]string{"ExecutionId":executionId})
|
|
||||||
sourceManifest = tpl.String()
|
|
||||||
|
|
||||||
resp, err := postCDRapiKube(
|
|
||||||
*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 {
|
|
||||||
fmt.Println("Error trying to create a Source on remote cluster : ", err , " : ", resp)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
func (k *KubernetesService) CreateKubeconfigSecret(context context.Context,kubeconfig string, executionId string) ([]byte, error) {
|
|
||||||
config, err := base64.StdEncoding.DecodeString(kubeconfig)
|
|
||||||
// config, err := base64.RawStdEncoding.DecodeString(kubeconfig)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while encoding kubeconfig")
|
|
||||||
fmt.Println(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
secretManifest := &v1.Secret{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "kube-secret-" + executionId,
|
|
||||||
Namespace: executionId,
|
|
||||||
},
|
|
||||||
Data: map[string][]byte{
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
resp, err := k.Set.CoreV1().
|
|
||||||
Secrets(executionId).
|
|
||||||
Create(context,secretManifest,metav1.CreateOptions{})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error while trying to contact API to get secret kube-secret-"+executionId)
|
|
||||||
fmt.Println(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := json.Marshal(resp)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Couldn't marshal resp from : ", data)
|
|
||||||
fmt.Println(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesService) GetKubeconfigSecret(context context.Context,executionId string) ([]byte, error) {
|
|
||||||
resp, err := k.Set.CoreV1().
|
|
||||||
Secrets(executionId).
|
|
||||||
Get(context,"kube-secret-"+executionId,metav1.GetOptions{})
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if(apierrors.IsNotFound(err)){
|
|
||||||
fmt.Println("kube-secret not found for execution", executionId)
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
fmt.Println("Error while trying to contact API to get secret kube-secret-"+executionId)
|
|
||||||
fmt.Println(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
data, err := json.Marshal(resp)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Couldn't marshal resp from : ", data)
|
|
||||||
fmt.Println(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return data, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *KubernetesService) DeleteKubeConfigSecret(executionID string) ([]byte, error){
|
|
||||||
|
|
||||||
return []byte{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCDRapiKube(client kubernetes.Clientset, ctx context.Context, path string) ([]byte,error) {
|
|
||||||
resp, err := client.RESTClient().Get().
|
|
||||||
AbsPath(path).
|
|
||||||
DoRaw(ctx) // from https://stackoverflow.com/questions/60764908/how-to-access-kubernetes-crd-using-client-go
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error from k8s API when getting " + path + " : " , err)
|
|
||||||
return nil,err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func postCDRapiKube(client kubernetes.Clientset, ctx context.Context, path string, body []byte, params ...map[string]string) ([]byte, error){
|
|
||||||
req := client.RESTClient().
|
|
||||||
Post().
|
|
||||||
AbsPath(path).
|
|
||||||
Body(body)
|
|
||||||
|
|
||||||
for _, param := range params {
|
|
||||||
for k,v := range param {
|
|
||||||
req = req.Param(k,v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := req.DoRaw(ctx)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error from k8s API when posting " + string(body) + " to " + path + " : " , err)
|
|
||||||
return nil,err
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the Kubernetes' Node object corresponding to the executionID if it exists on this host
|
|
||||||
//
|
|
||||||
// The node is created when an admiralty Target (on host) can connect to an admiralty Source (on remote)
|
|
||||||
func (k *KubernetesService) GetOneNode(context context.Context,executionID string) (*v1.Node, error) {
|
|
||||||
res, err := k.Set.CoreV1().
|
|
||||||
Nodes().
|
|
||||||
List(
|
|
||||||
context,
|
|
||||||
metav1.ListOptions{},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error getting the list of nodes from k8s API")
|
|
||||||
fmt.Println(err)
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, node := range res.Items {
|
|
||||||
if isNode := strings.Contains(node.Name,"admiralty-"+executionID+"-target-"+executionID+"-"); isNode {
|
|
||||||
return &node, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
9
main.go
9
main.go
@ -8,7 +8,6 @@ import (
|
|||||||
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"
|
||||||
beego "github.com/beego/beego/v2/server/web"
|
beego "github.com/beego/beego/v2/server/web"
|
||||||
"github.com/beego/beego/v2/server/web/filter/cors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const appname = "oc-datacenter"
|
const appname = "oc-datacenter"
|
||||||
@ -51,12 +50,6 @@ func main() {
|
|||||||
beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
|
beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger"
|
||||||
api := &tools.API{}
|
api := &tools.API{}
|
||||||
api.Discovered(beego.BeeApp.Handlers.GetAllControllerInfo())
|
api.Discovered(beego.BeeApp.Handlers.GetAllControllerInfo())
|
||||||
beego.InsertFilter("*", beego.BeforeRouter, cors.Allow(&cors.Options{
|
|
||||||
AllowAllOrigins: true,
|
|
||||||
AllowMethods: []string{"GET", "POST", "PUT", "DELETE", "OPTIONS"},
|
|
||||||
AllowHeaders: []string{"Origin", "Authorization", "Content-Type"},
|
|
||||||
ExposeHeaders: []string{"Content-Length", "Content-Type"},
|
|
||||||
AllowCredentials: true,
|
|
||||||
}))
|
|
||||||
beego.Run()
|
beego.Run()
|
||||||
}
|
}
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
package models
|
|
||||||
|
|
||||||
// KubeConfigValue is a struct used to create a kubectl configuration YAML file.
|
|
||||||
type KubeConfigValue struct {
|
|
||||||
APIVersion string `yaml:"apiVersion" json:"apiVersion"`
|
|
||||||
Kind string `yaml:"kind" json:"kind"`
|
|
||||||
Clusters []KubeconfigNamedCluster `yaml:"clusters" json:"clusters"`
|
|
||||||
Users []KubeconfigUser `yaml:"users" json:"users"`
|
|
||||||
Contexts []KubeconfigNamedContext `yaml:"contexts" json:"contexts"`
|
|
||||||
CurrentContext string `yaml:"current-context" json:"current-context"`
|
|
||||||
Preferences struct{} `yaml:"preferences" json:"preferences"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeconfigUser is a struct used to create a kubectl configuration YAML file
|
|
||||||
type KubeconfigUser struct {
|
|
||||||
Name string `yaml:"name" json:"name"`
|
|
||||||
User KubeconfigUserKeyPair `yaml:"user" json:"user"`
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeconfigUserKeyPair is a struct used to create a kubectl configuration YAML file
|
|
||||||
type KubeconfigUserKeyPair struct {
|
|
||||||
Token string `yaml:"token" json:"token"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeconfigAuthProvider is a struct used to create a kubectl authentication provider
|
|
||||||
type KubeconfigAuthProvider struct {
|
|
||||||
Name string `yaml:"name" json:"name"`
|
|
||||||
Config map[string]string `yaml:"config" json:"config"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeconfigNamedCluster is a struct used to create a kubectl configuration YAML file
|
|
||||||
type KubeconfigNamedCluster struct {
|
|
||||||
Name string `yaml:"name" json:"name"`
|
|
||||||
Cluster KubeconfigCluster `yaml:"cluster" json:"cluster"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeconfigCluster is a struct used to create a kubectl configuration YAML file
|
|
||||||
type KubeconfigCluster struct {
|
|
||||||
Server string `yaml:"server" json:"server"`
|
|
||||||
CertificateAuthorityData string `yaml:"certificate-authority-data" json:"certificate-authority-data"`
|
|
||||||
CertificateAuthority string `yaml:"certificate-authority" json:"certificate-authority"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeconfigNamedContext is a struct used to create a kubectl configuration YAML file
|
|
||||||
type KubeconfigNamedContext struct {
|
|
||||||
Name string `yaml:"name" json:"name"`
|
|
||||||
Context KubeconfigContext `yaml:"context" json:"context"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// KubeconfigContext is a struct used to create a kubectl configuration YAML file
|
|
||||||
type KubeconfigContext struct {
|
|
||||||
Cluster string `yaml:"cluster" json:"cluster"`
|
|
||||||
Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty"`
|
|
||||||
User string `yaml:"user" json:"user"`
|
|
||||||
}
|
|
BIN
oc-datacenter
BIN
oc-datacenter
Binary file not shown.
@ -7,78 +7,6 @@ import (
|
|||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "GetAdmiraltyKubeconfig",
|
|
||||||
Router: `/kubeconfig/:execution`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "GetNodeReady",
|
|
||||||
Router: `/node/:execution`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "GetKubeSecret",
|
|
||||||
Router: `/secret/:execution`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "CreateKubeSecret",
|
|
||||||
Router: `/secret/:execution`,
|
|
||||||
AllowHTTPMethods: []string{"post"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "CreateSource",
|
|
||||||
Router: `/source/:execution`,
|
|
||||||
AllowHTTPMethods: []string{"post"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "CreateAdmiraltyTarget",
|
|
||||||
Router: `/target/:execution`,
|
|
||||||
AllowHTTPMethods: []string{"post"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "GetAllTargets",
|
|
||||||
Router: `/targets`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:AdmiraltyController"],
|
|
||||||
beego.ControllerComments{
|
|
||||||
Method: "GetOneTarget",
|
|
||||||
Router: `/targets/:execution`,
|
|
||||||
AllowHTTPMethods: []string{"get"},
|
|
||||||
MethodParams: param.Make(),
|
|
||||||
Filters: nil,
|
|
||||||
Params: nil})
|
|
||||||
|
|
||||||
beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"],
|
beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"] = append(beego.GlobalControllerRouter["oc-datacenter/controllers:BookingController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "GetAll",
|
Method: "GetAll",
|
||||||
|
@ -18,7 +18,6 @@ func init() {
|
|||||||
beego.NSInclude(
|
beego.NSInclude(
|
||||||
&controllers.DatacenterController{},
|
&controllers.DatacenterController{},
|
||||||
),
|
),
|
||||||
|
|
||||||
beego.NSNamespace("/session",
|
beego.NSNamespace("/session",
|
||||||
beego.NSInclude(
|
beego.NSInclude(
|
||||||
&controllers.SessionController{},
|
&controllers.SessionController{},
|
||||||
@ -34,11 +33,6 @@ func init() {
|
|||||||
&controllers.VersionController{},
|
&controllers.VersionController{},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
beego.NSNamespace("/admiralty",
|
|
||||||
beego.NSInclude(
|
|
||||||
&controllers.AdmiraltyController{},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
beego.AddNamespace(ns)
|
beego.AddNamespace(ns)
|
||||||
|
BIN
swagger/favicon-16x16.png
Normal file
BIN
swagger/favicon-16x16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 665 B |
BIN
swagger/favicon-32x32.png
Normal file
BIN
swagger/favicon-32x32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 628 B |
60
swagger/index.html
Normal file
60
swagger/index.html
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<!-- HTML for static distribution bundle build -->
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Swagger UI</title>
|
||||||
|
<link rel="stylesheet" type="text/css" href="./swagger-ui.css" />
|
||||||
|
<link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32" />
|
||||||
|
<link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16" />
|
||||||
|
<style>
|
||||||
|
html
|
||||||
|
{
|
||||||
|
box-sizing: border-box;
|
||||||
|
overflow: -moz-scrollbars-vertical;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
*,
|
||||||
|
*:before,
|
||||||
|
*:after
|
||||||
|
{
|
||||||
|
box-sizing: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
margin:0;
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="swagger-ui"></div>
|
||||||
|
|
||||||
|
<script src="./swagger-ui-bundle.js" charset="UTF-8"> </script>
|
||||||
|
<script src="./swagger-ui-standalone-preset.js" charset="UTF-8"> </script>
|
||||||
|
<script>
|
||||||
|
window.onload = function() {
|
||||||
|
// Begin Swagger UI call region
|
||||||
|
const ui = SwaggerUIBundle({
|
||||||
|
url: "swagger.json",
|
||||||
|
dom_id: '#swagger-ui',
|
||||||
|
deepLinking: true,
|
||||||
|
presets: [
|
||||||
|
SwaggerUIBundle.presets.apis,
|
||||||
|
SwaggerUIStandalonePreset
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
SwaggerUIBundle.plugins.DownloadUrl
|
||||||
|
],
|
||||||
|
layout: "StandaloneLayout"
|
||||||
|
});
|
||||||
|
// End Swagger UI call region
|
||||||
|
|
||||||
|
window.ui = ui;
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
79
swagger/oauth2-redirect.html
Normal file
79
swagger/oauth2-redirect.html
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en-US">
|
||||||
|
<head>
|
||||||
|
<title>Swagger UI: OAuth2 Redirect</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
'use strict';
|
||||||
|
function run () {
|
||||||
|
var oauth2 = window.opener.swaggerUIRedirectOauth2;
|
||||||
|
var sentState = oauth2.state;
|
||||||
|
var redirectUrl = oauth2.redirectUrl;
|
||||||
|
var isValid, qp, arr;
|
||||||
|
|
||||||
|
if (/code|token|error/.test(window.location.hash)) {
|
||||||
|
qp = window.location.hash.substring(1);
|
||||||
|
} else {
|
||||||
|
qp = location.search.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
arr = qp.split("&");
|
||||||
|
arr.forEach(function (v,i,_arr) { _arr[i] = '"' + v.replace('=', '":"') + '"';});
|
||||||
|
qp = qp ? JSON.parse('{' + arr.join() + '}',
|
||||||
|
function (key, value) {
|
||||||
|
return key === "" ? value : decodeURIComponent(value);
|
||||||
|
}
|
||||||
|
) : {};
|
||||||
|
|
||||||
|
isValid = qp.state === sentState;
|
||||||
|
|
||||||
|
if ((
|
||||||
|
oauth2.auth.schema.get("flow") === "accessCode" ||
|
||||||
|
oauth2.auth.schema.get("flow") === "authorizationCode" ||
|
||||||
|
oauth2.auth.schema.get("flow") === "authorization_code"
|
||||||
|
) && !oauth2.auth.code) {
|
||||||
|
if (!isValid) {
|
||||||
|
oauth2.errCb({
|
||||||
|
authId: oauth2.auth.name,
|
||||||
|
source: "auth",
|
||||||
|
level: "warning",
|
||||||
|
message: "Authorization may be unsafe, passed state was changed in server Passed state wasn't returned from auth server"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qp.code) {
|
||||||
|
delete oauth2.state;
|
||||||
|
oauth2.auth.code = qp.code;
|
||||||
|
oauth2.callback({auth: oauth2.auth, redirectUrl: redirectUrl});
|
||||||
|
} else {
|
||||||
|
let oauthErrorMsg;
|
||||||
|
if (qp.error) {
|
||||||
|
oauthErrorMsg = "["+qp.error+"]: " +
|
||||||
|
(qp.error_description ? qp.error_description+ ". " : "no accessCode received from the server. ") +
|
||||||
|
(qp.error_uri ? "More info: "+qp.error_uri : "");
|
||||||
|
}
|
||||||
|
|
||||||
|
oauth2.errCb({
|
||||||
|
authId: oauth2.auth.name,
|
||||||
|
source: "auth",
|
||||||
|
level: "error",
|
||||||
|
message: oauthErrorMsg || "[Authorization failed]: no accessCode received from the server"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
oauth2.callback({auth: oauth2.auth, token: qp, isValid: isValid, redirectUrl: redirectUrl});
|
||||||
|
}
|
||||||
|
window.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState !== 'loading') {
|
||||||
|
run();
|
||||||
|
} else {
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
run();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
3
swagger/swagger-ui-bundle.js
Normal file
3
swagger/swagger-ui-bundle.js
Normal file
File diff suppressed because one or more lines are too long
1
swagger/swagger-ui-bundle.js.map
Normal file
1
swagger/swagger-ui-bundle.js.map
Normal file
File diff suppressed because one or more lines are too long
2
swagger/swagger-ui-es-bundle-core.js
Normal file
2
swagger/swagger-ui-es-bundle-core.js
Normal file
File diff suppressed because one or more lines are too long
3
swagger/swagger-ui-es-bundle.js
Normal file
3
swagger/swagger-ui-es-bundle.js
Normal file
File diff suppressed because one or more lines are too long
3
swagger/swagger-ui-standalone-preset.js
Normal file
3
swagger/swagger-ui-standalone-preset.js
Normal file
File diff suppressed because one or more lines are too long
1
swagger/swagger-ui-standalone-preset.js.map
Normal file
1
swagger/swagger-ui-standalone-preset.js.map
Normal file
File diff suppressed because one or more lines are too long
4
swagger/swagger-ui.css
Normal file
4
swagger/swagger-ui.css
Normal file
File diff suppressed because one or more lines are too long
1
swagger/swagger-ui.css.map
Normal file
1
swagger/swagger-ui.css.map
Normal file
File diff suppressed because one or more lines are too long
2
swagger/swagger-ui.js
Normal file
2
swagger/swagger-ui.js
Normal file
File diff suppressed because one or more lines are too long
1
swagger/swagger-ui.js.map
Normal file
1
swagger/swagger-ui.js.map
Normal file
File diff suppressed because one or more lines are too long
368
swagger/swagger.json
Normal file
368
swagger/swagger.json
Normal file
@ -0,0 +1,368 @@
|
|||||||
|
{
|
||||||
|
"swagger": "2.0",
|
||||||
|
"info": {
|
||||||
|
"title": "oc-datacenter",
|
||||||
|
"description": "Monitor owned datacenter activity\n",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"termsOfService": "http://cloud.o-forge.io/",
|
||||||
|
"contact": {
|
||||||
|
"email": "admin@o-cloud.io"
|
||||||
|
},
|
||||||
|
"license": {
|
||||||
|
"name": "AGPL",
|
||||||
|
"url": "https://www.gnu.org/licenses/agpl-3.0.html"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"basePath": "/oc/",
|
||||||
|
"paths": {
|
||||||
|
"/": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"oc-datacenter/controllersDatacenterController"
|
||||||
|
],
|
||||||
|
"description": "find booking by id\n\u003cbr\u003e",
|
||||||
|
"operationId": "DatacenterController.GetAll",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "is_draft",
|
||||||
|
"description": "draft wished",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{booking} models.booking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/booking/": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"booking"
|
||||||
|
],
|
||||||
|
"description": "find booking by id\n\u003cbr\u003e",
|
||||||
|
"operationId": "BookingController.GetAll",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "is_draft",
|
||||||
|
"description": "draft wished",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{booking} models.booking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"tags": [
|
||||||
|
"booking"
|
||||||
|
],
|
||||||
|
"description": "create booking\n\u003cbr\u003e",
|
||||||
|
"operationId": "BookingController.Post.",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "booking",
|
||||||
|
"description": "the booking you want to post",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "is_draft",
|
||||||
|
"description": "draft wished",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/booking/check/{id}/{start_date}/{end_date}": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"booking"
|
||||||
|
],
|
||||||
|
"description": "check booking\n\u003cbr\u003e",
|
||||||
|
"operationId": "BookingController.Check",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "id of the datacenter",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "start_date",
|
||||||
|
"description": "2006-01-02T15:04:05",
|
||||||
|
"type": "string",
|
||||||
|
"default": "the booking start date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "end_date",
|
||||||
|
"description": "2006-01-02T15:04:05",
|
||||||
|
"type": "string",
|
||||||
|
"default": "the booking end date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "is_draft",
|
||||||
|
"description": "draft wished",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/booking/search/execution/{id}": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"booking"
|
||||||
|
],
|
||||||
|
"description": "search bookings by execution\n\u003cbr\u003e",
|
||||||
|
"operationId": "BookingController.Search",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "id execution",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "is_draft",
|
||||||
|
"description": "draft wished",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{workspace} models.workspace"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/booking/search/{start_date}/{end_date}": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"booking"
|
||||||
|
],
|
||||||
|
"description": "search bookings\n\u003cbr\u003e",
|
||||||
|
"operationId": "BookingController.Search",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "start_date",
|
||||||
|
"description": "the word search you want to get",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "end_date",
|
||||||
|
"description": "the word search you want to get",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "is_draft",
|
||||||
|
"description": "draft wished",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{workspace} models.workspace"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/booking/{id}": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"booking"
|
||||||
|
],
|
||||||
|
"description": "find booking by id\n\u003cbr\u003e",
|
||||||
|
"operationId": "BookingController.Get",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "the id you want to get",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{booking} models.booking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"put": {
|
||||||
|
"tags": [
|
||||||
|
"booking"
|
||||||
|
],
|
||||||
|
"description": "create computes\n\u003cbr\u003e",
|
||||||
|
"operationId": "BookingController.Update",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "the compute id you want to get",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "body",
|
||||||
|
"name": "body",
|
||||||
|
"description": "The compute content",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/models.compute"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{compute} models.compute"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/session/token/{id}/{duration}": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"session"
|
||||||
|
],
|
||||||
|
"description": "find booking by id\n\u003cbr\u003e",
|
||||||
|
"operationId": "SessionController.GetToken",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "id of the datacenter",
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "duration",
|
||||||
|
"description": "duration of the token",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{booking} models.booking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/version/": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"version"
|
||||||
|
],
|
||||||
|
"description": "get version\n\u003cbr\u003e",
|
||||||
|
"operationId": "VersionController.GetAll",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/version/status": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"version"
|
||||||
|
],
|
||||||
|
"description": "get status\n\u003cbr\u003e",
|
||||||
|
"operationId": "VersionController.Status",
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/{id}": {
|
||||||
|
"get": {
|
||||||
|
"tags": [
|
||||||
|
"oc-datacenter/controllersDatacenterController"
|
||||||
|
],
|
||||||
|
"description": "find booking by id\n\u003cbr\u003e",
|
||||||
|
"operationId": "DatacenterController.Get",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "id",
|
||||||
|
"description": "the id you want to get",
|
||||||
|
"required": true,
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"in": "query",
|
||||||
|
"name": "is_draft",
|
||||||
|
"description": "draft wished",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "{booking} models.booking"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"definitions": {
|
||||||
|
"models.compute": {
|
||||||
|
"title": "compute",
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
|
"models.object": {
|
||||||
|
"title": "object",
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tags": [
|
||||||
|
{
|
||||||
|
"name": "oc-datacenter/controllersDatacenterController",
|
||||||
|
"description": "Operations about workspace\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "booking",
|
||||||
|
"description": "Operations about workspace\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "version",
|
||||||
|
"description": "VersionController operations for Version\n"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
268
swagger/swagger.yml
Normal file
268
swagger/swagger.yml
Normal file
@ -0,0 +1,268 @@
|
|||||||
|
swagger: "2.0"
|
||||||
|
info:
|
||||||
|
title: oc-datacenter
|
||||||
|
description: |
|
||||||
|
Monitor owned datacenter activity
|
||||||
|
version: 1.0.0
|
||||||
|
termsOfService: http://cloud.o-forge.io/
|
||||||
|
contact:
|
||||||
|
email: admin@o-cloud.io
|
||||||
|
license:
|
||||||
|
name: AGPL
|
||||||
|
url: https://www.gnu.org/licenses/agpl-3.0.html
|
||||||
|
basePath: /oc/
|
||||||
|
paths:
|
||||||
|
/:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- oc-datacenter/controllersDatacenterController
|
||||||
|
description: |-
|
||||||
|
find booking by id
|
||||||
|
<br>
|
||||||
|
operationId: DatacenterController.GetAll
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: is_draft
|
||||||
|
description: draft wished
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{booking} models.booking'
|
||||||
|
/{id}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- oc-datacenter/controllersDatacenterController
|
||||||
|
description: |-
|
||||||
|
find booking by id
|
||||||
|
<br>
|
||||||
|
operationId: DatacenterController.Get
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: the id you want to get
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: is_draft
|
||||||
|
description: draft wished
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{booking} models.booking'
|
||||||
|
/booking/:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- booking
|
||||||
|
description: |-
|
||||||
|
find booking by id
|
||||||
|
<br>
|
||||||
|
operationId: BookingController.GetAll
|
||||||
|
parameters:
|
||||||
|
- in: query
|
||||||
|
name: is_draft
|
||||||
|
description: draft wished
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{booking} models.booking'
|
||||||
|
post:
|
||||||
|
tags:
|
||||||
|
- booking
|
||||||
|
description: |-
|
||||||
|
create booking
|
||||||
|
<br>
|
||||||
|
operationId: BookingController.Post.
|
||||||
|
parameters:
|
||||||
|
- in: body
|
||||||
|
name: booking
|
||||||
|
description: the booking you want to post
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: is_draft
|
||||||
|
description: draft wished
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: ""
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.object'
|
||||||
|
/booking/{id}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- booking
|
||||||
|
description: |-
|
||||||
|
find booking by id
|
||||||
|
<br>
|
||||||
|
operationId: BookingController.Get
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: the id you want to get
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{booking} models.booking'
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- booking
|
||||||
|
description: |-
|
||||||
|
create computes
|
||||||
|
<br>
|
||||||
|
operationId: BookingController.Update
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: the compute id you want to get
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: body
|
||||||
|
name: body
|
||||||
|
description: The compute content
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.compute'
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{compute} models.compute'
|
||||||
|
/booking/check/{id}/{start_date}/{end_date}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- booking
|
||||||
|
description: |-
|
||||||
|
check booking
|
||||||
|
<br>
|
||||||
|
operationId: BookingController.Check
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: id of the datacenter
|
||||||
|
type: string
|
||||||
|
- in: path
|
||||||
|
name: start_date
|
||||||
|
description: 2006-01-02T15:04:05
|
||||||
|
type: string
|
||||||
|
default: the booking start date
|
||||||
|
- in: path
|
||||||
|
name: end_date
|
||||||
|
description: 2006-01-02T15:04:05
|
||||||
|
type: string
|
||||||
|
default: the booking end date
|
||||||
|
- in: query
|
||||||
|
name: is_draft
|
||||||
|
description: draft wished
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: ""
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/models.object'
|
||||||
|
/booking/search/{start_date}/{end_date}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- booking
|
||||||
|
description: |-
|
||||||
|
search bookings
|
||||||
|
<br>
|
||||||
|
operationId: BookingController.Search
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: start_date
|
||||||
|
description: the word search you want to get
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: path
|
||||||
|
name: end_date
|
||||||
|
description: the word search you want to get
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: is_draft
|
||||||
|
description: draft wished
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{workspace} models.workspace'
|
||||||
|
/booking/search/execution/{id}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- booking
|
||||||
|
description: |-
|
||||||
|
search bookings by execution
|
||||||
|
<br>
|
||||||
|
operationId: BookingController.Search
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: id execution
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
- in: query
|
||||||
|
name: is_draft
|
||||||
|
description: draft wished
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{workspace} models.workspace'
|
||||||
|
/session/token/{id}/{duration}:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- session
|
||||||
|
description: |-
|
||||||
|
find booking by id
|
||||||
|
<br>
|
||||||
|
operationId: SessionController.GetToken
|
||||||
|
parameters:
|
||||||
|
- in: path
|
||||||
|
name: id
|
||||||
|
description: id of the datacenter
|
||||||
|
type: string
|
||||||
|
- in: path
|
||||||
|
name: duration
|
||||||
|
description: duration of the token
|
||||||
|
type: string
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: '{booking} models.booking'
|
||||||
|
/version/:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- version
|
||||||
|
description: |-
|
||||||
|
get version
|
||||||
|
<br>
|
||||||
|
operationId: VersionController.GetAll
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: ""
|
||||||
|
/version/status:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- version
|
||||||
|
description: |-
|
||||||
|
get status
|
||||||
|
<br>
|
||||||
|
operationId: VersionController.Status
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: ""
|
||||||
|
definitions:
|
||||||
|
models.compute:
|
||||||
|
title: compute
|
||||||
|
type: object
|
||||||
|
models.object:
|
||||||
|
title: object
|
||||||
|
type: object
|
||||||
|
tags:
|
||||||
|
- name: oc-datacenter/controllersDatacenterController
|
||||||
|
description: |
|
||||||
|
Operations about workspace
|
||||||
|
- name: booking
|
||||||
|
description: |
|
||||||
|
Operations about workspace
|
||||||
|
- name: version
|
||||||
|
description: |
|
||||||
|
VersionController operations for Version
|
Loading…
Reference in New Issue
Block a user