Skip to content

Commit

Permalink
Merge pull request #21 from natrontech/landingpage
Browse files Browse the repository at this point in the history
Restructure Code
  • Loading branch information
janlauber authored Aug 15, 2023
2 parents a5afdf7 + c9b6769 commit 32dee87
Show file tree
Hide file tree
Showing 16 changed files with 452 additions and 401 deletions.
2 changes: 2 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ WORKDIR /build
COPY kubelab-backend/go.mod kubelab-backend/go.sum kubelab-backend/main.go ./
COPY kubelab-backend/hooks ./hooks
COPY kubelab-backend/pkg ./pkg
COPY kubelab-backend/vcluster-values.yaml ./vcluster-values.yaml
RUN apk --no-cache add upx make git gcc libtool musl-dev ca-certificates dumb-init \
&& go mod tidy \
&& CGO_ENABLED=0 go build \
Expand All @@ -20,6 +21,7 @@ RUN npm run build
FROM alpine as runtime
WORKDIR /app/kubelab
COPY --from=backend-builder /build/kubelab /app/kubelab/kubelab
COPY --from=backend-builder /build/vcluster-values.yaml /app/kubelab/vcluster-values.yaml
COPY ./kubelab-backend/pb_migrations ./pb_migrations
COPY --from=ui-builder /build/build /app/kubelab/pb_public
EXPOSE 8090
Expand Down
2 changes: 1 addition & 1 deletion kubelab-backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
/pb_data
/tmp
/bin
kubelab
./pocketbase
kubelab
4 changes: 2 additions & 2 deletions kubelab-backend/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ go 1.20
require (
github.com/caarlos0/env/v8 v8.0.0
github.com/pocketbase/dbx v1.10.0
github.com/pocketbase/pocketbase v0.17.4
gopkg.in/yaml.v2 v2.4.0
github.com/pocketbase/pocketbase v0.17.5
helm.sh/helm/v3 v3.11.2
k8s.io/api v0.27.2
k8s.io/apimachinery v0.27.2
Expand Down Expand Up @@ -101,6 +100,7 @@ require (
google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230807174057-1744710a1577 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/apiextensions-apiserver v0.26.3 // indirect
k8s.io/apiserver v0.26.3 // indirect
Expand Down
4 changes: 2 additions & 2 deletions kubelab-backend/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -600,8 +600,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pocketbase/dbx v1.10.0 h1:58VIT7r6T+BnVbYVosvGBsPjQEic3/VFRYGT823vWSQ=
github.com/pocketbase/dbx v1.10.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
github.com/pocketbase/pocketbase v0.17.4 h1:PwT84MMoXPVdv/EC/dfanCsqfByY1xMNlaNWvlM5MfY=
github.com/pocketbase/pocketbase v0.17.4/go.mod h1:IqsgywiDX5ewaUdeG+0NNckBLWp5mFhJSca1PH9zSp4=
github.com/pocketbase/pocketbase v0.17.5 h1:3KwMrlSMt1rcwZK2Z1/wFa5p/rkDHpcyeCRvUDXMb+Y=
github.com/pocketbase/pocketbase v0.17.5/go.mod h1:IqsgywiDX5ewaUdeG+0NNckBLWp5mFhJSca1PH9zSp4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/poy/onpar v0.0.0-20200406201722-06f95a1c68e8/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU=
Expand Down
277 changes: 6 additions & 271 deletions kubelab-backend/main.go
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
package main

import (
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
"time"

"github.com/natrontech/kubelab/hooks"
"github.com/natrontech/kubelab/pkg/controller"
"github.com/natrontech/kubelab/pkg/env"
"github.com/natrontech/kubelab/pkg/helm"
"github.com/natrontech/kubelab/pkg/k8s"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/apis"
"github.com/pocketbase/pocketbase/core"
"github.com/pocketbase/pocketbase/models"
"github.com/pocketbase/pocketbase/plugins/jsvm"
"github.com/pocketbase/pocketbase/plugins/migratecmd"
"gopkg.in/yaml.v2"
v1 "k8s.io/api/core/v1"
)

func defaultPublicDir() string {
Expand Down Expand Up @@ -76,271 +70,12 @@ func main() {
})

app.OnRecordBeforeUpdateRequest().Add(func(e *core.RecordUpdateEvent) error {
// check collection name
if e.Collection.Name == "lab_sessions" {
if e.Record.GetBool("clusterRunning") {

// deploy a new vcluster
helmclient, err := helm.CreateHelmClient(e.Record.GetString("lab"), e.Record.GetString("user"))
if err != nil {
log.Println(err)
return err
}

err = helm.AddHelmRepositoryToClient(helmclient, "loft-sh", "https://charts.loft.sh")
if err != nil {
log.Println(err)
return err
}

// create yaml struct
yamlValues := struct {
Sync struct {
PersistentVolumes struct {
Enabled bool `yaml:"enabled"`
} `yaml:"persistentvolumes"`
StorageClasses struct {
Enabled bool `yaml:"enabled"`
} `yaml:"storageclasses"`
Ingresses struct {
Enabled bool `yaml:"enabled"`
} `yaml:"ingresses"`
HostStorageClasses struct {
Enabled bool `yaml:"enabled"`
} `yaml:"hoststorageclasses"`
} `yaml:"sync"`
Storage struct {
Persistence bool `yaml:"persistence"`
} `yaml:"storage"`
Isolation struct {
Enabled bool `yaml:"enabled"`
PodSecurityStandard string `yaml:"podSecurityStandard"`
NodeProxyPermission struct {
Enabled bool `yaml:"enabled"`
} `yaml:"nodeProxyPermission"`
ResourceQuota struct {
Enabled bool `yaml:"enabled"`
} `yaml:"resourceQuota"`
LimitRange struct {
Enabled bool `yaml:"enabled"`
Default map[string]string `yaml:"default"`
DefaultRequest map[string]string `yaml:"defaultRequest"`
} `yaml:"limitRange"`
NetworkPolicy struct {
Enabled bool `yaml:"enabled"`
OutgoingConnections struct {
IPBlock struct {
CIDR string `yaml:"cidr"`
Except []string `yaml:"except"`
} `yaml:"ipBlock"`
} `yaml:"outgoingConnections"`
} `yaml:"networkPolicy"`
} `yaml:"isolation"`
}{}

// set values
yamlValues.Sync.PersistentVolumes.Enabled = true
yamlValues.Sync.StorageClasses.Enabled = false
yamlValues.Sync.Ingresses.Enabled = true
yamlValues.Sync.HostStorageClasses.Enabled = true
yamlValues.Storage.Persistence = false
yamlValues.Isolation.Enabled = true
yamlValues.Isolation.PodSecurityStandard = "baseline"
yamlValues.Isolation.NodeProxyPermission.Enabled = false
yamlValues.Isolation.ResourceQuota.Enabled = false
yamlValues.Isolation.LimitRange.Enabled = true
yamlValues.Isolation.LimitRange.Default = map[string]string{
"ephemeral-storage": "8Gi",
"memory": "512Mi",
"cpu": "1",
}
yamlValues.Isolation.LimitRange.DefaultRequest = map[string]string{
"ephemeral-storage": "3Gi",
"memory": "128Mi",
"cpu": "100m",
}
yamlValues.Isolation.NetworkPolicy.Enabled = true
yamlValues.Isolation.NetworkPolicy.OutgoingConnections.IPBlock.CIDR = "8.8.8.8/32"

// convert to yaml
yamlValuesBytes, err := yaml.Marshal(yamlValues)
if err != nil {
log.Println(err)
return err
}

_, err = helm.CreateOrUpdateHelmRelease(
helmclient,
"loft-sh/vcluster",
"vcluster",
helm.GetNamespaceName(e.Record.GetString("lab"), e.Record.GetString("user")),
"0.15.2",
string(string(yamlValuesBytes)),
)
if err != nil {
log.Println(err)
return err
}

err = k8s.CreateResourceQuota(helm.GetNamespaceName(e.Record.GetString("lab"), e.Record.GetString("user")), env.Config.ResourceName, env.Config.PodsLimit, env.Config.StorageLimit)
if err != nil {
log.Println(err)
return err
}

time.Sleep(15 * time.Second)

} else {
// delete the namespace
err := k8s.DeleteNamespace(helm.GetNamespaceName(e.Record.GetString("lab"), e.Record.GetString("user")))
if err != nil {
log.Println(err)
}

time.Sleep(15 * time.Second)
}
}

if e.Collection.Name == "exercise_sessions" {
if e.Record.GetBool("agentRunning") {
var err error
var exercise *models.Record
// retrieve the exercise
exercise, err = app.Dao().FindRecordById("exercises", e.Record.GetString("exercise"))
if err != nil {
log.Println(err)
return err
}

// check if the namespace exists
err = k8s.CreateNamespace(helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")))
if err != nil {
log.Println(err)
} else {
return err
}

// check if vcluster pod exists 'vcluster-0'
_, err = k8s.GetPodByName(helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")), "vcluster-0")
if err != nil {
log.Println(err)
return err
}

// get kubeconfig secret called 'vc-vcluster'
var secret *v1.Secret
secret, err = k8s.GetSecretByName(helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")), "vc-vcluster")
if err != nil {
log.Println(err)
return err
}

// get exercise.GetString("bootstrap") this is a url to a bootstrap script over https github raw
bootstrap, err := http.Get(exercise.GetString("bootstrap"))
if err != nil {
log.Println(err)
return err
}

defer bootstrap.Body.Close()

// read the body
bootstrapBody, err := io.ReadAll(bootstrap.Body)
if err != nil {
log.Println(err)
return err
}

check, err := http.Get(exercise.GetString("check"))
if err != nil {
log.Println(err)
return err
}

defer check.Body.Close()

// read the body
checkBody, err := io.ReadAll(check.Body)
if err != nil {
log.Println(err)
return err
}

// create a new deployment
_, err = k8s.CreateDeployment(
"kubelab-agent-"+exercise.Id,
helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")),
env.Config.KubelabImage,
1,
string(secret.Data["config"]),
string(bootstrapBody),
string(checkBody),
env.Config.AllowedHosts,
)
if err != nil {
log.Println(err)
}

// create a new service
_, err = k8s.CreateService(
helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")),
"kubelab-agent-"+exercise.Id,
8376,
)
if err != nil {
log.Println(err)
}

// create a new ingress
_, err = k8s.CreateIngress(
helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")),
"kubelab-"+exercise.GetString("lab")+"-"+exercise.Id+"-"+e.Record.GetString("user"),
env.Config.AllowedHosts,
"kubelab-agent-"+exercise.Id,
"kubelab-"+exercise.GetString("lab")+"-"+exercise.Id+"-"+e.Record.GetString("user"),
)

// check if deployment is ready
err = k8s.WaitForDeployment(helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")), "kubelab-agent-"+exercise.Id)
if err != nil {
log.Println(err)
}

// sleep for 5 seconds
time.Sleep(5 * time.Second)

} else {
var err error
var exercise *models.Record
// retrieve the exercise
exercise, err = app.Dao().FindRecordById("exercises", e.Record.GetString("exercise"))
if err != nil {
log.Println(err)
return err
}
// delete the deployment
err = k8s.DeleteDeployment(helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")), "kubelab-agent-"+exercise.Id)
if err != nil {
log.Println(err)
// return err
}

// delete the service
err = k8s.DeleteService(helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")), "kubelab-agent-"+exercise.Id)
if err != nil {
log.Println(err)
// return err
}

// delete the ingress
err = k8s.DeleteIngress(helm.GetNamespaceName(exercise.GetString("lab"), e.Record.GetString("user")), "kubelab-"+exercise.GetString("lab")+"-"+exercise.Id+"-"+e.Record.GetString("user"))
if err != nil {
log.Println(err)
// return err
}
}
switch e.Collection.Name {
case "lab_sessions":
return controller.HandleLabSessions(e, app)
case "exercise_sessions":
return controller.HandleExerciseSessions(e, app)
}

return nil
})

Expand Down
Loading

0 comments on commit 32dee87

Please sign in to comment.