Skip to content

Commit e81c0ac

Browse files
authored
feat: Add serverinfo command (#440)
1 parent d993757 commit e81c0ac

File tree

7 files changed

+248
-2
lines changed

7 files changed

+248
-2
lines changed

internal/cmd/root/root.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import (
44
"fmt"
55
"os"
66

7-
"github.com/ankitpokhrel/jira-cli/pkg/netrc"
8-
97
"github.com/spf13/cobra"
108
"github.com/spf13/viper"
119

@@ -18,10 +16,12 @@ import (
1816
"github.com/ankitpokhrel/jira-cli/internal/cmd/me"
1917
"github.com/ankitpokhrel/jira-cli/internal/cmd/open"
2018
"github.com/ankitpokhrel/jira-cli/internal/cmd/project"
19+
"github.com/ankitpokhrel/jira-cli/internal/cmd/serverinfo"
2120
"github.com/ankitpokhrel/jira-cli/internal/cmd/sprint"
2221
"github.com/ankitpokhrel/jira-cli/internal/cmd/version"
2322
"github.com/ankitpokhrel/jira-cli/internal/cmdutil"
2423
jiraConfig "github.com/ankitpokhrel/jira-cli/internal/config"
24+
"github.com/ankitpokhrel/jira-cli/pkg/netrc"
2525

2626
"github.com/zalando/go-keyring"
2727
)
@@ -124,6 +124,7 @@ func addChildCommands(cmd *cobra.Command) {
124124
project.NewCmdProject(),
125125
open.NewCmdOpen(),
126126
me.NewCmdMe(),
127+
serverinfo.NewCmdServerInfo(),
127128
completion.NewCmdCompletion(),
128129
version.NewCmdVersion(),
129130
man.NewCmdMan(),

internal/cmd/serverinfo/serverinfo.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package serverinfo
2+
3+
import (
4+
"github.com/spf13/cobra"
5+
6+
"github.com/ankitpokhrel/jira-cli/api"
7+
"github.com/ankitpokhrel/jira-cli/internal/cmdutil"
8+
"github.com/ankitpokhrel/jira-cli/internal/view"
9+
"github.com/ankitpokhrel/jira-cli/pkg/jira"
10+
)
11+
12+
// NewCmdServerInfo is a server info command.
13+
func NewCmdServerInfo() *cobra.Command {
14+
return &cobra.Command{
15+
Use: "serverinfo",
16+
Short: "Displays information about the Jira instance",
17+
Long: "Displays information about the Jira instance.",
18+
Aliases: []string{"systeminfo"},
19+
Run: serverInfo,
20+
}
21+
}
22+
23+
func serverInfo(cmd *cobra.Command, _ []string) {
24+
debug, err := cmd.Flags().GetBool("debug")
25+
cmdutil.ExitIfError(err)
26+
27+
info, err := func() (*jira.ServerInfo, error) {
28+
s := cmdutil.Info("Fetching server info...")
29+
defer s.Stop()
30+
31+
info, err := api.Client(jira.Config{Debug: debug}).ServerInfo()
32+
if err != nil {
33+
return nil, err
34+
}
35+
return info, nil
36+
}()
37+
cmdutil.ExitIfError(err)
38+
39+
v := view.NewServerInfo(info)
40+
41+
cmdutil.ExitIfError(v.Render())
42+
}

internal/view/serverinfo.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package view
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"io"
7+
"text/tabwriter"
8+
9+
"github.com/ankitpokhrel/jira-cli/pkg/jira"
10+
"github.com/ankitpokhrel/jira-cli/pkg/tui"
11+
)
12+
13+
// ServerInfoOption is a functional option to wrap serverinfo properties.
14+
type ServerInfoOption func(*ServerInfo)
15+
16+
// ServerInfo is a serveronfo view.
17+
type ServerInfo struct {
18+
data *jira.ServerInfo
19+
writer io.Writer
20+
buf *bytes.Buffer
21+
}
22+
23+
// NewServerInfo initializes server info struct.
24+
func NewServerInfo(data *jira.ServerInfo, opts ...ServerInfoOption) *ServerInfo {
25+
s := ServerInfo{
26+
data: data,
27+
buf: new(bytes.Buffer),
28+
}
29+
s.writer = tabwriter.NewWriter(s.buf, 0, tabWidth, 1, '\t', 0)
30+
31+
for _, opt := range opts {
32+
opt(&s)
33+
}
34+
return &s
35+
}
36+
37+
// WithServerInfoWriter sets a writer for the serverinfo view.
38+
func WithServerInfoWriter(w io.Writer) ServerInfoOption {
39+
return func(s *ServerInfo) {
40+
s.writer = w
41+
}
42+
}
43+
44+
// Render renders the serverinfo view.
45+
func (s ServerInfo) Render() error {
46+
fmt.Fprintf(s.writer, `SERVER INFO
47+
-----------
48+
49+
Version: %s
50+
Build Number: %d
51+
Deployment Type: %s
52+
Default Locale: %s
53+
`, s.data.Version, s.data.BuildNumber, s.data.DeploymentType, s.data.DefaultLocale.Locale)
54+
55+
return tui.PagerOut(s.buf.String())
56+
}

internal/view/serverinfo_test.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package view
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
10+
"github.com/ankitpokhrel/jira-cli/pkg/jira"
11+
)
12+
13+
func TestServerInfoRender(t *testing.T) {
14+
var b bytes.Buffer
15+
16+
data := &jira.ServerInfo{
17+
Version: "9.1.0",
18+
VersionNumbers: []int{9, 1, 0},
19+
DeploymentType: "Server",
20+
BuildNumber: 901000,
21+
DefaultLocale: struct {
22+
Locale string `json:"locale"`
23+
}{Locale: "en_US"},
24+
}
25+
26+
serverInfo := NewServerInfo(data, WithServerInfoWriter(&b))
27+
assert.NoError(t, serverInfo.Render())
28+
29+
expected := fmt.Sprintf(`SERVER INFO
30+
-----------
31+
32+
Version: %s
33+
Build Number: %d
34+
Deployment Type: %s
35+
Default Locale: %s
36+
`, data.Version, data.BuildNumber, data.DeploymentType, data.DefaultLocale.Locale)
37+
38+
assert.Equal(t, expected, b.String())
39+
}

pkg/jira/serverinfo.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package jira
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"net/http"
7+
)
8+
9+
// ServerInfo struct holds response from /serverInfo endpoint.
10+
type ServerInfo struct {
11+
Version string `json:"version"`
12+
VersionNumbers []int `json:"versionNumbers"`
13+
DeploymentType string `json:"deploymentType"`
14+
BuildNumber int `json:"buildNumber"`
15+
DefaultLocale struct {
16+
Locale string `json:"locale"`
17+
} `json:"defaultLocale"`
18+
}
19+
20+
// ServerInfo fetches response from /serverInfo endpoint.
21+
func (c *Client) ServerInfo() (*ServerInfo, error) {
22+
res, err := c.GetV2(context.Background(), "/serverInfo", nil)
23+
if err != nil {
24+
return nil, err
25+
}
26+
if res != nil {
27+
defer func() { _ = res.Body.Close() }()
28+
}
29+
if res.StatusCode != http.StatusOK {
30+
return nil, formatUnexpectedResponse(res)
31+
}
32+
33+
var info ServerInfo
34+
35+
err = json.NewDecoder(res.Body).Decode(&info)
36+
37+
return &info, err
38+
}

