diff --git a/operator/test.yaml b/operator/test.yaml index 54938655..507a1487 100644 --- a/operator/test.yaml +++ b/operator/test.yaml @@ -19,38 +19,38 @@ spec: limits: cpu: "200m" memory: "256Mi" - # env: - # - name: "REFLEX_USERNAME" - # value: "admin" - # - name: DEBUG - # value: "true" + env: + - name: "REFLEX_USERNAME" + value: "admin" + - name: DEBUG + value: "true" secrets: - name: "REFLEX_PASSWORD" value: "admin" - name: "ANOTHER_SECRET" value: "122" - # volumes: - # - name: "data" - # mountPath: "/data" - # size: "2Gi" - # storageClass: "standard" + volumes: + - name: "data" + mountPath: "/data" + size: "2Gi" + storageClass: "standard" interfaces: - name: "http" port: 80 - name: "https" port: 443 - # ingress: - # ingressClass: "nginx" - # annotations: - # nginx.ingress.kubernetes.io/rewrite-target: / - # nginx.ingress.kubernetes.io/ssl-redirect: "false" - # rules: - # - host: "reflex.oneclickapps.dev" - # path: "/test" - # tls: false - # - host: "reflex.oneclickapps.dev" - # path: "/test" - # tls: false + ingress: + ingressClass: "nginx" + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/ssl-redirect: "false" + rules: + - host: "reflex.oneclickapps.dev" + path: "/test" + tls: false + - host: "reflex.oneclickapps.dev" + path: "/test" + tls: false # - name: "https" # port: 8443 # ingress: diff --git a/ui/frontend/.gitignore b/ui/frontend/.gitignore index 6635cf55..1e744ba9 100644 --- a/ui/frontend/.gitignore +++ b/ui/frontend/.gitignore @@ -8,3 +8,4 @@ node_modules !.env.example vite.config.js.timestamp-* vite.config.ts.timestamp-* +.node-red.json diff --git a/ui/frontend/src/lib/components/base/Nav.svelte b/ui/frontend/src/lib/components/base/Nav.svelte index c7c4f1b9..18a5225d 100644 --- a/ui/frontend/src/lib/components/base/Nav.svelte +++ b/ui/frontend/src/lib/components/base/Nav.svelte @@ -51,7 +51,7 @@ Flowbite Logo - - + {/if} +
diff --git a/ui/pocketbase/pb_migrations/1701789066_created_manifests.js b/ui/pocketbase/pb_migrations/1701789066_created_manifests.js new file mode 100644 index 00000000..220c2914 --- /dev/null +++ b/ui/pocketbase/pb_migrations/1701789066_created_manifests.js @@ -0,0 +1,37 @@ +/// +migrate((db) => { + const collection = new Collection({ + "id": "a3bwaaqkbj0nfdu", + "created": "2023-12-05 15:11:06.505Z", + "updated": "2023-12-05 15:11:06.505Z", + "name": "manifests", + "type": "base", + "system": false, + "schema": [ + { + "system": false, + "id": "qze3nz4j", + "name": "json", + "type": "json", + "required": false, + "presentable": false, + "unique": false, + "options": {} + } + ], + "indexes": [], + "listRule": null, + "viewRule": null, + "createRule": null, + "updateRule": null, + "deleteRule": null, + "options": {} + }); + + return Dao(db).saveCollection(collection); +}, (db) => { + const dao = new Dao(db); + const collection = dao.findCollectionByNameOrId("a3bwaaqkbj0nfdu"); + + return dao.deleteCollection(collection); +}) diff --git a/ui/pocketbase/pb_migrations/1701789139_updated_manifests.js b/ui/pocketbase/pb_migrations/1701789139_updated_manifests.js new file mode 100644 index 00000000..b860e45a --- /dev/null +++ b/ui/pocketbase/pb_migrations/1701789139_updated_manifests.js @@ -0,0 +1,33 @@ +/// +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("a3bwaaqkbj0nfdu") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "zrqmwzee", + "name": "rollout", + "type": "relation", + "required": false, + "presentable": false, + "unique": false, + "options": { + "collectionId": "22k6ts6gvnp46mc", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": null + } + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("a3bwaaqkbj0nfdu") + + // remove + collection.schema.removeField("zrqmwzee") + + return dao.saveCollection(collection) +}) diff --git a/ui/pocketbase/pb_migrations/1701789200_updated_manifests.js b/ui/pocketbase/pb_migrations/1701789200_updated_manifests.js new file mode 100644 index 00000000..37f30444 --- /dev/null +++ b/ui/pocketbase/pb_migrations/1701789200_updated_manifests.js @@ -0,0 +1,87 @@ +/// +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("a3bwaaqkbj0nfdu") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "e70d5dls", + "name": "active", + "type": "bool", + "required": false, + "presentable": false, + "unique": false, + "options": {} + })) + + // update + collection.schema.addField(new SchemaField({ + "system": false, + "id": "zrqmwzee", + "name": "rollout", + "type": "relation", + "required": true, + "presentable": false, + "unique": false, + "options": { + "collectionId": "22k6ts6gvnp46mc", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": null + } + })) + + // update + collection.schema.addField(new SchemaField({ + "system": false, + "id": "qze3nz4j", + "name": "json", + "type": "json", + "required": true, + "presentable": false, + "unique": false, + "options": {} + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("a3bwaaqkbj0nfdu") + + // remove + collection.schema.removeField("e70d5dls") + + // update + collection.schema.addField(new SchemaField({ + "system": false, + "id": "zrqmwzee", + "name": "rollout", + "type": "relation", + "required": false, + "presentable": false, + "unique": false, + "options": { + "collectionId": "22k6ts6gvnp46mc", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": null + } + })) + + // update + collection.schema.addField(new SchemaField({ + "system": false, + "id": "qze3nz4j", + "name": "json", + "type": "json", + "required": false, + "presentable": false, + "unique": false, + "options": {} + })) + + return dao.saveCollection(collection) +}) diff --git a/ui/pocketbase/pb_migrations/1701789274_updated_manifests.js b/ui/pocketbase/pb_migrations/1701789274_updated_manifests.js new file mode 100644 index 00000000..b7c9358f --- /dev/null +++ b/ui/pocketbase/pb_migrations/1701789274_updated_manifests.js @@ -0,0 +1,63 @@ +/// +migrate((db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("a3bwaaqkbj0nfdu") + + // remove + collection.schema.removeField("e70d5dls") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "nrwdaqpz", + "name": "startDate", + "type": "date", + "required": true, + "presentable": false, + "unique": false, + "options": { + "min": "", + "max": "" + } + })) + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "grnqhwti", + "name": "endDate", + "type": "date", + "required": false, + "presentable": false, + "unique": false, + "options": { + "min": "", + "max": "" + } + })) + + return dao.saveCollection(collection) +}, (db) => { + const dao = new Dao(db) + const collection = dao.findCollectionByNameOrId("a3bwaaqkbj0nfdu") + + // add + collection.schema.addField(new SchemaField({ + "system": false, + "id": "e70d5dls", + "name": "active", + "type": "bool", + "required": false, + "presentable": false, + "unique": false, + "options": {} + })) + + // remove + collection.schema.removeField("nrwdaqpz") + + // remove + collection.schema.removeField("grnqhwti") + + return dao.saveCollection(collection) +}) diff --git a/ui/pocketbase/pb_migrations/1701789313_deleted_manifests.js b/ui/pocketbase/pb_migrations/1701789313_deleted_manifests.js new file mode 100644 index 00000000..29962ddd --- /dev/null +++ b/ui/pocketbase/pb_migrations/1701789313_deleted_manifests.js @@ -0,0 +1,79 @@ +/// +migrate((db) => { + const dao = new Dao(db); + const collection = dao.findCollectionByNameOrId("a3bwaaqkbj0nfdu"); + + return dao.deleteCollection(collection); +}, (db) => { + const collection = new Collection({ + "id": "a3bwaaqkbj0nfdu", + "created": "2023-12-05 15:11:06.505Z", + "updated": "2023-12-05 15:14:34.816Z", + "name": "manifests", + "type": "base", + "system": false, + "schema": [ + { + "system": false, + "id": "zrqmwzee", + "name": "rollout", + "type": "relation", + "required": true, + "presentable": false, + "unique": false, + "options": { + "collectionId": "22k6ts6gvnp46mc", + "cascadeDelete": false, + "minSelect": null, + "maxSelect": 1, + "displayFields": null + } + }, + { + "system": false, + "id": "qze3nz4j", + "name": "json", + "type": "json", + "required": true, + "presentable": false, + "unique": false, + "options": {} + }, + { + "system": false, + "id": "nrwdaqpz", + "name": "startDate", + "type": "date", + "required": true, + "presentable": false, + "unique": false, + "options": { + "min": "", + "max": "" + } + }, + { + "system": false, + "id": "grnqhwti", + "name": "endDate", + "type": "date", + "required": false, + "presentable": false, + "unique": false, + "options": { + "min": "", + "max": "" + } + } + ], + "indexes": [], + "listRule": null, + "viewRule": null, + "createRule": null, + "updateRule": null, + "deleteRule": null, + "options": {} + }); + + return Dao(db).saveCollection(collection); +}) diff --git a/ui/pocketbase/pkg/controller/rollouts.go b/ui/pocketbase/pkg/controller/rollouts.go index 589cfb81..d1cad085 100644 --- a/ui/pocketbase/pkg/controller/rollouts.go +++ b/ui/pocketbase/pkg/controller/rollouts.go @@ -56,7 +56,7 @@ func HandleRolloutCreate(e *core.RecordCreateEvent, app *pocketbase.PocketBase) } // Delete rollout in k8s - err = k8s.DeleteRollout(project.Id, running_rollout.Id) + err = k8s.DeleteRollout(project.Id, util.StringParser(project.GetString("name")), running_rollout.Id) if err != nil { log.Println(err) return err @@ -64,7 +64,7 @@ func HandleRolloutCreate(e *core.RecordCreateEvent, app *pocketbase.PocketBase) } // Create rollout in k8s - err = k8s.CreateOrUpdateRollout(rolloutId, user, project.Id, e.Record.GetString("manifest")) + err = k8s.CreateOrUpdateRollout(rolloutId, util.StringParser(project.GetString("name")), user, project.Id, e.Record.GetString("manifest")) if err != nil { log.Println(err) return err @@ -102,7 +102,7 @@ func HandleRolloutUpdate(e *core.RecordUpdateEvent, app *pocketbase.PocketBase) // Check if endDate is set, if yes, delete rollout if e.Record.GetString("endDate") != "" { - err = k8s.DeleteRollout(project.Id, rollout.Id) + err = k8s.DeleteRollout(project.Id, util.StringParser(project.GetString("name")), rollout.Id) if err != nil { log.Println(err) return err @@ -130,7 +130,7 @@ func HandleRolloutUpdate(e *core.RecordUpdateEvent, app *pocketbase.PocketBase) } // Delete rollout in k8s - err = k8s.DeleteRollout(project.Id, running_rollout.Id) + err = k8s.DeleteRollout(project.Id, util.StringParser(project.GetString("name")), running_rollout.Id) if err != nil { log.Println(err) return err @@ -140,7 +140,7 @@ func HandleRolloutUpdate(e *core.RecordUpdateEvent, app *pocketbase.PocketBase) e.Record.Set("startDate", time.Now().UTC().Format(time.RFC3339)) // If endDate was set before, but is not set anymore, create rollout again - err = k8s.CreateOrUpdateRollout(rollout.Id, user, project.Id, e.Record.GetString("manifest")) + err = k8s.CreateOrUpdateRollout(rollout.Id, util.StringParser(project.GetString("name")), user, project.Id, e.Record.GetString("manifest")) if err != nil { log.Println(err) return err @@ -151,7 +151,7 @@ func HandleRolloutUpdate(e *core.RecordUpdateEvent, app *pocketbase.PocketBase) } else { e.Record.Set("startDate", time.Now().UTC().Format(time.RFC3339)) // Update rollout in k8s - err = k8s.CreateOrUpdateRollout(rollout.Id, user, project.Id, e.Record.GetString("manifest")) + err = k8s.CreateOrUpdateRollout(rollout.Id, util.StringParser(project.GetString("name")), user, project.Id, e.Record.GetString("manifest")) if err != nil { log.Println(err) return err @@ -177,7 +177,7 @@ func HandleRolloutDelete(e *core.RecordDeleteEvent, app *pocketbase.PocketBase) // Check if endDate is set, if no, delete rollout if rollout.GetString("endDate") == "" { - err = k8s.DeleteRollout(project.Id, rollout.Id) + err = k8s.DeleteRollout(project.Id, util.StringParser(project.GetString("name")), rollout.Id) if err != nil { log.Println(err) } @@ -187,8 +187,14 @@ func HandleRolloutDelete(e *core.RecordDeleteEvent, app *pocketbase.PocketBase) } func HandleRolloutStatus(c echo.Context, app *pocketbase.PocketBase, projectId string, rollout string) error { + // Get project + project, err := app.Dao().FindRecordById("projects", projectId) + if err != nil { + return err + } + // Get rollout status - status, err := k8s.GetRolloutStatus(projectId, rollout) + status, err := k8s.GetRolloutStatus(projectId, util.StringParser(project.GetString("name")), rollout) if err != nil { log.Println(err) return err @@ -198,8 +204,14 @@ func HandleRolloutStatus(c echo.Context, app *pocketbase.PocketBase, projectId s } func HandleRolloutMetrics(c echo.Context, app *pocketbase.PocketBase, projectId string, rollout string) error { + // Get project + project, err := app.Dao().FindRecordById("projects", projectId) + if err != nil { + return err + } + // Get rollout metrics - metrics, err := k8s.GetRolloutMetrics(projectId, rollout) + metrics, err := k8s.GetRolloutMetrics(projectId, util.StringParser(project.GetString("name")), rollout) if err != nil { log.Println(err) return err @@ -209,8 +221,14 @@ func HandleRolloutMetrics(c echo.Context, app *pocketbase.PocketBase, projectId } func HandleRolloutEvents(c echo.Context, app *pocketbase.PocketBase, projectId string, rollout string) error { + // Get project + project, err := app.Dao().FindRecordById("projects", projectId) + if err != nil { + return err + } + // Get rollout events - events, err := k8s.GetRolloutEvents(projectId, rollout) + events, err := k8s.GetRolloutEvents(projectId, util.StringParser(project.GetString("name")), rollout) if err != nil { log.Println(err) return err diff --git a/ui/pocketbase/pkg/k8s/rollout.go b/ui/pocketbase/pkg/k8s/rollout.go index 927ff4bf..f71dc13f 100644 --- a/ui/pocketbase/pkg/k8s/rollout.go +++ b/ui/pocketbase/pkg/k8s/rollout.go @@ -14,7 +14,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer/yaml" ) -func CreateOrUpdateRollout(rolloutId string, user *pb_models.Record, projectId string, manifest string) error { +func CreateOrUpdateRollout(rolloutId string, projectName string, user *pb_models.Record, projectId string, manifest string) error { if rolloutId == "" { return fmt.Errorf("rolloutId is required") } @@ -46,7 +46,7 @@ func CreateOrUpdateRollout(rolloutId string, user *pb_models.Record, projectId s } // Set the name and namespace to rolloutId and projectId - obj.SetName(rolloutId) + obj.SetName(projectName) obj.SetNamespace(projectId) // Define the GroupVersionResource for the Rollout object @@ -67,7 +67,7 @@ func CreateOrUpdateRollout(rolloutId string, user *pb_models.Record, projectId s } // Try to get the existing Rollout - existingRollout, err := DynamicClient.Resource(rolloutGVR).Namespace(projectId).Get(Ctx, rolloutId, metav1.GetOptions{}) + existingRollout, err := DynamicClient.Resource(rolloutGVR).Namespace(projectId).Get(Ctx, projectName, metav1.GetOptions{}) if err != nil { // If not found, create it _, err = DynamicClient.Resource(rolloutGVR).Namespace(projectId).Create(Ctx, obj, metav1.CreateOptions{}) @@ -88,7 +88,7 @@ func CreateOrUpdateRollout(rolloutId string, user *pb_models.Record, projectId s return nil } -func DeleteRollout(projectId string, rolloutId string) error { +func DeleteRollout(projectId string, projectName string, rolloutId string) error { // Define the GroupVersionResource for the Rollout object rolloutGVR := schema.GroupVersionResource{ Group: "one-click.io", @@ -99,7 +99,7 @@ func DeleteRollout(projectId string, rolloutId string) error { namespace := projectId // Delete the Rollout - err := DynamicClient.Resource(rolloutGVR).Namespace(namespace).Delete(Ctx, rolloutId, metav1.DeleteOptions{}) + err := DynamicClient.Resource(rolloutGVR).Namespace(namespace).Delete(Ctx, projectName, metav1.DeleteOptions{}) if err != nil { return fmt.Errorf("error deleting Rollout: %w", err) } @@ -107,7 +107,7 @@ func DeleteRollout(projectId string, rolloutId string) error { return nil } -func GetRolloutStatus(projectId string, rolloutId string) (*models.RolloutStatus, error) { +func GetRolloutStatus(projectId string, projectName string, rolloutId string) (*models.RolloutStatus, error) { // Define the GroupVersionResource for the Rollout object rolloutGVR := schema.GroupVersionResource{ Group: "one-click.io", @@ -118,7 +118,7 @@ func GetRolloutStatus(projectId string, rolloutId string) (*models.RolloutStatus namespace := projectId // Get the Rollout - rollout, err := DynamicClient.Resource(rolloutGVR).Namespace(namespace).Get(Ctx, rolloutId, metav1.GetOptions{}) + rollout, err := DynamicClient.Resource(rolloutGVR).Namespace(namespace).Get(Ctx, projectName, metav1.GetOptions{}) if err != nil { return nil, fmt.Errorf("error getting Rollout: %w", err) } @@ -139,11 +139,11 @@ func GetRolloutStatus(projectId string, rolloutId string) (*models.RolloutStatus return &rolloutStatus, nil } -func GetRolloutMetrics(projectId string, rolloutId string) (*models.PodMetricsResponse, error) { +func GetRolloutMetrics(projectId string, projectName string, rolloutId string) (*models.PodMetricsResponse, error) { // List all pods in the projectId namespaced controlled by the rolloutId deployment pods, err := Clientset.CoreV1().Pods(projectId).List(Ctx, metav1.ListOptions{ - LabelSelector: fmt.Sprintf("rollout.one-click.io/name=%s", rolloutId), + LabelSelector: fmt.Sprintf("rollout.one-click.io/name=%s", projectName), }) if err != nil { @@ -171,10 +171,10 @@ func GetRolloutMetrics(projectId string, rolloutId string) (*models.PodMetricsRe return &podMetricsResponse, nil } -func GetRolloutEvents(projectId string, rolloutId string) (*models.EventResponse, error) { +func GetRolloutEvents(projectId string, projectName string, rolloutId string) (*models.EventResponse, error) { // List all events in the projectId namespaced controlled by the rolloutId deployment events, err := Clientset.CoreV1().Events(projectId).List(Ctx, metav1.ListOptions{ - FieldSelector: fmt.Sprintf("involvedObject.name=%s", rolloutId), + FieldSelector: fmt.Sprintf("involvedObject.name=%s", projectName), }) if err != nil {