Skip to content

Commit

Permalink
feat: add workflow and goreleaser for plugin provider
Browse files Browse the repository at this point in the history
  • Loading branch information
mabdh committed Sep 11, 2023
1 parent b2813ea commit 20db655
Show file tree
Hide file tree
Showing 5 changed files with 212 additions and 4 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Release
on:
push:
tags:
- 'v*'
- "v*"

jobs:
release:
Expand Down Expand Up @@ -43,10 +43,10 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2.6.1
uses: goreleaser/goreleaser-action@v4
with:
distribution: goreleaser
version: latest
args: --rm-dist
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.GO_RELEASER_TOKEN }}
2 changes: 1 addition & 1 deletion .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ brews:
- name: siren
homepage: "https://github.com/goto/siren"
description: "Universal data observability tool."
tap:
repository:
owner: goto
name: homebrew-taps
license: "Apache 2.0"
Expand Down
27 changes: 27 additions & 0 deletions plugins/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package plugins

type Config struct {
PluginPath string `mapstructure:"plugin_path" yaml:"plugin_path" json:"plugin_path" default:"./plugin"`
Plugins map[string]PluginConfig `mapstructure:"plugins" yaml:"plugins" json:"plugins"`
}

type PluginConfig struct {
Handshake HandshakeConfig `mapstructure:"handshake" yaml:"handshake" json:"handshake"`
ServiceConfig map[string]interface{} `mapstructure:"service_config" yaml:"plugin_config" json:"plugin_config"`
}

type HandshakeConfig struct {
// ProtocolVersion is the version that clients must match on to
// agree they can communicate. This should match the ProtocolVersion
// set on ClientConfig when using a plugin.
// This field is not required if VersionedPlugins are being used in the
// Client or Server configurations.
ProtocolVersion uint `mapstructure:"protocol_version" yaml:"protocol_version" json:"protocol_version"`

// MagicCookieKey and value are used as a very basic verification
// that a plugin is intended to be launched. This is not a security
// measure, just a UX feature. If the magic cookie doesn't match,
// we show human-friendly output.
MagicCookieKey string `mapstructure:"magic_cookie_key" yaml:"magic_cookie_key" json:"magic_cookie_key"`
MagicCookieValue string `mapstructure:"magic_cookie_value" yaml:"magic_cookie_value" json:"magic_cookie_value"`
}
73 changes: 73 additions & 0 deletions plugins/providers/cortex/.goreleaser.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
env:
- GORELEASER_CURRENT_TAG={{ .Env.PLUGIN_VERSION }}

project_name: "{{ .Env.PLUGIN_NAME }}"

release:
draft: true
prerelease: auto

before:
hooks:
- go mod tidy
- go mod vendor

builds:
- main: ./main.go
id: "{{ .Env.PLUGIN_NAME }}"
binary: "{{ .Env.PLUGIN_NAME }}"
flags:
- -a
ldflags:
- -s -w -X github.com/goto/siren/plugins/providers/{{ .Env.PLUGIN_DIR_NAME }}/config.Version={{{{ .Env.PLUGIN_VERSION }}}} -X github.com/goto/siren/plugins/providers/{{ .Env.PLUGIN_DIR_NAME }}/config.BuildCommit={{.FullCommit}} -X github.com/goto/siren/plugins/providers/{{ .Env.PLUGIN_DIR_NAME }}/config.BuildDate={{.Date}}
env:
- CGO_ENABLED=0
goos: [darwin, linux, windows]
goarch: [amd64, '386']

archives:
- name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else if eq .Arch "windows" }}windows
{{- else if eq .Arch "linux" }}linux
{{- else if eq .Arch "darwin" }}macos
{{- else }}{{ .Arch }}{{ end }}
format_overrides:
- goos: windows
format: zip
changelog:
sort: asc
filters:
exclude:
- "^docs:"
- "^test:"
- "^build:"
- "Merge pull request"
- "Merge branch"

checksum:
name_template: "checksums.txt"

