Skip to content

Commit

Permalink
feat: add yatai component
Browse files Browse the repository at this point in the history
  • Loading branch information
yetone committed Aug 29, 2022
1 parent d74583c commit 552e86e
Show file tree
Hide file tree
Showing 17 changed files with 615 additions and 31 deletions.
172 changes: 172 additions & 0 deletions api-server/controllers/controllersv1/yatai_component.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
package controllersv1

import (
"context"
"strings"
"time"

"github.com/gin-gonic/gin"
"github.com/pkg/errors"

"github.com/bentoml/yatai-schemas/modelschemas"
"github.com/bentoml/yatai-schemas/schemasv1"
"github.com/bentoml/yatai/api-server/models"
"github.com/bentoml/yatai/api-server/services"
"github.com/bentoml/yatai/api-server/transformers/transformersv1"
"github.com/bentoml/yatai/common/utils"
)

type yataiComponentController struct {
baseController
}

var YataiComponentController = yataiComponentController{}

type GetYataiComponentSchema struct {
GetClusterSchema
YataiComponentName string `path:"yataiComponentName"`
}

func (s *GetYataiComponentSchema) GetYataiComponent(ctx context.Context) (*models.YataiComponent, error) {
cluster, err := s.GetCluster(ctx)
if err != nil {
return nil, errors.Wrap(err, "get cluster")
}
yataiComponent, err := services.YataiComponentService.GetByName(ctx, cluster.ID, s.YataiComponentName)
if err != nil {
return nil, errors.Wrapf(err, "get yataiComponent %s", s.YataiComponentName)
}
return yataiComponent, nil
}

func (c *yataiComponentController) canView(ctx context.Context, yataiComponent *models.YataiComponent) error {
cluster, err := services.ClusterService.GetAssociatedCluster(ctx, yataiComponent)
if err != nil {
return errors.Wrap(err, "get associated cluster")
}
return ClusterController.canView(ctx, cluster)
}

func (c *yataiComponentController) canUpdate(ctx context.Context, yataiComponent *models.YataiComponent) error {
cluster, err := services.ClusterService.GetAssociatedCluster(ctx, yataiComponent)
if err != nil {
return errors.Wrap(err, "get associated cluster")
}
return ClusterController.canUpdate(ctx, cluster)
}

func (c *yataiComponentController) canOperate(ctx context.Context, yataiComponent *models.YataiComponent) error {
cluster, err := services.ClusterService.GetAssociatedCluster(ctx, yataiComponent)
if err != nil {
return errors.Wrap(err, "get associated cluster")
}
return ClusterController.canOperate(ctx, cluster)
}

type RegisterYataiComponentSchema struct {
schemasv1.RegisterYataiComponentSchema
GetClusterSchema
}

func (c *yataiComponentController) Register(ctx *gin.Context, schema *RegisterYataiComponentSchema) (*schemasv1.YataiComponentSchema, error) {
user, err := services.GetCurrentUser(ctx)
if err != nil {
return nil, err
}
cluster, err := schema.GetCluster(ctx)
if err != nil {
return nil, err
}
if err = ClusterController.canUpdate(ctx, cluster); err != nil {
return nil, err
}

kubeNamespace := strings.TrimSpace(schema.KubeNamespace)

// nolint: ineffassign, staticcheck
_, ctx_, df, err := services.StartTransaction(ctx)
if err != nil {
return nil, err
}
defer func() { df(err) }()

yataiComponent, err := services.YataiComponentService.GetByName(ctx_, cluster.ID, string(schema.Name))
isNotFound := utils.IsNotFound(err)
if err != nil && !isNotFound {
return nil, errors.Wrap(err, "get yataiComponent")
}

if isNotFound {
yataiComponent, err = services.YataiComponentService.Create(ctx_, services.CreateYataiComponentOption{
CreatorId: user.ID,
OrganizationId: cluster.OrganizationId,
ClusterId: cluster.ID,
Name: string(schema.Name),
KubeNamespace: kubeNamespace,
Version: schema.Version,
Manifest: &modelschemas.YataiComponentManifestSchema{
SelectorLabels: schema.SelectorLabels,
},
})
} else {
manifest := &modelschemas.YataiComponentManifestSchema{
SelectorLabels: schema.SelectorLabels,
}
now := time.Now()
now_ := &now
opt := services.UpdateYataiComponentOption{
LatestHeartbeatAt: &now_,
}
if yataiComponent.Version != schema.Version {
opt.Version = &schema.Version
opt.LatestInstalledAt = &now_
opt.Manifest = &manifest
}
yataiComponent, err = services.YataiComponentService.Update(ctx_, yataiComponent, opt)
}

if err != nil {
return nil, errors.Wrap(err, "register yataiComponent")
}

yataiComponentSchema, err := transformersv1.ToYataiComponentSchema(ctx_, yataiComponent)
return yataiComponentSchema, err
}

