diff --git a/cmd/root.go b/cmd/root.go
index 752ff3402b..d673b13269 100644
--- a/cmd/root.go
+++ b/cmd/root.go
@@ -25,6 +25,7 @@ import (
authIrmaAPI "github.com/nuts-foundation/nuts-node/auth/api/irma"
authV1API "github.com/nuts-foundation/nuts-node/auth/api/v0"
authCmd "github.com/nuts-foundation/nuts-node/auth/cmd"
+ "github.com/nuts-foundation/nuts-node/core/status"
"io"
"os"
@@ -144,7 +145,7 @@ func CreateSystem() *core.System {
networkInstance := network.NewNetworkInstance(network.DefaultConfig(), cryptoInstance)
vdrInstance := vdr.NewVDR(vdr.DefaultConfig(), cryptoInstance, networkInstance)
credentialInstance := vcr.NewVCRInstance(cryptoInstance, vdrInstance, networkInstance)
- statusEngine := core.NewStatusEngine(system)
+ statusEngine := status.NewStatusEngine(system)
metricsEngine := core.NewMetricsEngine()
authInstance := auth.NewAuthInstance(auth.DefaultConfig(), vdrInstance, cryptoInstance)
@@ -182,6 +183,7 @@ func Execute(system *core.System) {
func addSubCommands(system *core.System, root *cobra.Command) {
// Register client commands
clientCommands := []*cobra.Command{
+ status.Cmd(),
cryptoCmd.Cmd(),
networkCmd.Cmd(),
vdrCmd.Cmd(),
diff --git a/core/metrics_test.go b/core/metrics_test.go
index d329e5296f..c5335f4e8f 100644
--- a/core/metrics_test.go
+++ b/core/metrics_test.go
@@ -31,6 +31,11 @@ import (
"github.com/stretchr/testify/assert"
)
+func TestMetricsEngine_Name(t *testing.T) {
+ named := NewMetricsEngine().(Named)
+ assert.Equal(t, "Metrics", named.Name())
+}
+
func TestNewMetricsEngine(t *testing.T) {
mEngine := NewMetricsEngine().(*metrics)
_ = mEngine.Configure(ServerConfig{})
diff --git a/core/status/cmd.go b/core/status/cmd.go
new file mode 100644
index 0000000000..d981fccb2a
--- /dev/null
+++ b/core/status/cmd.go
@@ -0,0 +1,54 @@
+/*
+ * Nuts node
+ * Copyright (C) 2021. Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package status
+
+import (
+ "fmt"
+ "github.com/spf13/cobra"
+ "io/ioutil"
+ "net/http"
+
+ "github.com/nuts-foundation/nuts-node/core"
+)
+
+// Cmd contains sub-commands for the remote client
+func Cmd() *cobra.Command {
+ cmd := &cobra.Command{
+ Use: "status",
+ Short: "Shows the status of the Nuts Node.",
+ RunE: func(cmd *cobra.Command, args []string) error {
+ config := core.NewClientConfig()
+ if err := config.Load(cmd.PersistentFlags()); err != nil {
+ return err
+ }
+ targetURL := config.GetAddress() + diagnosticsEndpoint
+ response, err := http.Get(targetURL)
+ if err != nil {
+ return err
+ }
+ if response.StatusCode != http.StatusOK {
+ return fmt.Errorf("unexpected HTTP response code (url=%s): %d", targetURL, response.StatusCode)
+ }
+ bytes, _ := ioutil.ReadAll(response.Body)
+ cmd.Println(string(bytes))
+ return nil
+ },
+ }
+ return cmd
+}
diff --git a/core/status/cmd_test.go b/core/status/cmd_test.go
new file mode 100644
index 0000000000..2e20b876ad
--- /dev/null
+++ b/core/status/cmd_test.go
@@ -0,0 +1,63 @@
+/*
+ * Nuts node
+ * Copyright (C) 2021. Nuts community
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package status
+
+import (
+ "bytes"
+ "net/http"
+ "net/http/httptest"
+ "os"
+ "testing"
+
+ "github.com/nuts-foundation/nuts-node/core"
+ http2 "github.com/nuts-foundation/nuts-node/test/http"
+ "github.com/stretchr/testify/assert"
+)
+
+func TestEngine_Command(t *testing.T) {
+ t.Run("ok", func(t *testing.T) {
+ cmd := Cmd()
+ s := httptest.NewServer(http2.Handler{StatusCode: http.StatusOK, ResponseData: "diagnostics"})
+ os.Setenv("NUTS_ADDRESS", s.URL)
+ defer os.Unsetenv("NUTS_ADDRESS")
+ core.NewServerConfig().Load(cmd)
+ defer s.Close()
+
+ buf := new(bytes.Buffer)
+ cmd.SetArgs([]string{"status"})
+ cmd.SetOut(buf)
+ err := cmd.Execute()
+ assert.NoError(t, err)
+ assert.Equal(t, "diagnostics\n", buf.String())
+ })
+ t.Run("unexpected status code", func(t *testing.T) {
+ cmd := Cmd()
+ s := httptest.NewServer(http2.Handler{StatusCode: http.StatusInternalServerError, ResponseData: ""})
+ os.Setenv("NUTS_ADDRESS", s.URL)
+ defer os.Unsetenv("NUTS_ADDRESS")
+ core.NewServerConfig().Load(cmd)
+ defer s.Close()
+
+ buf := new(bytes.Buffer)
+ cmd.SetArgs([]string{"status"})
+ cmd.SetOut(buf)
+ err := cmd.Execute()
+ assert.Error(t, err)
+ })
+}
diff --git a/core/status.go b/core/status/engine.go
similarity index 67%
rename from core/status.go
rename to core/status/engine.go
index 592e4340e3..b84391795f 100644
--- a/core/status.go
+++ b/core/status/engine.go
@@ -17,10 +17,11 @@
*
*/
-package core
+package status
import (
"fmt"
+ "github.com/nuts-foundation/nuts-node/core"
"net/http"
"strings"
"time"
@@ -29,14 +30,16 @@ import (
)
const moduleName = "Status"
+const diagnosticsEndpoint = "/status/diagnostics"
+const statusEndpoint = "/status"
type status struct {
- system *System
+ system *core.System
startTime time.Time
}
//NewStatusEngine creates a new Engine for viewing all engines
-func NewStatusEngine(system *System) Engine {
+func NewStatusEngine(system *core.System) core.Engine {
return &status{
system: system,
startTime: time.Now(),
@@ -47,9 +50,9 @@ func (s *status) Name() string {
return moduleName
}
-func (s *status) Routes(router EchoRouter) {
- router.Add(http.MethodGet, "/status/diagnostics", s.diagnosticsOverview)
- router.Add(http.MethodGet, "/status", statusOK)
+func (s *status) Routes(router core.EchoRouter) {
+ router.Add(http.MethodGet, diagnosticsEndpoint, s.diagnosticsOverview)
+ router.Add(http.MethodGet, statusEndpoint, statusOK)
}
func (s *status) diagnosticsOverview(ctx echo.Context) error {
@@ -58,8 +61,8 @@ func (s *status) diagnosticsOverview(ctx echo.Context) error {
func (s *status) diagnosticsSummaryAsText() string {
var lines []string
- s.system.VisitEngines(func(engine Engine) {
- if m, ok := engine.(ViewableDiagnostics); ok {
+ s.system.VisitEngines(func(engine core.Engine) {
+ if m, ok := engine.(core.ViewableDiagnostics); ok {
lines = append(lines, m.Name())
diagnostics := m.Diagnostics()
for _, d := range diagnostics {
@@ -72,17 +75,17 @@ func (s *status) diagnosticsSummaryAsText() string {
// Diagnostics returns list of DiagnosticResult for the StatusEngine.
// The results are a list of all registered engines
-func (s *status) Diagnostics() []DiagnosticResult {
- return []DiagnosticResult{
- &GenericDiagnosticResult{Title: "Registered engines", Outcome: strings.Join(s.listAllEngines(), ",")},
- &GenericDiagnosticResult{Title: "Uptime", Outcome: time.Now().Sub(s.startTime).String()},
+func (s *status) Diagnostics() []core.DiagnosticResult {
+ return []core.DiagnosticResult{
+ &core.GenericDiagnosticResult{Title: "Registered engines", Outcome: strings.Join(s.listAllEngines(), ",")},
+ &core.GenericDiagnosticResult{Title: "Uptime", Outcome: time.Now().Sub(s.startTime).String()},
}
}
func (s *status) listAllEngines() []string {
var names []string
- s.system.VisitEngines(func(engine Engine) {
- if m, ok := engine.(Named); ok {
+ s.system.VisitEngines(func(engine core.Engine) {
+ if m, ok := engine.(core.Named); ok {
names = append(names, m.Name())
}
})
diff --git a/core/status_test.go b/core/status/engine_test.go
similarity index 86%
rename from core/status_test.go
rename to core/status/engine_test.go
index fde858c00c..78b40d014e 100644
--- a/core/status_test.go
+++ b/core/status/engine_test.go
@@ -1,6 +1,7 @@
-package core
+package status
import (
+ "github.com/nuts-foundation/nuts-node/core"
"github.com/nuts-foundation/nuts-node/test"
"net/http"
"testing"
@@ -14,19 +15,19 @@ func TestNewStatusEngine_Routes(t *testing.T) {
t.Run("Registers a single route for listing all engines", func(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
- echo := NewMockEchoRouter(ctrl)
+ echo := core.NewMockEchoRouter(ctrl)
echo.EXPECT().Add(http.MethodGet, "/status/diagnostics", gomock.Any())
echo.EXPECT().Add(http.MethodGet, "/status", gomock.Any())
- NewStatusEngine(NewSystem()).(*status).Routes(echo)
+ NewStatusEngine(core.NewSystem()).(*status).Routes(echo)
})
}
func TestNewStatusEngine_Diagnostics(t *testing.T) {
- system := NewSystem()
+ system := core.NewSystem()
system.RegisterEngine(NewStatusEngine(system))
- system.RegisterEngine(NewMetricsEngine())
+ system.RegisterEngine(core.NewMetricsEngine())
t.Run("diagnostics() returns engine list", func(t *testing.T) {
system := NewStatusEngine(system)