forked from raystack/siren
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add workflow and goreleaser for plugin provider
- Loading branch information
Showing
5 changed files
with
212 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
} | ||
} | ||
} |