func (c *yataiComponentController) ListAll(ctx *gin.Context, schema *GetOrganizationSchema) ([]*schemasv1.YataiComponentSchema, error) {
org, err := schema.GetOrganization(ctx)
if err != nil {
return nil, err
}
if err = OrganizationController.canView(ctx, org); err != nil {
return nil, err
}

yataiComponents, err := services.YataiComponentService.List(ctx, services.ListYataiComponentOption{
OrganizationId: &org.ID,
})
if err != nil {
return nil, err
}

return transformersv1.ToYataiComponentSchemas(ctx, yataiComponents)
}

func (c *yataiComponentController) List(ctx *gin.Context, schema *GetClusterSchema) ([]*schemasv1.YataiComponentSchema, error) {
cluster, err := schema.GetCluster(ctx)
if err != nil {
return nil, err
}
if err = ClusterController.canView(ctx, cluster); err != nil {
return nil, err
}

yataiComponents, err := services.YataiComponentService.List(ctx, services.ListYataiComponentOption{
ClusterId: &cluster.ID,
})
if err != nil {
return nil, err
}

return transformersv1.ToYataiComponentSchemas(ctx, yataiComponents)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DROP TABLE IF EXISTS `yatai_component`;
21 changes: 21 additions & 0 deletions api-server/db/migrations/000004_add_yatai_component.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
ALTER TYPE "resource_type" ADD VALUE 'yatai_component';

CREATE TABLE IF NOT EXISTS "yatai_component" (
id SERIAL PRIMARY KEY,
uid VARCHAR(32) UNIQUE NOT NULL DEFAULT generate_object_id(),
name VARCHAR(128) NOT NULL,
description TEXT,
version VARCHAR(128),
cluster_id INTEGER NOT NULL REFERENCES "cluster"("id") ON DELETE CASCADE,
organization_id INTEGER NOT NULL REFERENCES "organization"("id") ON DELETE CASCADE,
kube_namespace VARCHAR(128) NOT NULL,
manifest JSONB,
creator_id INTEGER NOT NULL REFERENCES "user"("id") ON DELETE CASCADE,
latest_heartbeat_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,
latest_installed_at TIMESTAMP WITH TIME ZONE DEFAULT NULL,
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE,
deleted_at TIMESTAMP WITH TIME ZONE
);

CREATE UNIQUE INDEX "uk_yataiComponent_clusterId_name" ON "yatai_component" ("cluster_id", "name");
25 changes: 25 additions & 0 deletions api-server/models/yatai_component.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package models

import (
"time"

"github.com/bentoml/yatai-schemas/modelschemas"
)

type YataiComponent struct {
ResourceMixin
CreatorAssociate
ClusterAssociate
OrganizationAssociate

Version string `json:"version"`
KubeNamespace string `json:"kube_namespace"`
Description string `json:"description"`
Manifest *modelschemas.YataiComponentManifestSchema `json:"manifest" type:"jsonb"`
LatestInstalledAt *time.Time `json:"latest_installed_at"`
LatestHeartbeatAt *time.Time `json:"latest_heartbeat_at"`
}

func (d *YataiComponent) GetResourceType() modelschemas.ResourceType {
return modelschemas.ResourceTypeYataiComponent
}
20 changes: 20 additions & 0 deletions api-server/routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,11 @@ func organizationRoutes(grp *fizz.RouterGroup) {
fizz.Summary("Update an organization"),
}, tonic.Handler(controllersv1.OrganizationController.Update, 200))

