Skip to content

Commit

Permalink
[feat]: integration relate (#101)
Browse files Browse the repository at this point in the history
Signed-off-by: kevin <[email protected]>
  • Loading branch information
kevin6025 authored Jul 12, 2023
1 parent 18e4ec7 commit a08abc9
Show file tree
Hide file tree
Showing 9 changed files with 240 additions and 14 deletions.
28 changes: 27 additions & 1 deletion http/api/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
package api

import (
"context"

"github.com/gin-gonic/gin"
"gorm.io/datatypes"

Expand All @@ -41,7 +43,7 @@ func NewChartAPI(deps *depspkg.API) *ChartAPI {
}

// CreateChart creates a new chart.
func (api *ChartAPI) CreateChart(c *gin.Context) {
func (api *ChartAPI) CreateChart(c *gin.Context) { //nolint:dupl
var chartJSON datatypes.JSON
if err := c.ShouldBind(&chartJSON); err != nil {
httppkg.Error(c, err)
Expand All @@ -57,6 +59,10 @@ func (api *ChartAPI) CreateChart(c *gin.Context) {
httppkg.Error(c, err)
return
}
if err0 := api.saveChartMeta(ctx, chart); err0 != nil {
httppkg.Error(c, err0)
return
}
httppkg.OK(c, uid)
}

Expand All @@ -77,6 +83,10 @@ func (api *ChartAPI) UpdateChart(c *gin.Context) {
httppkg.Error(c, err)
return
}
if err0 := api.saveChartMeta(ctx, chart); err0 != nil {
httppkg.Error(c, err0)
return
}
httppkg.OK(c, "Chart updated")
}

Expand Down Expand Up @@ -105,6 +115,7 @@ func (api *ChartAPI) DeleteChartByUID(c *gin.Context) {
httppkg.Error(c, err)
return
}
// FIXME: delete chart metadata
httppkg.OK(c, "Chart deleted")
}

Expand Down Expand Up @@ -142,3 +153,18 @@ func (api *ChartAPI) UnlinkChartFromDashboard(c *gin.Context) {
}
httppkg.OK(c, "Unlinked chart from dashboard")
}

// saveChartMeta saves chart metadata.
func (api *ChartAPI) saveChartMeta(ctx context.Context, chart *model.Chart) error {
// connect integration
if chart.Integration != "" {
if err := api.deps.IntegrationSrv.ConnectSource(ctx, chart.Integration, chart.UID, model.ChartConnection); err != nil {
return err
}
} else {
if err := api.deps.IntegrationSrv.DisconnectSource(ctx, chart.UID, model.ChartConnection); err != nil {
return err
}
}
return nil
}
34 changes: 31 additions & 3 deletions http/api/chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ func TestChartAPI_CreateChart(t *testing.T) {
defer ctrl.Finish()

chartSrv := service.NewMockChartService(ctrl)
integrationSrv := service.NewMockIntegrationService(ctrl)
r := gin.New()
api := NewChartAPI(&deps.API{
ChartSrv: chartSrv,
ChartSrv: chartSrv,
IntegrationSrv: integrationSrv,
})
r.POST("/charts", api.CreateChart)
body := encoding.JSONMarshal(&model.Chart{})
Expand Down Expand Up @@ -75,11 +77,23 @@ func TestChartAPI_CreateChart(t *testing.T) {
assert.Equal(t, http.StatusInternalServerError, resp.Code)
},
},
{
name: "integration failure",
body: bytes.NewBuffer(body),
prepare: func() {
chartSrv.EXPECT().CreateChart(gomock.Any(), gomock.Any()).Return("1234", nil)
integrationSrv.EXPECT().DisconnectSource(gomock.Any(), gomock.Any(), model.ChartConnection).Return(fmt.Errorf("err"))
},
assert: func(resp *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusInternalServerError, resp.Code)
},
},
{
name: "create chart successfully",
body: bytes.NewBuffer(body),
prepare: func() {
chartSrv.EXPECT().CreateChart(gomock.Any(), gomock.Any()).Return("1234", nil)
integrationSrv.EXPECT().DisconnectSource(gomock.Any(), gomock.Any(), model.ChartConnection).Return(nil)
},
assert: func(resp *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusOK, resp.Code)
Expand Down Expand Up @@ -168,12 +182,14 @@ func TestChartAPI_UpdateChart(t *testing.T) {
defer ctrl.Finish()

chartSrv := service.NewMockChartService(ctrl)
integrationSrv := service.NewMockIntegrationService(ctrl)
r := gin.New()
api := NewChartAPI(&deps.API{
ChartSrv: chartSrv,
ChartSrv: chartSrv,
IntegrationSrv: integrationSrv,
})
r.PUT("/chart", api.UpdateChart)
body := encoding.JSONMarshal(&model.Chart{})
body := encoding.JSONMarshal(&model.Chart{Integration: "abc"})

cases := []struct {
name string
Expand All @@ -198,11 +214,23 @@ func TestChartAPI_UpdateChart(t *testing.T) {
assert.Equal(t, http.StatusInternalServerError, resp.Code)
},
},
{
name: "integration failure",
body: bytes.NewBuffer(body),
prepare: func() {
chartSrv.EXPECT().UpdateChart(gomock.Any(), gomock.Any()).Return(nil)
integrationSrv.EXPECT().ConnectSource(gomock.Any(), "abc", gomock.Any(), model.ChartConnection).Return(fmt.Errorf("err"))
},
assert: func(resp *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusInternalServerError, resp.Code)
},
},
{
name: "update chart successfully",
body: bytes.NewBuffer(body),
prepare: func() {
chartSrv.EXPECT().UpdateChart(gomock.Any(), gomock.Any()).Return(nil)
integrationSrv.EXPECT().ConnectSource(gomock.Any(), "abc", gomock.Any(), model.ChartConnection).Return(nil)
},
assert: func(resp *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusOK, resp.Code)
Expand Down
30 changes: 25 additions & 5 deletions http/api/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
package api

import (
"context"

"github.com/gin-gonic/gin"
"gorm.io/datatypes"

Expand Down Expand Up @@ -47,7 +49,7 @@ func NewDashboardAPI(deps *depspkg.API) *DashboardAPI {
}

// CreateDashboard creates a new dashboard.
func (api *DashboardAPI) CreateDashboard(c *gin.Context) {
func (api *DashboardAPI) CreateDashboard(c *gin.Context) { //nolint:dupl
var dashboardJSON datatypes.JSON
if err := c.ShouldBind(&dashboardJSON); err != nil {
httppkg.Error(c, err)
Expand All @@ -63,8 +65,7 @@ func (api *DashboardAPI) CreateDashboard(c *gin.Context) {
httppkg.Error(c, err)
return
}
// try add chart links if use chart repos in dashboard config
if err = api.deps.ChartSrv.LinkChartsToDashboard(ctx, dashboard); err != nil {
if err := api.saveDashbardMeta(ctx, dashboard); err != nil {
httppkg.Error(c, err)
return
}
Expand All @@ -87,8 +88,7 @@ func (api *DashboardAPI) UpdateDashboard(c *gin.Context) {
httppkg.Error(c, err)
return
}
// try add chart links if use chart repos in dashboard config
if err := api.deps.ChartSrv.LinkChartsToDashboard(ctx, dashboard); err != nil {
if err := api.saveDashbardMeta(ctx, dashboard); err != nil {
httppkg.Error(c, err)
return
}
Expand All @@ -102,6 +102,7 @@ func (api *DashboardAPI) DeleteDashboardByUID(c *gin.Context) {
httppkg.Error(c, err)
return
}
// FIXME: delete metadata
httppkg.OK(c, "Dashboard deleted")
}

Expand Down Expand Up @@ -163,3 +164,22 @@ func (api *DashboardAPI) SearchDashboards(c *gin.Context) {
"dashboards": dashboards,
})
}

// saveDashbardMeta saves dashboard metadata after created/updated.
func (api *DashboardAPI) saveDashbardMeta(ctx context.Context, dashboard *model.Dashboard) error {
// try add chart links if use chart repos in dashboard config
if err := api.deps.ChartSrv.LinkChartsToDashboard(ctx, dashboard); err != nil {
return err
}
// connect integration
if dashboard.Integration != "" {
if err := api.deps.IntegrationSrv.ConnectSource(ctx, dashboard.Integration, dashboard.UID, model.DashboardConnection); err != nil {
return err
}
} else {
if err := api.deps.IntegrationSrv.DisconnectSource(ctx, dashboard.UID, model.DashboardConnection); err != nil {
return err
}
}
return nil
}
42 changes: 37 additions & 5 deletions http/api/dashboard_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,12 @@ func TestDashboardAPI_CreateDashboard(t *testing.T) {

dashboardSrv := service.NewMockDashboardService(ctrl)
chartSrv := service.NewMockChartService(ctrl)
integrationSrv := service.NewMockIntegrationService(ctrl)
r := gin.New()
api := NewDashboardAPI(&deps.API{
DashboardSrv: dashboardSrv,
ChartSrv: chartSrv,
DashboardSrv: dashboardSrv,
ChartSrv: chartSrv,
IntegrationSrv: integrationSrv,
})
r.POST("/dashboard", api.CreateDashboard)
body := encoding.JSONMarshal(&model.Dashboard{Title: "test"})
Expand Down Expand Up @@ -90,12 +92,25 @@ func TestDashboardAPI_CreateDashboard(t *testing.T) {
assert.Equal(t, http.StatusInternalServerError, resp.Code)
},
},
{
name: "integration failure",
body: bytes.NewBuffer(encoding.JSONMarshal(&model.Dashboard{Config: body})),
prepare: func() {
dashboardSrv.EXPECT().CreateDashboard(gomock.Any(), gomock.Any()).Return("1234", nil)
chartSrv.EXPECT().LinkChartsToDashboard(gomock.Any(), gomock.Any()).Return(nil)
integrationSrv.EXPECT().DisconnectSource(gomock.Any(), gomock.Any(), model.DashboardConnection).Return(fmt.Errorf("err"))
},
assert: func(resp *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusInternalServerError, resp.Code)
},
},
{
name: "create dashboard successfully",
body: bytes.NewBuffer(encoding.JSONMarshal(&model.Dashboard{Config: body})),
prepare: func() {
dashboardSrv.EXPECT().CreateDashboard(gomock.Any(), gomock.Any()).Return("1234", nil)
chartSrv.EXPECT().LinkChartsToDashboard(gomock.Any(), gomock.Any()).Return(nil)
integrationSrv.EXPECT().DisconnectSource(gomock.Any(), gomock.Any(), model.DashboardConnection).Return(nil)
},
assert: func(resp *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusOK, resp.Code)
Expand Down Expand Up @@ -124,13 +139,17 @@ func TestDashboardAPI_UpdateDashboard(t *testing.T) {

dashboardSrv := service.NewMockDashboardService(ctrl)
chartSrv := service.NewMockChartService(ctrl)
integrationSrv := service.NewMockIntegrationService(ctrl)
r := gin.New()
api := NewDashboardAPI(&deps.API{
DashboardSrv: dashboardSrv,
ChartSrv: chartSrv,
DashboardSrv: dashboardSrv,
ChartSrv: chartSrv,
IntegrationSrv: integrationSrv,
})
r.PUT("/dashboard", api.UpdateDashboard)
body := encoding.JSONMarshal(&model.Dashboard{})
body := encoding.JSONMarshal(&model.Dashboard{
Integration: "abc",
})

cases := []struct {
name string
Expand Down Expand Up @@ -166,12 +185,25 @@ func TestDashboardAPI_UpdateDashboard(t *testing.T) {
assert.Equal(t, http.StatusInternalServerError, resp.Code)
},
},
{
name: "integration failure",
body: bytes.NewBuffer(body),
prepare: func() {
dashboardSrv.EXPECT().UpdateDashboard(gomock.Any(), gomock.Any()).Return(nil)
chartSrv.EXPECT().LinkChartsToDashboard(gomock.Any(), gomock.Any()).Return(nil)
integrationSrv.EXPECT().ConnectSource(gomock.Any(), "abc", gomock.Any(), model.DashboardConnection).Return(fmt.Errorf("err"))
},
assert: func(resp *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusInternalServerError, resp.Code)
},
},
{
name: "update dashboard successfully",
body: bytes.NewBuffer(body),
prepare: func() {
dashboardSrv.EXPECT().UpdateDashboard(gomock.Any(), gomock.Any()).Return(nil)
chartSrv.EXPECT().LinkChartsToDashboard(gomock.Any(), gomock.Any()).Return(nil)
integrationSrv.EXPECT().ConnectSource(gomock.Any(), "abc", gomock.Any(), model.DashboardConnection).Return(nil)
},
assert: func(resp *httptest.ResponseRecorder) {
assert.Equal(t, http.StatusOK, resp.Code)
Expand Down
2 changes: 2 additions & 0 deletions model/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type Chart struct {
Title string `json:"title" gorm:"column:title;index:u_idx_chart_org_title,unique"`
Desc string `json:"description,omitempty" gorm:"column:desc"`
Integration string `json:"integration" gorm:"column:integration"`
Type string `json:"type" gorm:"column:type"`
Version int `json:"version,omitempty" gorm:"column:version"`

Model datatypes.JSON `json:"model,omitempty" gorm:"column:model"`
Expand All @@ -46,6 +47,7 @@ func (c *Chart) ReadMeta() {
c.Title = gjson.Get(json, "title").String()
c.Desc = gjson.Get(json, "description").String()
c.Integration = gjson.Get(json, "integration").String()
c.Type = gjson.Get(json, "type").String()
}

// SearchChartRequest represents search chart request params.
Expand Down
18 changes: 18 additions & 0 deletions model/integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@

package model

type ConnectionType int

const (
DashboardConnection ConnectionType = iota + 1
ChartConnection
)

// Integration represents all integrations for observability of your application or infrastructure.
type Integration struct {
BaseModel
Expand All @@ -28,3 +35,14 @@ type Integration struct {
Icon string `json:"icon" gorm:"column:icon"`
DocURL string `json:"docUrl" gorm:"column:doc_url"`
}

// IntegrationConnection represents connection between integration and source(dashboard/chart etc.).
type IntegrationConnection struct {
BaseModel

OrgID int64 `json:"-" gorm:"column:org_id;index:u_idx_ic,unique"`

IntegrationUID string `json:"integrationUID" gorm:"column:integration_uid;index:u_idx_ic,unique"`
SourceUID string `json:"sourceUID" gorm:"column:source_uid;index:u_idx_ic,unique"`
Type ConnectionType `json:"type" gorm:"column:type;index:u_idx_ic,unique"`
}
2 changes: 2 additions & 0 deletions service/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ func (srv *chartService) UpdateChart(ctx context.Context, chart *model.Chart) er
chartFromDB.Title = chart.Title
chartFromDB.Desc = chart.Desc
chartFromDB.Model = chart.Model
chartFromDB.Integration = chart.Integration
chartFromDB.Type = chart.Type
chartFromDB.UpdatedBy = user.User.ID
return srv.db.Update(chartFromDB, "uid=? and org_id=?", chart.UID, user.Org.ID)
}
Expand Down
Loading

0 comments on commit a08abc9

Please sign in to comment.