Skip to content

Commit

Permalink
Improved templates APIs (#206)
Browse files Browse the repository at this point in the history
  • Loading branch information
jakubno authored Nov 27, 2024
2 parents e64fc64 + f9e776f commit d2d0f23
Show file tree
Hide file tree
Showing 29 changed files with 1,427 additions and 90 deletions.
30 changes: 30 additions & 0 deletions packages/api/internal/api/api.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

81 changes: 42 additions & 39 deletions packages/api/internal/api/spec.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 36 additions & 0 deletions packages/api/internal/api/types.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion packages/api/internal/handlers/template_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (a *APIStore) DeleteTemplatesTemplateID(c *gin.Context, aliasOrTemplateID a
return
}

// Prepare info for rebuilding env
// Prepare info for deleting env
userID, teams, err := a.GetUserAndTeams(c)
if err != nil {
a.sendAPIStoreError(c, http.StatusInternalServerError, fmt.Sprintf("Error when getting default team: %s", err))
Expand Down
1 change: 1 addition & 0 deletions packages/api/internal/handlers/template_request_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ func (a *APIStore) TemplateRequestBuild(c *gin.Context, templateID api.TemplateI
Create().
SetID(templateID).
SetTeamID(team.ID).
SetCreatedBy(*userID).
SetPublic(false).
OnConflictColumns(env.FieldID).
UpdateUpdatedAt().
Expand Down
124 changes: 124 additions & 0 deletions packages/api/internal/handlers/template_update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
package handlers

import (
"fmt"
"net/http"

"github.com/gin-gonic/gin"
"go.opentelemetry.io/otel/attribute"

"github.com/e2b-dev/infra/packages/api/internal/api"
"github.com/e2b-dev/infra/packages/api/internal/utils"
"github.com/e2b-dev/infra/packages/shared/pkg/db"
"github.com/e2b-dev/infra/packages/shared/pkg/id"
"github.com/e2b-dev/infra/packages/shared/pkg/models"
"github.com/e2b-dev/infra/packages/shared/pkg/models/env"
"github.com/e2b-dev/infra/packages/shared/pkg/models/envalias"
"github.com/e2b-dev/infra/packages/shared/pkg/telemetry"
)

// PatchTemplatesTemplateID serves to update a template
func (a *APIStore) PatchTemplatesTemplateID(c *gin.Context, aliasOrTemplateID api.TemplateID) {
ctx := c.Request.Context()

body, err := utils.ParseBody[api.TemplateUpdateRequest](ctx, c)
if err != nil {
a.sendAPIStoreError(c, http.StatusBadRequest, fmt.Sprintf("Invalid request body: %s", err))

return
}

cleanedAliasOrEnvID, err := id.CleanEnvID(aliasOrTemplateID)
if err != nil {
a.sendAPIStoreError(c, http.StatusBadRequest, fmt.Sprintf("Invalid env ID: %s", aliasOrTemplateID))

err = fmt.Errorf("invalid env ID: %w", err)
telemetry.ReportCriticalError(ctx, err)

return
}

// Prepare info for updating env
userID, teams, err := a.GetUserAndTeams(c)
if err != nil {
a.sendAPIStoreError(c, http.StatusInternalServerError, fmt.Sprintf("Error when getting default team: %s", err))

err = fmt.Errorf("error when getting default team: %w", err)
telemetry.ReportCriticalError(ctx, err)

return
}

template, err := a.db.
Client.
Env.
Query().
Where(
env.Or(
env.HasEnvAliasesWith(envalias.ID(aliasOrTemplateID)),
env.ID(aliasOrTemplateID),
),
).Only(ctx)

notFound := models.IsNotFound(err)
if notFound {
telemetry.ReportError(ctx, fmt.Errorf("template '%s' not found", aliasOrTemplateID))
a.sendAPIStoreError(c, http.StatusNotFound, fmt.Sprintf("the sandbox template '%s' wasn't found", cleanedAliasOrEnvID))

return
} else if err != nil {
telemetry.ReportError(ctx, fmt.Errorf("failed to get env '%s': %w", aliasOrTemplateID, err))
a.sendAPIStoreError(c, http.StatusInternalServerError, "Error when getting env")

return
}

var team *models.Team
for _, t := range teams {
if t.ID == template.TeamID {
team = t
break
}
}

if team == nil {
errMsg := fmt.Errorf("user '%s' doesn't have access to the sandbox template '%s'", userID, cleanedAliasOrEnvID)
telemetry.ReportError(ctx, errMsg)

a.sendAPIStoreError(c, http.StatusForbidden, fmt.Sprintf("You (%s) don't have access to sandbox template '%s'", userID, cleanedAliasOrEnvID))

return
}

// Update env
dbErr := a.db.UpdateEnv(ctx, template.ID, db.UpdateEnvInput{
Public: *body.Public,
})

if dbErr != nil {
errMsg := fmt.Errorf("error when updating env: %w", dbErr)
telemetry.ReportError(ctx, errMsg)

a.sendAPIStoreError(c, http.StatusInternalServerError, "Error when updating env")
return
}

telemetry.SetAttributes(ctx,
attribute.String("user.id", userID.String()),
attribute.String("env.team.id", team.ID.String()),
attribute.String("env.team.name", team.Name),
attribute.String("env.id", template.ID),
)

a.templateCache.Invalidate(template.ID)

telemetry.ReportEvent(ctx, "updated env")

properties := a.posthog.GetPackageToPosthogProperties(&c.Request.Header)
a.posthog.IdentifyAnalyticsTeam(team.ID.String(), team.Name)
a.posthog.CreateAnalyticsUserEvent(userID.String(), team.ID.String(), "updated environment", properties.Set("environment", template.ID))

a.logger.Infof("Updated env '%s' from team '%s'", template.ID, team.ID)

c.JSON(http.StatusOK, nil)
}
26 changes: 20 additions & 6 deletions packages/api/internal/handlers/templates_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,27 @@ func (a *APIStore) GetTemplates(c *gin.Context, params api.GetTemplatesParams) {

templates := make([]*api.Template, 0, len(envs))
for _, item := range envs {
var createdBy *api.TeamUser
if item.CreatedBy != nil {
createdBy = &api.TeamUser{
Id: item.CreatedBy.Id,
Email: item.CreatedBy.Email,
}
}

templates = append(templates, &api.Template{
TemplateID: item.TemplateID,
BuildID: item.BuildID,
CpuCount: int32(item.VCPU),
MemoryMB: int32(item.RAMMB),
Public: item.Public,
Aliases: item.Aliases,
TemplateID: item.TemplateID,
BuildID: item.BuildID,
CpuCount: int32(item.VCPU),
MemoryMB: int32(item.RAMMB),
Public: item.Public,
Aliases: item.Aliases,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
LastSpawnedAt: item.LastSpawnedAt,
SpawnCount: item.SpawnCount,
BuildCount: item.BuildCount,
CreatedBy: createdBy,
})
}

Expand Down
Loading

0 comments on commit d2d0f23

Please sign in to comment.