Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfd939c5

Browse files
committed
Add the server version to arduino-app-cli version.
1 parenta6c084e commitfd939c5

File tree

2 files changed

+207
-9
lines changed

2 files changed

+207
-9
lines changed

‎cmd/arduino-app-cli/version/version.go‎

Lines changed: 107 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,34 +16,132 @@
1616
package version
1717

1818
import (
19+
"encoding/json"
1920
"fmt"
21+
"io"
22+
"net"
23+
"net/http"
24+
"net/url"
25+
"time"
2026

2127
"github.com/spf13/cobra"
2228

2329
"github.com/arduino/arduino-app-cli/cmd/feedback"
30+
"github.com/arduino/arduino-app-cli/cmd/i18n"
2431
)
2532

26-
funcNewVersionCmd(versionstring)*cobra.Command {
33+
// The actual listening address for the daemon
34+
// is defined in the installation package
35+
const (
36+
DefaultHostname="localhost"
37+
DefaultPort="8800"
38+
)
39+
40+
funcNewVersionCmd(clientVersionstring)*cobra.Command {
2741
cmd:=&cobra.Command{
2842
Use:"version",
29-
Short:"Print the versionnumber ofArduino App CLI",
43+
Short:"Print theclient and serverversionnumbers for theArduino App CLI.",
3044
Run:func(cmd*cobra.Command,args []string) {
31-
feedback.PrintResult(versionResult{
32-
AppName:"Arduino App CLI",
33-
Version:version,
34-
})
45+
host,_:=cmd.Flags().GetString("host")
46+
47+
versionHandler(clientVersion,host)
3548
},
3649
}
50+
cmd.Flags().String("host",fmt.Sprintf("%s:%s",DefaultHostname,DefaultPort),
51+
"The daemon network address [host]:[port]")
3752
returncmd
3853
}
3954

40-
typeversionResultstruct {
41-
AppNamestring`json:"appName"`
55+
funcversionHandler(clientVersionstring,hoststring) {
56+
httpClient:= http.Client{
57+
Timeout:time.Second,
58+
}
59+
result:=doVersionHandler(httpClient,clientVersion,host)
60+
feedback.PrintResult(result)
61+
}
62+
63+
funcdoVersionHandler(httpClient http.Client,clientVersionstring,hoststring)versionResult {
64+
url,err:=getValidOrDefaultUrl(host)
65+
iferr!=nil {
66+
feedback.Fatal(i18n.Tr("Error: invalid host:port format"),feedback.ErrBadArgument)
67+
}
68+
69+
serverVersion,err:=getServerVersion(httpClient,url)
70+
iferr!=nil {
71+
serverVersion=fmt.Sprintf("n/a (cannot connect to the server %s://%s)",url.Scheme,url.Host)
72+
}
73+
74+
returnversionResult{
75+
ClientVersion:clientVersion,
76+
ServerVersion:serverVersion,
77+
}
78+
}
79+
80+
funcgetValidOrDefaultUrl(hostPortstring) (url.URL,error) {
81+
host:=DefaultHostname
82+
port:=DefaultPort
83+
84+
ifhostPort!="" {
85+
h,p,err:=net.SplitHostPort(hostPort)
86+
iferr!=nil {
87+
return url.URL{},err
88+
}
89+
ifh!="" {
90+
host=h
91+
}
92+
ifp!="" {
93+
port=p
94+
}
95+
96+
}
97+
98+
hostAndPort:=net.JoinHostPort(host,port)
99+
100+
u:= url.URL{
101+
Scheme:"http",
102+
Host:hostAndPort,
103+
Path:"/v1/version",
104+
}
105+
106+
returnu,nil
107+
}
108+
109+
funcgetServerVersion(httpClient http.Client,url url.URL) (string,error) {
110+
resp,err:=httpClient.Get(url.String())
111+
iferr!=nil {
112+
return"",err
113+
}
114+
deferresp.Body.Close()
115+
116+
ifresp.StatusCode!=http.StatusOK {
117+
return"",fmt.Errorf("request failed with status %d",resp.StatusCode)
118+
}
119+
120+
body,err:=io.ReadAll(resp.Body)
121+
iferr!=nil {
122+
return"",err
123+
}
124+
125+
varserverResponseserverVersionResponse
126+
iferr:=json.Unmarshal(body,&serverResponse);err!=nil {
127+
return"",err
128+
}
129+
130+
returnserverResponse.Version,nil
131+
}
132+
133+
typeserverVersionResponsestruct {
42134
Versionstring`json:"version"`
43135
}
44136

137+
typeversionResultstruct {
138+
ClientVersionstring`json:"version"`
139+
ServerVersionstring`json:"serverVersion"`
140+
}
141+
45142
func (rversionResult)String()string {
46-
returnfmt.Sprintf("%s v%s",r.AppName,r.Version)
143+
returnfmt.Sprintf("client: %s\nserver: %s",
144+
r.ClientVersion,r.ServerVersion)
47145
}
48146

49147
func (rversionResult)Data()interface{} {
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package version
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"io"
7+
"net/http"
8+
"strings"
9+
"testing"
10+
11+
"github.com/stretchr/testify/require"
12+
)
13+
14+
funcTestServerVersion(t*testing.T) {
15+
clientVersion:="5.1-dev"
16+
17+
testCases:= []struct {
18+
namestring
19+
serverStubTripper
20+
expectedResultversionResult
21+
hoststring
22+
}{
23+
{
24+
name:"return the server version when the server is up",
25+
serverStub:successServer,
26+
expectedResult:versionResult{
27+
ClientVersion:"5.1-dev",
28+
ServerVersion:"3.0",
29+
},
30+
host:"",
31+
},
32+
{
33+
name:"return error if default server is not listening",
34+
serverStub:failureServer,
35+
expectedResult:versionResult{
36+
ClientVersion:"5.1-dev",
37+
ServerVersion:fmt.Sprintf("n/a (cannot connect to the server http://%s:%s)",DefaultHostname,DefaultPort),
38+
},
39+
host:"",
40+
},
41+
{
42+
name:"return error if provided server is not listening",
43+
serverStub:failureServer,
44+
expectedResult:versionResult{
45+
ClientVersion:"5.1-dev",
46+
ServerVersion:"n/a (cannot connect to the server http://unreacheable:123)",
47+
},
48+
host:"unreacheable:123",
49+
},
50+
{
51+
name:"return error for server resopnse 500 Internal Server Error",
52+
serverStub:failureInternalServerError,
53+
expectedResult:versionResult{
54+
ClientVersion:"5.1-dev",
55+
ServerVersion:"n/a (cannot connect to the server http://unreacheable:123)",
56+
},
57+
host:"unreacheable:123",
58+
},
59+
}
60+
for_,tc:=rangetestCases {
61+
t.Run(tc.name,func(t*testing.T) {
62+
// arrange
63+
httpClient:= http.Client{}
64+
httpClient.Transport=tc.serverStub
65+
66+
// act
67+
result:=doVersionHandler(httpClient,clientVersion,tc.host)
68+
69+
// assert
70+
require.Equal(t,tc.expectedResult,result)
71+
})
72+
}
73+
}
74+
75+
// Leverage the http.Client's RoundTripper
76+
// to return a canned response and bypass network calls.
77+
typeTripperfunc(*http.Request) (*http.Response,error)
78+
79+
func (tTripper)RoundTrip(request*http.Request) (*http.Response,error) {
80+
returnt(request)
81+
}
82+
83+
varsuccessServer=Tripper(func(*http.Request) (*http.Response,error) {
84+
body:=io.NopCloser(strings.NewReader(`{"version":"3.0"}`))
85+
return&http.Response{
86+
StatusCode:http.StatusOK,
87+
Body:body,
88+
},nil
89+
})
90+
91+
varfailureServer=Tripper(func(*http.Request) (*http.Response,error) {
92+
returnnil,errors.New("connetion refused")
93+
})
94+
95+
varfailureInternalServerError=Tripper(func(*http.Request) (*http.Response,error) {
96+
return&http.Response{
97+
StatusCode:http.StatusInternalServerError,
98+
Body:io.NopCloser(strings.NewReader("")),
99+
},nil
100+
})

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp