Skip to content

Commit

Permalink
Merge branch 'master' into fixFormat
Browse files Browse the repository at this point in the history
  • Loading branch information
Jougan-0 committed May 25, 2024
2 parents c82c722 + c356e50 commit c619f38
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 78 deletions.
201 changes: 124 additions & 77 deletions server/handlers/meshery_pattern_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package handlers

import (
"bytes"
"context"
"database/sql"
"encoding/json"
"fmt"
Expand Down Expand Up @@ -698,67 +697,145 @@ func (h *Handler) handlePatternPOST(

}

// Verifies and converts a pattern to design format if required.
// A pattern is required to be converted to design format iff,
// 1. pattern_file attribute is empty, and
// 2. The "type" (sourcetype/original content) is not Design. [is one of compose/helmchart/manifests]

func (h *Handler) VerifyAndConvertToDesign(
ctx context.Context,
mesheryPattern *models.MesheryPattern,
func (h *Handler) HandleConversionToDesign(
rw http.ResponseWriter,
r *http.Request,
_ *models.Preference,
user *models.User,
provider models.Provider,
) error {
) {
defer func() {
_ = r.Body.Close()
}()

if mesheryPattern.Type.Valid && mesheryPattern.Type.String != string(models.Design) && mesheryPattern.PatternFile == "" {
token, _ := ctx.Value(models.TokenCtxKey).(string)
userUUID := uuid.FromStringOrNil(user.ID)
eventBuilder := events.NewEvent().FromSystem(*h.SystemID).FromUser(userUUID).WithCategory("pattern").WithAction("convert").ActedUpon(userUUID)

sourceContent, err := provider.GetDesignSourceContent(token, mesheryPattern.ID.String())
if err != nil {
return err
sourcetype := mux.Vars(r)["sourcetype"]
parsedBody := &MesheryPatternPOSTRequestBody{}
if err := json.NewDecoder(r.Body).Decode(&parsedBody); err != nil {
event := eventBuilder.WithDescription(fmt.Sprintf("Unable to convert design of type %s", sourcetype)).WithMetadata(map[string]interface{}{"err": err}).WithSeverity(events.Error).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userUUID, event)
h.log.Error(ErrRequestBody(err))
http.Error(rw, ErrRequestBody(err).Error(), http.StatusBadRequest)
}

token, _ := r.Context().Value(models.TokenCtxKey).(string)

mesheryPattern := &models.MesheryPattern{} // pattern to be saved in the database
if parsedBody.PatternData == nil {
err := ErrRequestBody(fmt.Errorf("pattern_data cannot be empty, provide a valid pattern id for conversion"))

event := eventBuilder.WithDescription(fmt.Sprintf("Unable to convert design of type %s", sourcetype)).WithMetadata(map[string]interface{}{"err": err}).WithSeverity(events.Error).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userUUID, event)

h.log.Error(err)
http.Error(rw, err.Error(), http.StatusBadRequest)
}

mesheryPattern.Name = parsedBody.PatternData.Name
mesheryPattern.ID = parsedBody.PatternData.ID

eventBuilder.ActedUpon(*mesheryPattern.ID)

if parsedBody.PatternData.Location == nil {
parsedBody.PatternData.Location = map[string]interface{}{
"host": "",
"path": "",
"type": "local",
"branch": "",
}
}

mesheryPattern.SourceContent = sourceContent
sourcetype := mesheryPattern.Type.String
sourceContent, err := provider.GetDesignSourceContent(r, mesheryPattern.ID.String())
if err != nil {
event := eventBuilder.WithDescription(fmt.Sprintf("Unable to convert design of type %s", sourcetype)).WithMetadata(map[string]interface{}{"err": err}).WithSeverity(events.Error).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userUUID, event)
h.log.Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}

if sourcetype == string(models.DockerCompose) || sourcetype == string(models.K8sManifest) {
var k8sres string
if sourcetype == string(models.DockerCompose) {
k8sres, err = kompose.Convert(sourceContent) // convert the docker compose file into kubernetes manifest
if err != nil {
err = ErrConvertingDockerComposeToDesign(err)
return err
}
mesheryPattern.SourceContent = sourceContent

} else if sourcetype == string(models.K8sManifest) {
k8sres = string(sourceContent)
}
pattern, err := pCore.NewPatternFileFromK8sManifest(k8sres, false, h.registryManager)
if sourcetype == string(models.DockerCompose) || sourcetype == string(models.K8sManifest) {
var k8sres string
if sourcetype == string(models.DockerCompose) {
k8sres, err = kompose.Convert(sourceContent) // convert the docker compose file into kubernetes manifest
if err != nil {
err = ErrConvertingK8sManifestToDesign(err)
return err
err = ErrConvertingDockerComposeToDesign(err)
event := eventBuilder.WithDescription(fmt.Sprintf("Unable to convert design of type %s", sourcetype)).WithMetadata(map[string]interface{}{"err": err}).WithSeverity(events.Error).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userUUID, event)

h.log.Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
response, err := yaml.Marshal(pattern)
if err != nil {
err = ErrMarshallingDesignIntoYAML(err)
return err
mesheryPattern.Type = sql.NullString{
String: string(models.DockerCompose),
Valid: true,
}
} else if sourcetype == string(models.K8sManifest) {
k8sres = string(sourceContent)
mesheryPattern.Type = sql.NullString{
String: string(models.K8sManifest),
Valid: true,
}
mesheryPattern.PatternFile = string(response)
}

resp, err := provider.SaveMesheryPattern(token, mesheryPattern)
pattern, err := pCore.NewPatternFileFromK8sManifest(k8sres, false, h.registryManager)
if err != nil {
obj := "save"
saveErr := ErrApplicationFailure(err, obj)
return saveErr
err = ErrConvertingK8sManifestToDesign(err)
event := eventBuilder.WithDescription(fmt.Sprintf("Unable to convert design of type %s", sourcetype)).WithMetadata(map[string]interface{}{"err": err}).WithSeverity(events.Error).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userUUID, event)

h.log.Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}
response, err := yaml.Marshal(pattern)
if err != nil {
err = ErrMarshallingDesignIntoYAML(err)
event := eventBuilder.WithDescription(fmt.Sprintf("Unable to convert design of type %s", sourcetype)).WithMetadata(map[string]interface{}{"err": err}).WithSeverity(events.Error).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userUUID, event)

contentMesheryPatternSlice := make([]models.MesheryPattern, 0)
h.log.Error((err))
http.Error(rw, err.Error(), http.StatusInternalServerError)

if err := json.Unmarshal(resp, &contentMesheryPatternSlice); err != nil {
return models.ErrUnmarshal(err, "pattern")
return
}
mesheryPattern.PatternFile = string(response)
}
return nil

resp, err := provider.SaveMesheryPattern(token, mesheryPattern)
if err != nil {
obj := "save"
saveErr := ErrApplicationFailure(err, obj)
h.log.Error(saveErr)
http.Error(rw, saveErr.Error(), http.StatusInternalServerError)
return
}

contentMesheryPatternSlice := make([]models.MesheryPattern, 0)

if err := json.Unmarshal(resp, &contentMesheryPatternSlice); err != nil {
http.Error(rw, ErrDecodePattern(err).Error(), http.StatusInternalServerError)
return
}

if len(contentMesheryPatternSlice) > 0 {
event := eventBuilder.WithDescription(fmt.Sprintf("Converted %s \"%s\" to Design format", sourcetype, contentMesheryPatternSlice[0].Name)).WithSeverity(events.Success).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userUUID, event)
}

rw.Header().Set("Content-Type", "application/json")
fmt.Fprint(rw, string(resp))
}

func unCompressOCIArtifactIntoDesign(artifact []byte) (*models.MesheryPattern, error) {
Expand Down Expand Up @@ -1136,16 +1213,6 @@ func (h *Handler) DownloadMesheryPatternHandler(
return
}

err = h.VerifyAndConvertToDesign(r.Context(), pattern, provider)
if err != nil {
event := events.NewEvent().ActedUpon(*pattern.ID).FromSystem(*h.SystemID).FromUser(userID).WithCategory("pattern").WithAction("convert").WithDescription(fmt.Sprintf("The \"%s\" is not in the design format, failed to convert and persist the original source content from \"%s\" to design file format", pattern.Name, pattern.Type.String)).WithMetadata(map[string]interface{}{"error": err}).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userID, event)
h.log.Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}

if ociFormat {
tmpDir, err := oci.CreateTempOCIContentDir()
if err != nil {
Expand Down Expand Up @@ -1553,11 +1620,10 @@ func (h *Handler) GetMesheryPatternHandler(
rw http.ResponseWriter,
r *http.Request,
_ *models.Preference,
user *models.User,
_ *models.User,
provider models.Provider,
) {
patternID := mux.Vars(r)["id"]
userID := uuid.FromStringOrNil(user.ID)

resp, err := provider.GetMesheryPattern(r, patternID, r.URL.Query().Get("metrics"))
if err != nil {
Expand All @@ -1566,23 +1632,6 @@ func (h *Handler) GetMesheryPatternHandler(
return
}

pattern := &models.MesheryPattern{}
err = json.Unmarshal(resp, &pattern)
if err != nil {
h.log.Error(ErrGetPattern(err))
http.Error(rw, ErrGetPattern(err).Error(), http.StatusInternalServerError)
return
}
err = h.VerifyAndConvertToDesign(r.Context(), pattern, provider)
if err != nil {
event := events.NewEvent().ActedUpon(*pattern.ID).FromSystem(*h.SystemID).FromUser(userID).WithCategory("pattern").WithAction("convert").WithDescription(fmt.Sprintf("The \"%s\" is not in the design format, failed to convert and persist the original source content from \"%s\" to design file format", pattern.Name, pattern.Type.String)).WithMetadata(map[string]interface{}{"error": err}).Build()
_ = provider.PersistEvent(event)
go h.config.EventBroadcaster.Publish(userID, event)
h.log.Error(err)
http.Error(rw, err.Error(), http.StatusInternalServerError)
return
}

rw.Header().Set("Content-Type", "application/json")
fmt.Fprint(rw, string(resp))
}
Expand Down Expand Up @@ -1944,9 +1993,7 @@ func (h *Handler) GetMesheryPatternSourceHandler(
provider models.Provider,
) {
designID := mux.Vars(r)["id"]
token, _ := r.Context().Value(models.TokenCtxKey).(string)

resp, err := provider.GetDesignSourceContent(token, designID)
resp, err := provider.GetDesignSourceContent(r, designID)
if err != nil {
h.log.Error(ErrGetPattern(err))
http.Error(rw, ErrGetPattern(err).Error(), http.StatusNotFound)
Expand Down
1 change: 1 addition & 0 deletions server/models/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ type HandlerInterface interface {
UnPublishCatalogPatternHandler(rw http.ResponseWriter, r *http.Request, prefObj *Preference, user *User, provider Provider)
GetMesheryPatternHandler(rw http.ResponseWriter, r *http.Request, prefObj *Preference, user *User, provider Provider)
DesignFileRequestHandlerWithSourceType(rw http.ResponseWriter, r *http.Request, prefObj *Preference, user *User, provider Provider)
HandleConversionToDesign(rw http.ResponseWriter, r *http.Request, prefObj *Preference, user *User, provider Provider)
GetMesheryDesignTypesHandler(rw http.ResponseWriter, r *http.Request, prefObj *Preference, user *User, provider Provider)
GetMesheryPatternSourceHandler(rw http.ResponseWriter, r *http.Request, prefObj *Preference, user *User, provider Provider)

Expand Down
2 changes: 1 addition & 1 deletion server/models/providers.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ type Provider interface {
GetMesheryPatternResources(token, page, pageSize, search, order, name, namespace, typ, oamType string) (*PatternResourcePage, error)
DeleteMesheryPatternResource(token, resourceID string) error
SaveMesheryPatternSourceContent(token string, applicationID string, sourceContent []byte) error
GetDesignSourceContent(token, patternID string) ([]byte, error)
GetDesignSourceContent(req *http.Request, patternID string) ([]byte, error)

SaveMesheryFilter(tokenString string, filter *MesheryFilter) ([]byte, error)
GetMesheryFilters(tokenString, page, pageSize, search, order string, visibility []string) ([]byte, error)
Expand Down
2 changes: 2 additions & 0 deletions server/router/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ func NewRouter(_ context.Context, h models.HandlerInterface, port int, g http.Ha
Methods("POST", "GET")
gMux.Handle("/api/pattern/{sourcetype}", h.ProviderMiddleware(h.AuthMiddleware(h.SessionInjectorMiddleware(h.DesignFileRequestHandlerWithSourceType), models.ProviderAuth))).
Methods("POST", "PUT")
gMux.Handle("/api/pattern/convert/{sourcetype}", h.ProviderMiddleware(h.AuthMiddleware(h.SessionInjectorMiddleware(h.HandleConversionToDesign), models.ProviderAuth))).
Methods("POST", "PUT")
gMux.Handle("/api/pattern/types", h.ProviderMiddleware(h.AuthMiddleware(h.SessionInjectorMiddleware(h.GetMesheryDesignTypesHandler), models.ProviderAuth))).
Methods("GET")
gMux.Handle("/api/pattern/catalog", h.ProviderMiddleware(h.AuthMiddleware(h.SessionInjectorMiddleware(h.GetCatalogMesheryPatternsHandler), models.ProviderAuth))).
Expand Down

0 comments on commit c619f38

Please sign in to comment.