snapshot:
name_template: "{{ .Env.PLUGIN_VERSION }}-next"

brews:
- name: siren-cortex
homepage: "https://github.com/goto/siren/plugins/providers/{{ .Env.PLUGIN_DIR_NAME }}/"
description: "{{ .Env.PLUGIN_DIR_NAME }} plugin for siren."
repository:
owner: goto
name: homebrew-taps
license: "Apache 2.0"
folder: Formula
dependencies:
- name: git
install: |-
bin.install "{{ .Env.PLUGIN_NAME }}"
commit_author:
name: github-actions[bot]
email: 41898282+github-actions[bot]@users.noreply.github.com
108 changes: 108 additions & 0 deletions plugins/providers/manager.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package providers

import (
"context"
"encoding/json"
"fmt"
"os/exec"
"path/filepath"

"github.com/goto/salt/log"
"github.com/goto/siren/plugins"
"github.com/hashicorp/go-plugin"
)

type PluginManager struct {
cfg plugins.Config
pluginClients map[string]*plugin.Client
}

func NewPluginManager(logger log.Logger, cfg plugins.Config) *PluginManager {
return &PluginManager{
cfg: cfg,
}
}

func (pl *PluginManager) InitClients() map[string]*plugin.Client {
var pluginClients = make(map[string]*plugin.Client, 0)
for k, v := range pl.cfg.Plugins {
// We're a host. Start by launching the plugin process.
client := plugin.NewClient(&plugin.ClientConfig{
HandshakeConfig: plugin.HandshakeConfig{
ProtocolVersion: v.Handshake.ProtocolVersion,
MagicCookieKey: v.Handshake.MagicCookieKey,
MagicCookieValue: v.Handshake.MagicCookieValue,
},
Cmd: exec.Command("sh", "-c", filepath.Join(pl.cfg.PluginPath, k)),
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
VersionedPlugins: map[int]plugin.PluginSet{
1: {
k: &plugins.ProviderV1beta1GRPCPlugin{},
},
},
})
pluginClients[k] = client
}

pl.pluginClients = pluginClients

return pl.pluginClients
}

func (pl *PluginManager) DispenseClients(pluginClients map[string]*plugin.Client) (map[string]plugins.ProviderV1beta1, error) {
var providerPlugins = make(map[string]plugins.ProviderV1beta1, 0)

for k, client := range pluginClients {
prot := client.Protocol()
_ = prot
rpcClient, err := client.Client()
if err != nil {
return nil, fmt.Errorf("error creating plugin client: %s with error %s", k, err.Error())
} else {
// Request the plugin
raw, err := rpcClient.Dispense(k)
if err != nil {
return nil, fmt.Errorf("error dispensing plugin client: %s with error %s", k, err.Error())
}

providerClient := raw.(plugins.ProviderV1beta1)

providerPlugins[k] = providerClient
}
}

return providerPlugins, nil
}

func (pl *PluginManager) InitConfigs(ctx context.Context, providerPlugins map[string]plugins.ProviderV1beta1, logLevel string) error {
for k, client := range providerPlugins {
pluginConfig, ok := pl.cfg.Plugins[k]
if !ok {
return fmt.Errorf("cannot found config for provider %s", k)
}

var serviceConfig = make(map[string]interface{}, 0)

if pluginConfig.ServiceConfig != nil {
serviceConfig = pluginConfig.ServiceConfig
}

jsonRaw, err := json.Marshal(serviceConfig)
if err != nil {
return fmt.Errorf("cannot stringify config for provider %s with error %s", k, err.Error())
}

if err := client.SetConfig(ctx, string(jsonRaw)); err != nil {
return fmt.Errorf("cannot set config for provider %s with error %s", k, err.Error())
}
}
return nil
}

func (pl *PluginManager) Stop() {
for _, pluginClient := range pl.pluginClients {
if !pluginClient.Exited() {
pluginClient.Kill()
}
}
}

0 comments on commit 20db655

Please sign in to comment.