Skip to content

Commit

Permalink
fix(api): select requirements from plugin binary depending os/arch (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
richardlt authored Nov 18, 2021
1 parent b966485 commit fb437e9
Show file tree
Hide file tree
Showing 19 changed files with 252 additions and 221 deletions.
2 changes: 1 addition & 1 deletion contrib/integrations/arsenal/plugin-arsenal/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Arsenal integration must configured as following
host:
type: string
deployment: true
deployment_default_config:
additional_default_config:
version:
type: string
deployment.token:
Expand Down
2 changes: 1 addition & 1 deletion contrib/integrations/hello/hello.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name: Hello
author: "Username Lastname"
default_config: {}
deployment_default_config:
additional_default_config:
deployment.token:
value: ""
type: password
Expand Down
10 changes: 5 additions & 5 deletions contrib/integrations/hello/plugin-hello-deployment/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ build: $(TARGET_DIR)
FILENAME=deployment-plugin-$(TARGET_NAME)-$$GOOS-$$GOARCH$$EXTENSION; \
echo Compiling $(TARGET_DIR)/$$FILENAME $(VERSION); \
GOOS=$$GOOS GOARCH=$$GOARCH $(GO_BUILD) $(TARGET_LDFLAGS) -o $(TARGET_DIR)/$$FILENAME || exit 1; \
echo "$$PLUGIN_MANIFEST_BINARY" > $(TARGET_DIR)/plugin-kubernetes-$$GOOS-$$GOARCH.yml; \
perl -pi -e s,%os%,$$GOOS,g $(TARGET_DIR)/plugin-kubernetes-$$GOOS-$$GOARCH.yml; \
perl -pi -e s,%arch%,$$GOARCH,g $(TARGET_DIR)/plugin-kubernetes-$$GOOS-$$GOARCH.yml; \
perl -pi -e s,%filename%,$$FILENAME,g $(TARGET_DIR)/plugin-kubernetes-$$GOOS-$$GOARCH.yml; \
echo "$$PLUGIN_MANIFEST_BINARY" > $(TARGET_DIR)/plugin-hello-deployment-$$GOOS-$$GOARCH.yml; \
perl -pi -e s,%os%,$$GOOS,g $(TARGET_DIR)/plugin-hello-deployment-$$GOOS-$$GOARCH.yml; \
perl -pi -e s,%arch%,$$GOARCH,g $(TARGET_DIR)/plugin-hello-deployment-$$GOOS-$$GOARCH.yml; \
perl -pi -e s,%filename%,$$FILENAME,g $(TARGET_DIR)/plugin-hello-deployment-$$GOOS-$$GOARCH.yml; \
done; \
done

Expand All @@ -61,7 +61,7 @@ publish:
PLUGIN_YML=$(TARGET_DIR)/plugin.yml; \
NAME_PLUGIN=`grep 'name:' $$PLUGIN_YML|cut -d ':' -f2;`; \
echo "Updating plugin $$NAME_PLUGIN with binary $$FILENAME"; \
cdsctl admin plugins binary-add $$NAME_PLUGIN $(TARGET_DIR)/plugin-$$GOOS-$$GOARCH.yml $(TARGET_DIR)/$$FILENAME; \
cdsctl admin plugins binary-add $$NAME_PLUGIN $(TARGET_DIR)/plugin-hello-deployment-$$GOOS-$$GOARCH.yml $(TARGET_DIR)/$$FILENAME; \
else \
echo "$$FILENAME is missing"; \
fi \
Expand Down
2 changes: 1 addition & 1 deletion contrib/integrations/hello/plugin-hello-deployment/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Hello integration must configured as following (content of hello-integration.yml
name: Hello
author: "Username Lastname"
default_config: {}
deployment_default_config:
additional_default_config:
deployment.token:
value: ""
type: password
Expand Down
2 changes: 1 addition & 1 deletion contrib/integrations/kubernetes/kubernetes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ default_config:
token:
type: password
deployment: true
deployment_default_config:
additional_default_config:
release_name:
type: string
description: Fill it if you want to use another name than your application name for the Helm release. Leave empty if not
Expand Down
54 changes: 41 additions & 13 deletions engine/api/grpc_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ func (api *API) postGRPCluginHandler() service.Handler {

func (api *API) getAllGRPCluginHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {

ps, err := plugin.LoadAll(api.mustDB())
ps, err := plugin.LoadAll(ctx, api.mustDB())
if err != nil {
return sdk.WrapError(err, "unable to load all plugins")
}
Expand All @@ -87,9 +86,9 @@ func (api *API) getAllGRPCluginHandler() service.Handler {

func (api *API) getGRPCluginHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
var name = mux.Vars(r)["name"]
name := mux.Vars(r)["name"]

p, err := plugin.LoadByName(api.mustDB(), name)
p, err := plugin.LoadByName(ctx, api.mustDB(), name)
if err != nil {
return sdk.WrapError(err, "getGRPCluginHandler")
}
Expand All @@ -100,6 +99,8 @@ func (api *API) getGRPCluginHandler() service.Handler {

func (api *API) putGRPCluginHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
name := mux.Vars(r)["name"]

db := api.mustDB()
var p sdk.GRPCPlugin
if err := service.UnmarshalBody(r, &p); err != nil {
Expand All @@ -109,8 +110,7 @@ func (api *API) putGRPCluginHandler() service.Handler {
return sdk.WithStack(err)
}

var name = mux.Vars(r)["name"]
old, err := plugin.LoadByName(api.mustDB(), name)
old, err := plugin.LoadByName(ctx, api.mustDB(), name)
if err != nil {
return sdk.WrapError(err, "unable to load old plugin")
}
Expand Down Expand Up @@ -153,8 +153,9 @@ func (api *API) putGRPCluginHandler() service.Handler {

func (api *API) deleteGRPCluginHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
var name = mux.Vars(r)["name"]
old, err := plugin.LoadByName(api.mustDB(), name)
name := mux.Vars(r)["name"]

old, err := plugin.LoadByName(ctx, api.mustDB(), name)
if err != nil {
return sdk.WrapError(err, "unable to load old plugin")
}
Expand All @@ -169,6 +170,9 @@ func (api *API) deleteGRPCluginHandler() service.Handler {

func (api *API) postGRPCluginBinaryHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
vars := mux.Vars(r)
name := vars["name"]

var b sdk.GRPCPluginBinary
if err := service.UnmarshalBody(r, &b); err != nil {
return sdk.WrapError(err, "postGRPCluginBinaryHandler")
Expand All @@ -184,8 +188,7 @@ func (api *API) postGRPCluginBinaryHandler() service.Handler {
}
defer tx.Rollback() // nolint

name := mux.Vars(r)["name"]
p, err := plugin.LoadByName(tx, name)
p, err := plugin.LoadByName(ctx, tx, name)
if err != nil {
return sdk.WrapError(err, "postGRPCluginBinaryHandler")
}
Expand Down Expand Up @@ -218,7 +221,7 @@ func (api *API) getGRPCluginBinaryHandler() service.Handler {
os := vars["os"]
arch := vars["arch"]

p, err := plugin.LoadByName(api.mustDB(), name)
p, err := plugin.LoadByName(ctx, api.mustDB(), name)
if err != nil {
return sdk.WrapError(err, "getGRPCluginBinaryHandler")
}
Expand Down Expand Up @@ -268,7 +271,7 @@ func (api *API) getGRPCluginBinaryInfosHandler() service.Handler {
os := vars["os"]
arch := vars["arch"]

p, err := plugin.LoadByName(api.mustDB(), name)
p, err := plugin.LoadByName(ctx, api.mustDB(), name)
if err != nil {
return sdk.WithStack(err)
}
Expand All @@ -284,6 +287,31 @@ func (api *API) getGRPCluginBinaryInfosHandler() service.Handler {

func (api *API) deleteGRPCluginBinaryHandler() service.Handler {
return func(ctx context.Context, w http.ResponseWriter, r *http.Request) error {
return nil
vars := mux.Vars(r)

name := vars["name"]
os := vars["os"]
arch := vars["arch"]

tx, err := api.mustDB().Begin()
if err != nil {
return sdk.WrapError(err, "unable to start tx")
}
defer tx.Rollback() // nolint

p, err := plugin.LoadByName(ctx, tx, name)
if err != nil {
return sdk.WrapError(err, "unable to load plugin")
}

if err := plugin.DeleteBinary(ctx, tx, api.SharedStorage, p, os, arch); err != nil {
return err
}

if err := tx.Commit(); err != nil {
return sdk.WrapError(err, "unable to commit tx")
}

return service.WriteJSON(w, nil, http.StatusOK)
}
}
157 changes: 54 additions & 103 deletions engine/api/plugin/dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package plugin

import (
"context"
"database/sql"

"github.com/go-gorp/gorp"
"github.com/rockbears/log"
Expand All @@ -14,43 +13,20 @@ import (

// Insert inserts a plugin
func Insert(db gorp.SqlExecutor, p *sdk.GRPCPlugin) error {
m := grpcPlugin(*p)
if err := db.Insert(&m); err != nil {
return sdk.WithStack(err)
for i := range p.Binaries {
p.Binaries[i].FileContent = nil
p.Binaries[i].PluginName = p.Name
}
*p = sdk.GRPCPlugin(m)
return nil
return sdk.WrapError(gorpmapping.Insert(db, p), "unable to insert plugin %q", p.Name)
}

// Update updates a plugin
func Update(db gorp.SqlExecutor, p *sdk.GRPCPlugin) error {
m := grpcPlugin(*p)
if _, err := db.Update(&m); err != nil {
return sdk.WithStack(err)
}
*p = sdk.GRPCPlugin(m)
return nil
}

func (p *grpcPlugin) PostInsert(db gorp.SqlExecutor) error {
return p.PostUpdate(db)
}

func (p *grpcPlugin) PostUpdate(db gorp.SqlExecutor) error {
for i := range p.Binaries {
p.Binaries[i].FileContent = nil
p.Binaries[i].PluginName = p.Name
}
s, err := gorpmapping.JSONToNullString(p.Binaries)
if err != nil {
return sdk.WrapError(err, "unable to marshal data")
}

if _, err := db.Exec("UPDATE grpc_plugin SET binaries = $2 WHERE id = $1", p.ID, s); err != nil {
return sdk.WrapError(err, "unable to update data")
}

return nil
return sdk.WrapError(gorpmapping.Update(db, p), "unable to update plugin %q", p.Name)
}

// Delete deletes a plugin
Expand All @@ -60,96 +36,71 @@ func Delete(ctx context.Context, db gorp.SqlExecutor, storageDriver objectstore.
log.Error(ctx, "plugin.Delete> unable to delete binary %v", b.ObjectPath)
}
}

m := grpcPlugin(*p)
if _, err := db.Delete(&m); err != nil {
return sdk.WrapError(err, "plugin.Delete")
}
return nil
return sdk.WrapError(gorpmapping.Delete(db, p), "unable to delete plugin %q", p.Name)
}

// LoadByName loads a plugin by name
func LoadByName(db gorp.SqlExecutor, name string) (*sdk.GRPCPlugin, error) {
m := grpcPlugin{}
if err := db.SelectOne(&m, "SELECT * FROM grpc_plugin WHERE NAME = $1", name); err != nil {
if err == sql.ErrNoRows {
return nil, sdk.NewErrorFrom(sdk.ErrNotFound, "plugin %s not found", name)
func getAll(ctx context.Context, db gorp.SqlExecutor, q gorpmapping.Query, opts ...LoadOptionFunc) ([]sdk.GRPCPlugin, error) {
pps := []*sdk.GRPCPlugin{}

if err := gorpmapping.GetAll(ctx, db, q, &pps); err != nil {
return nil, sdk.WrapError(err, "cannot get plugins")
}
if len(pps) > 0 {
for i := range opts {
if err := opts[i](ctx, db, pps...); err != nil {
return nil, err
}
}
return nil, sdk.WrapError(err, "plugin.LoadByName")
}
if err := m.PostGet(db); err != nil {
return nil, sdk.WrapError(err, "plugin.LoadByName")

ps := make([]sdk.GRPCPlugin, len(pps))
for i := range pps {
ps[i] = *pps[i]
}
p := sdk.GRPCPlugin(m)
return &p, nil

return ps, nil
}

// LoadByIntegrationModelIDAndType loads a single plugin associated to a integration model id with a specified type
func LoadByIntegrationModelIDAndType(db gorp.SqlExecutor, integrationModelID int64, typePlugin string) (*sdk.GRPCPlugin, error) {
m := grpcPlugin{}
if err := db.SelectOne(&m, "SELECT * FROM grpc_plugin where integration_model_id = $1 and type = $2", integrationModelID, typePlugin); err != nil {
if err == sql.ErrNoRows {
return nil, sdk.NewErrorFrom(sdk.ErrNotFound, "plugin not found (type: %s) for integration %d", typePlugin, integrationModelID)
}
return nil, sdk.WrapError(err, "plugin.LoadByIntegrationModelIDAndType")
func get(ctx context.Context, db gorp.SqlExecutor, q gorpmapping.Query, opts ...LoadOptionFunc) (*sdk.GRPCPlugin, error) {
var p sdk.GRPCPlugin

found, err := gorpmapping.Get(ctx, db, q, &p)
if err != nil {
return nil, sdk.WrapError(err, "cannot get plugin")
}
if err := m.PostGet(db); err != nil {
return nil, sdk.WrapError(err, "plugin.LoadByIntegrationModelIDAndType")
if !found {
return nil, sdk.WithStack(sdk.ErrNotFound)
}
p := sdk.GRPCPlugin(m)
return &p, nil
}

// LoadAllByIntegrationModelID loads all plugins associated to a integration model id
func LoadAllByIntegrationModelID(db gorp.SqlExecutor, integrationModelID int64) ([]sdk.GRPCPlugin, error) {
m := []grpcPlugin{}
if _, err := db.Select(&m, "SELECT * FROM grpc_plugin where integration_model_id = $1", integrationModelID); err != nil {
return nil, sdk.WrapError(err, "plugin.LoadAllByIntegrationModelID")
}
res := make([]sdk.GRPCPlugin, len(m))
for i := range m {
p := m[i]
if err := p.PostGet(db); err != nil {
return nil, sdk.WrapError(err, "LoadAllByIntegrationModelID")
for i := range opts {
if err := opts[i](ctx, db, &p); err != nil {
return nil, err
}
res[i] = sdk.GRPCPlugin(p)
}
return res, nil

return &p, nil
}

// LoadAll loads all GRPC Plugins
func LoadAll(db gorp.SqlExecutor) ([]sdk.GRPCPlugin, error) {
m := []grpcPlugin{}
if _, err := db.Select(&m, "SELECT * FROM grpc_plugin"); err != nil {
return nil, sdk.WrapError(err, "plugin.LoadAll")
}
// LoadAll GRPC plugins.
func LoadAll(ctx context.Context, db gorp.SqlExecutor) ([]sdk.GRPCPlugin, error) {
query := gorpmapping.NewQuery("SELECT * FROM grpc_plugin")
return getAll(ctx, db, query, LoadOptions.WithIntegrationModelName)
}

res := make([]sdk.GRPCPlugin, len(m))
for i := range m {
p := m[i]
if err := p.PostGet(db); err != nil {
return nil, sdk.WrapError(err, "LoadAll")
}
res[i] = sdk.GRPCPlugin(p)
}
// LoadAllByIntegrationModelID load all GRPC plugins for given integration model id.
func LoadAllByIntegrationModelID(ctx context.Context, db gorp.SqlExecutor, integrationModelID int64) ([]sdk.GRPCPlugin, error) {
query := gorpmapping.NewQuery("SELECT * FROM grpc_plugin WHERE integration_model_id = $1").Args(integrationModelID)
return getAll(ctx, db, query, LoadOptions.WithIntegrationModelName)
}

return res, nil
// LoadByName retrieves in database the plugin with given name.
func LoadByName(ctx context.Context, db gorp.SqlExecutor, name string) (*sdk.GRPCPlugin, error) {
query := gorpmapping.NewQuery("SELECT * FROM grpc_plugin WHERE name = $1").Args(name)
return get(ctx, db, query, LoadOptions.WithIntegrationModelName)
}

func (p *grpcPlugin) PostGet(db gorp.SqlExecutor) error {
s, err := db.SelectNullStr("SELECT binaries FROM grpc_plugin WHERE ID = $1", p.ID)
if err != nil {
return sdk.WrapError(err, "unable to get binaries for ID=%d", p.ID)
}
if err := gorpmapping.JSONNullString(s, &p.Binaries); err != nil {
return sdk.WrapError(err, "plugin.PostGet")
}
if p.IntegrationModelID != nil {
var err error
p.Integration, err = db.SelectStr("SELECT name FROM integration_model WHERE ID = $1", p.IntegrationModelID)
if err != nil {
return sdk.WrapError(err, "unable to get integration name for ID=%d", p.IntegrationModelID)
}
}
return nil
// LoadByIntegrationModelIDAndType retrieves in database a single plugin associated to a integration model id with a specified type.
func LoadByIntegrationModelIDAndType(ctx context.Context, db gorp.SqlExecutor, integrationModelID int64, typePlugin string) (*sdk.GRPCPlugin, error) {
query := gorpmapping.NewQuery("SELECT * FROM grpc_plugin WHERE integration_model_id = $1 AND type = $2").Args(integrationModelID, typePlugin)
return get(ctx, db, query, LoadOptions.WithIntegrationModelName)
}
4 changes: 2 additions & 2 deletions engine/api/plugin/dao_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ func TestInsertUpdateLoadDelete(t *testing.T) {

require.NoError(t, Update(db, &p))

_, err := LoadByName(db, "test_plugin")
_, err := LoadByName(context.TODO(), db, "test_plugin")
test.NoError(t, err)

all, err := LoadAll(db)
all, err := LoadAll(context.TODO(), db)
require.NoError(t, err)
assert.True(t, len(all) >= 1)
var found bool
Expand Down
Loading

0 comments on commit fb437e9

Please sign in to comment.