diff --git a/Earthfile b/Earthfile index ac9860b..4cc5699 100644 --- a/Earthfile +++ b/Earthfile @@ -49,9 +49,10 @@ build: COPY +amt-rpc-lib/librpc.so /usr/local/lib/librpc.so COPY +amt-rpc-lib/librpc.h /usr/local/include/librpc.h - RUN go build -ldflags "-linkmode 'external'" -o agent-provider-amt cmd/main.go && upx agent-provider-amt + RUN go build -o agent-provider-amt cmd/main.go && upx agent-provider-amt SAVE ARTIFACT agent-provider-amt AS LOCAL artifacts/agent-provider-amt + SAVE ARTIFACT /usr/local/lib/librpc.so AS LOCAL artifacts/librpc.so image: FROM +version @@ -60,9 +61,8 @@ image: FROM scratch - COPY --chmod 0777 +amt-rpc-lib/librpc.so /usr/local/lib/librpc.so - COPY --chmod 0777 +amt-rpc-lib/librpc.h /usr/local/include/librpc.h - COPY --chmod 0777 +build/agent-provider-amt /system/providers/agent-provider-amt + COPY --chmod 0777 +amt-rpc-lib/librpc.so librpc.so + COPY --chmod 0777 +build/agent-provider-amt agent-provider-amt SAVE IMAGE --push $IMAGE_REPOSITORY:$VERSION diff --git a/cmd/main.go b/cmd/main.go index 3c86a0b..bb1034e 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,11 +1,10 @@ package main import ( - "encoding/json" "fmt" - "github.com/kairos-io/kairos-sdk/bus" - "github.com/mudler/go-pluggable" "github.com/sirupsen/logrus" + "gopkg.in/yaml.v3" + "io" "os" "provider-amt/pkg/amtrpc" "reflect" @@ -13,109 +12,46 @@ import ( "strings" ) -const ( - StateActive = "active" - StateError = "error" - StateUnavailable = "unavailable" - StateSkipped = "skipped" -) - type AMT struct { - DnsSuffixOverride string `json:"dns_suffix_override,omitempty" flag:"-d"` - Hostname string `json:"hostname,omitempty" flag:"-h"` - LMSAddress string `json:"lms_address,omitempty" flag:"-lmsaddress"` - LMSPort string `json:"lms_port,omitempty" flag:"-lmsport"` - ProxyAddress string `json:"proxy_address,omitempty" flag:"-p"` - Password string `json:"password,omitempty" flag:"-password"` - Profile string `json:"profile,omitempty" flag:"-profile"` - ServerAddress string `json:"server_address,omitempty" flag:"-u"` - Timeout string `json:"timeout,omitempty" flag:"-t"` - Extra map[string]string `json:"extra,omitempty"` -} - -type Configuration struct { - AMT *AMT `yaml:"amt,omitempty" json:"amt,omitempty"` + DnsSuffixOverride string `json:"dns_suffix_override,omitempty" yaml:"dns_suffix_override,omitempty" flag:"-d"` + Hostname string `json:"hostname,omitempty" yaml:"hostname,omitempty" flag:"-h"` + LMSAddress string `json:"lms_address,omitempty" yaml:"lms_address,omitempty" flag:"-lmsaddress"` + LMSPort string `json:"lms_port,omitempty" yaml:"lms_port,omitempty" flag:"-lmsport"` + ProxyAddress string `json:"proxy_address,omitempty" yaml:"proxy_address,omitempty" flag:"-p"` + Password string `json:"password,omitempty" yaml:"password,omitempty" flag:"-password"` + Profile string `json:"profile,omitempty" yaml:"profile,omitempty" flag:"-profile"` + ServerAddress string `json:"server_address,omitempty" yaml:"server_address,omitempty" flag:"-u"` + Timeout string `json:"timeout,omitempty" yaml:"timeout,omitempty" flag:"-t"` + Extra map[string]string `json:"extra,omitempty" yaml:"extra,omitempty"` } func main() { - err := pluggable.NewPluginFactory( - pluggable.FactoryPlugin{ - EventType: bus.EventInstall, - PluginHandler: func(event *pluggable.Event) pluggable.EventResponse { - return activateAMT(amtrpc.AMTRPC{}, event) - }, - }, - ).Run(pluggable.EventType(os.Args[1]), os.Stdin, os.Stdout) + var config AMT - if err != nil { - logrus.Fatal(err) + if err := yaml.NewDecoder(io.TeeReader(os.Stdin, os.Stderr)).Decode(&config); err != nil { + logrus.Fatal("failed to parse configuration: ", err) + } + + if err := activateAMT(amtrpc.AMTRPC{}, &config); err != nil { + logrus.Fatal() } } -func getConfiguration(event *pluggable.Event) (*AMT, error) { - var payload bus.EventPayload - var config Configuration - - // parse the event to get the configuration - if err := json.Unmarshal([]byte(event.Data), &payload); err != nil { - return nil, fmt.Errorf("failed to parse event payload %s", err.Error()) - } - - // parse the configuration to get the amt configuration - if err := json.Unmarshal([]byte(payload.Config), &config); err != nil { - return nil, fmt.Errorf("failed to parse configuration %s", err.Error()) - } - - return config.AMT, nil -} - -func activateAMT(rpc amtrpc.Interface, event *pluggable.Event) pluggable.EventResponse { - config, err := getConfiguration(event) - if err != nil { - return pluggable.EventResponse{ - State: StateError, - Data: event.Data, - Error: err.Error(), - } - } - - // if no amt configuration is given we do nothing - if config == nil { - return pluggable.EventResponse{ - State: StateSkipped, - Data: event.Data, - } - } - +func activateAMT(rpc amtrpc.Interface, config *AMT) error { if status := rpc.CheckAccess(); status != utils.Success { if status == utils.AmtNotDetected { - return pluggable.EventResponse{ - State: StateUnavailable, - Data: event.Data, - Logs: "no intel AMT device detected", - } + logrus.Info("amt device could not be detected, skipping configuration") + return nil } - return pluggable.EventResponse{ - State: StateError, - Data: event.Data, - Error: fmt.Sprintf("failed to access AMT device with status code: %d", status), - } + return fmt.Errorf("failed to access AMT device with status code: %d", status) } if response, status := rpc.Exec(toCLIFlags("activate", config, config.Extra)); status != utils.Success { - return pluggable.EventResponse{ - State: StateError, - Data: event.Data, - Error: fmt.Sprintf("failed to activate AMT device with status code: %d", status), - Logs: response, - } + return fmt.Errorf("failed to access AMT device with status code: %d %s", status, response) } - return pluggable.EventResponse{ - State: StateActive, - Data: event.Data, - } + return nil } const flagTag = "flag" diff --git a/cmd/main_test.go b/cmd/main_test.go index 93ce767..c168b70 100644 --- a/cmd/main_test.go +++ b/cmd/main_test.go @@ -1,9 +1,6 @@ package main import ( - "encoding/json" - "github.com/kairos-io/kairos-sdk/bus" - "github.com/mudler/go-pluggable" "github.com/stretchr/testify/assert" "provider-amt/pkg/amtrpc" "rpc/pkg/utils" @@ -31,93 +28,50 @@ var amtExecError = amtrpc.AMTRPC{ } func Test_activateAMTUnavailable(t *testing.T) { - config := Configuration{ - AMT: &AMT{ - ServerAddress: "wss://fake", - }, + config := &AMT{ + ServerAddress: "wss://fake", } - event := encodeConfiguration(config) - resp := activateAMT(amtUnavailable, event) + err := activateAMT(amtUnavailable, config) - assert.Equal(t, StateUnavailable, resp.State) - assert.Equal(t, event.Data, resp.Data) + assert.NoError(t, err) } func Test_activateAMTCheckAccessError(t *testing.T) { - config := Configuration{ - AMT: &AMT{ - ServerAddress: "wss://fake", - }, + config := &AMT{ + ServerAddress: "wss://fake", } - event := encodeConfiguration(config) - resp := activateAMT(amtAccessError, event) + err := activateAMT(amtAccessError, config) - assert.Equal(t, StateError, resp.State) - assert.Equal(t, event.Data, resp.Data) + assert.Error(t, err) } func Test_activateAMTNoConfiguration(t *testing.T) { - config := Configuration{} - event := encodeConfiguration(config) + err := activateAMT(amtActive, &AMT{}) - resp := activateAMT(amtActive, event) - - assert.Equal(t, StateSkipped, resp.State) - assert.Equal(t, event.Data, resp.Data) -} - -func Test_activateAMTInvalidEventData(t *testing.T) { - config := Configuration{ - AMT: &AMT{ - ServerAddress: "wss://fake", - }, - } - event := encodeConfiguration(config) - event.Data = event.Data[1:] - - resp := activateAMT(amtActive, event) - - assert.Equal(t, StateError, resp.State) - assert.Equal(t, event.Data, resp.Data) -} - -func Test_activateAMTInvalidConfiguration(t *testing.T) { - event := &pluggable.Event{Data: `{"config":"{"}`} - - resp := activateAMT(amtActive, event) - - assert.Equal(t, StateError, resp.State) - assert.Equal(t, event.Data, resp.Data) + assert.NoError(t, err) } func Test_activateAMTApplyError(t *testing.T) { - config := Configuration{ - AMT: &AMT{ - ServerAddress: "wss://fake", - }, + config := &AMT{ + ServerAddress: "wss://fake", } - event := encodeConfiguration(config) - resp := activateAMT(amtExecError, event) + err := activateAMT(amtExecError, config) - assert.Equal(t, StateError, resp.State) - assert.Equal(t, event.Data, resp.Data) + assert.Error(t, err) } func Test_activateAMTStandard(t *testing.T) { var execCommand string - config := Configuration{ - AMT: &AMT{ - ServerAddress: "wss://fake", - Extra: map[string]string{ - "-foo": "bar", - }, + config := &AMT{ + ServerAddress: "wss://fake", + Extra: map[string]string{ + "-foo": "bar", }, } - event := encodeConfiguration(config) amt := amtrpc.AMTRPC{ MockAccessStatus: func() int { return utils.Success }, MockExec: func(s string) (string, int) { @@ -126,24 +80,10 @@ func Test_activateAMTStandard(t *testing.T) { }, } - resp := activateAMT(amt, event) + err := activateAMT(amt, config) assert.Contains(t, execCommand, "activate") - assert.Contains(t, execCommand, "-u "+config.AMT.ServerAddress) + assert.Contains(t, execCommand, "-u "+config.ServerAddress) assert.Contains(t, execCommand, "-foo bar") - assert.Equal(t, StateActive, resp.State) - assert.Equal(t, event.Data, resp.Data) - assert.False(t, resp.Errored()) -} - -func encodeConfiguration(config Configuration) *pluggable.Event { - inner, _ := json.Marshal(config) - data, _ := json.Marshal(bus.EventPayload{ - Config: string(inner), - }) - - return &pluggable.Event{ - Name: bus.EventInstall, - Data: string(data), - } + assert.NoError(t, err) } diff --git a/pkg/amtrpc/amtrpc.go b/pkg/amtrpc/amtrpc.go index 33f1c78..f276fc6 100644 --- a/pkg/amtrpc/amtrpc.go +++ b/pkg/amtrpc/amtrpc.go @@ -3,7 +3,7 @@ package amtrpc /* -#cgo LDFLAGS: -L/usr/local/lib -lrpc -Wl,-rpath=/usr/local/lib +#cgo LDFLAGS: -L'$ORIGIN' -lrpc -Wl,-rpath='$ORIGIN' #include #include "librpc.h" */