grp.GET("/yatai_components", []fizz.OperationOption{
fizz.ID("List organization all yatai components"),
fizz.Summary("List organization all yatai components"),
}, tonic.Handler(controllersv1.YataiComponentController.ListAll, 200))

grp.GET("/members", []fizz.OperationOption{
fizz.ID("List organization members"),
fizz.Summary("Get organization members"),
Expand Down Expand Up @@ -491,6 +496,7 @@ func clusterRoutes(grp *fizz.RouterGroup) {
fizz.Summary("Create cluster"),
}, tonic.Handler(controllersv1.ClusterController.Create, 200))

yataiComponentRoutes(resourceGrp)
deploymentRoutes(resourceGrp)
}

Expand Down Expand Up @@ -598,6 +604,20 @@ func bentoRoutes(grp *fizz.RouterGroup) {
}, tonic.Handler(controllersv1.BentoController.Create, 200))
}

func yataiComponentRoutes(grp *fizz.RouterGroup) {
grp = grp.Group("/yatai_components", "yatai components", "yatai components")

grp.GET("", []fizz.OperationOption{
fizz.ID("List yatai components"),
fizz.Summary("List yatai components"),
}, tonic.Handler(controllersv1.YataiComponentController.List, 200))

grp.POST("", []fizz.OperationOption{
fizz.ID("Register yatai component"),
fizz.Summary("Register yatai component"),
}, tonic.Handler(controllersv1.YataiComponentController.Register, 200))
}

func deploymentRoutes(grp *fizz.RouterGroup) {
namespacedGrp := grp.Group("/namespaces/:kubeNamespace/deployments", "deployments", "deployments")
grp = grp.Group("/deployments", "cluster deployments", "cluster deployments")
Expand Down
2 changes: 1 addition & 1 deletion api-server/services/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ type GetLabelByKeyOption struct {
func (s *labelService) GetByKey(ctx context.Context, opt GetLabelByKeyOption) (*models.Label, error) {
var label models.Label
query := getBaseQuery(ctx, s).
Where("organization_id = ? ", opt.OrganizationId).
Where("organization_id = ?", opt.OrganizationId).
Where("key = ?", opt.Key).
Where("resource_type = ?", opt.ResourceType).
Where("resource_id = ?", opt.ResourceId)
Expand Down
11 changes: 11 additions & 0 deletions api-server/services/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ func (m *resourceService) Get(ctx context.Context, resourceType modelschemas.Res
case modelschemas.ResourceTypeLabel:
label, err := LabelService.Get(ctx, resourceId)
return label, err
case modelschemas.ResourceTypeYataiComponent:
yataiComponent, err := YataiComponentService.Get(ctx, resourceId)
return yataiComponent, err
default:
return nil, errors.Errorf("cannot recognize this resource type: %s", resourceType)
}
Expand Down Expand Up @@ -116,6 +119,11 @@ func (m *resourceService) List(ctx context.Context, resourceType modelschemas.Re
Ids: &resourceIds,
})
return labels, err
case modelschemas.ResourceTypeYataiComponent:
yataiComponents, err := YataiComponentService.List(ctx, ListYataiComponentOption{
Ids: &resourceIds,
})
return yataiComponents, err
default:
return nil, errors.Errorf("cannot recognize this resource type: %s", resourceType)
}
Expand Down Expand Up @@ -159,6 +167,9 @@ func (m *resourceService) GetByUid(ctx context.Context, resourceType modelschema
case modelschemas.ResourceTypeLabel:
label, err := LabelService.GetByUid(ctx, resourceUid)
return label, err
case modelschemas.ResourceTypeYataiComponent:
yataiComponent, err := YataiComponentService.GetByUid(ctx, resourceUid)
return yataiComponent, err
default:
return nil, errors.Errorf("cannot recognize this resource type: %s", resourceType)
}
Expand Down
Loading

0 comments on commit 552e86e

Please sign in to comment.