pkg/jira/serverinfo_test.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package jira
2+
3+
import (
4+
"net/http"
5+
"net/http/httptest"
6+
"os"
7+
"testing"
8+
"time"
9+
10+
"github.com/stretchr/testify/assert"
11+
)
12+
13+
func TestServerInfo(t *testing.T) {
14+
var unexpectedStatusCode bool
15+
16+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
17+
assert.Equal(t, "/rest/api/2/serverInfo", r.URL.Path)
18+
19+
if unexpectedStatusCode {
20+
w.WriteHeader(400)
21+
} else {
22+
resp, err := os.ReadFile("./testdata/serverinfo.json")
23+
assert.NoError(t, err)
24+
25+
w.Header().Set("Content-Type", "application/json")
26+
w.WriteHeader(200)
27+
_, _ = w.Write(resp)
28+
}
29+
}))
30+
defer server.Close()
31+
32+
client := NewClient(Config{Server: server.URL}, WithTimeout(3*time.Second))
33+
34+
actual, err := client.ServerInfo()
35+
assert.NoError(t, err)
36+
37+
expected := &ServerInfo{
38+
Version: "1001.0.0-SNAPSHOT",
39+
VersionNumbers: []int{1001, 0, 0},
40+
DeploymentType: "Cloud",
41+
BuildNumber: 100204,
42+
DefaultLocale: struct {
43+
Locale string `json:"locale"`
44+
}{Locale: "en_US"},
45+
}
46+
assert.Equal(t, expected, actual)
47+
48+
unexpectedStatusCode = true
49+
50+
_, err = client.ServerInfo()
51+
assert.Error(t, &ErrUnexpectedResponse{}, err)
52+
}

pkg/jira/testdata/serverinfo.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"baseUrl": "https://demo.atlassian.net",
3+
"version": "1001.0.0-SNAPSHOT",
4+
"versionNumbers": [
5+
1001,
6+
0,
7+
0
8+
],
9+
"deploymentType": "Cloud",
10+
"buildNumber": 100204,
11+
"buildDate": "2022-08-12T12:59:12.000+0200",
12+
"serverTime": "2022-08-15T21:08:52.725+0200",
13+
"scmInfo": "948b370c557f4bbf768b92203f3aca5d86ee9758",
14+
"serverTitle": "Jira",
15+
"defaultLocale": {
16+
"locale": "en_US"
17+
}
18+
}

0 commit comments

Comments
 (0)