Skip to content

Commit 8800552

Browse files
committed
api wip
1 parent 6de9f4f commit 8800552

File tree

7 files changed

+363
-17
lines changed

7 files changed

+363
-17
lines changed

.env

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ SHELLHUB_VERSION=v0.14.2
77
# This specification details the network interface to which the gateway container will be bound.
88
SHELLHUB_BIND_ADDRESS=0.0.0.0
99

10+
SHELLHUB_API_PORT=8080
11+
1012
# The HTTP listen port for the ShellHub web-based GUI, API and Reverse SSH tunnel.
1113
# Values: any free port on host
1214
SHELLHUB_HTTP_PORT=80

api/server.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ var serverCmd = &cobra.Command{
6363
// Provides the configuration for the API service.
6464
// The values are load from the system environment variables.
6565
type config struct {
66+
HttpPort string `env:"HTTP_PORT"`
6667
// MongoDB connection string (URI format)
6768
MongoURI string `env:"MONGO_URI,default=mongodb://mongo:27017/main"`
6869
// Redis connection string (URI format)
@@ -155,7 +156,7 @@ func startServer(cfg *config, store store.Store, cache storecache.Cache) error {
155156
}
156157
})
157158

158-
e.Logger.Fatal(e.Start(":8080"))
159+
e.Logger.Fatal(e.Start(":" + cfg.HttpPort))
159160

160161
return nil
161162
}

docker-compose.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ services:
2727
image: shellhubio/api:${SHELLHUB_VERSION}
2828
restart: unless-stopped
2929
environment:
30+
- HTTP_PORT=${SHELLHUB_API_PORT}
3031
- SHELLHUB_VERSION=${SHELLHUB_VERSION}
3132
- PRIVATE_KEY=/run/secrets/api_private_key
3233
- PUBLIC_KEY=/run/secrets/api_public_key
@@ -57,7 +58,7 @@ services:
5758
networks:
5859
- shellhub
5960
healthcheck:
60-
test: "curl -f http://api:8080/api/healthcheck || exit 1"
61+
test: "curl -f http://api:${SHELLHUB_API_PORT}/api/healthcheck || exit 1"
6162
interval: 30s
6263
start_period: 10s
6364
ui:
@@ -81,6 +82,7 @@ services:
8182
image: shellhubio/gateway:${SHELLHUB_VERSION}
8283
restart: unless-stopped
8384
environment:
85+
- SHELLHUB_API_PORT=${SHELLHUB_API_PORT}
8486
- SHELLHUB_DOMAIN=${SHELLHUB_DOMAIN}
8587
- SHELLHUB_PUBLIC_URL_DOMAIN=${SHELLHUB_PUBLIC_URL_DOMAIN}
8688
- SHELLHUB_VERSION=${SHELLHUB_VERSION}

gateway/conf.d/shellhub.conf

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ server {
2424
server_name {{ (env.Getenv "SHELLHUB_DOMAIN") }};
2525
resolver 127.0.0.11 ipv6=off;
2626

27+
set $api_port {{ env.Getenv "SHELLHUB_API_PORT" }};
28+
set $api_endpoint "api:${api_port}";
29+
30+
# set $api_endpoint "api:${(env.Getenv 'SHELLHUB_API_PORT')}";
31+
2732
# Load configuration files for the default server block
2833
include /etc/nginx/default.d/*.conf;
2934

@@ -53,7 +58,7 @@ server {
5358
}
5459

5560
location /api {
56-
set $upstream api:8080;
61+
set $upstream $api_endpoint;
5762

5863
auth_request /auth;
5964
auth_request_set $tenant_id $upstream_http_x_tenant_id;
@@ -75,7 +80,7 @@ server {
7580
}
7681

7782
location ~ ^/(install.sh|kickstart.sh)$ {
78-
set $upstream api:8080;
83+
set $upstream $api_endpoint;
7984
rewrite ^/(.*)$ /api/install break;
8085
proxy_set_header X-Forwarded-Host $host;
8186
proxy_set_header X-Forwarded-Proto $x_forwarded_proto;
@@ -84,7 +89,7 @@ server {
8489
}
8590

8691
location /api/auth/user {
87-
set $upstream api:8080;
92+
set $upstream $api_endpoint;
8893

8994
auth_request /auth/skip;
9095
auth_request_set $tenant_id $upstream_http_x_tenant_id;
@@ -188,7 +193,7 @@ server {
188193
}
189194

190195
location /ssh/auth {
191-
set $upstream api:8080;
196+
set $upstream $api_endpoint;
192197
auth_request /auth;
193198
auth_request_set $device_uid $upstream_http_x_device_uid;
194199
error_page 500 =401 /auth;
@@ -357,7 +362,7 @@ server {
357362
}
358363

359364
location /api/devices/auth {
360-
set $upstream api:8080;
365+
set $upstream $api_endpoint;
361366
auth_request off;
362367
rewrite ^/api/(.*)$ /api/$1 break;
363368
{{ if bool (env.Getenv "SHELLHUB_PROXY") -}}
@@ -369,7 +374,7 @@ server {
369374
}
370375

371376
location /api/login {
372-
set $upstream api:8080;
377+
set $upstream $api_endpoint;
373378
auth_request off;
374379
rewrite ^/api/(.*)$ /api/$1 break;
375380
proxy_pass http://$upstream;
@@ -383,14 +388,14 @@ server {
383388
}
384389

385390
location /auth {
386-
set $upstream_auth api:8080;
391+
set $upstream_auth $api_endpoint;
387392
internal;
388393
rewrite ^/(.*)$ /internal/$1 break;
389394
proxy_pass http://$upstream_auth;
390395
}
391396

392397
location /auth/skip {
393-
set $upstream_auth api:8080;
398+
set $upstream_auth $api_endpoint;
394399
internal;
395400
rewrite ^/auth/(.*)$ /internal/auth?args=$1 break;
396401
proxy_pass http://$upstream_auth;
@@ -414,7 +419,7 @@ server {
414419
}
415420

416421
location /info {
417-
set $upstream api:8080;
422+
set $upstream $api_endpoint;
418423

419424
proxy_set_header X-Forwarded-Host $host;
420425
proxy_set_header X-Forwarded-Port $x_forwarded_port;

tests/api_test.go

Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
"strings"
8+
"testing"
9+
10+
"github.com/go-resty/resty/v2"
11+
"github.com/shellhub-io/shellhub/pkg/models"
12+
"github.com/sirupsen/logrus"
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
func ReadToString(reader io.Reader, dst *string) error {
17+
buf := new(strings.Builder)
18+
19+
_, err := io.Copy(buf, reader)
20+
if err != nil {
21+
return err
22+
}
23+
24+
*dst = buf.String()
25+
26+
return nil
27+
}
28+
29+
func TestDevSetup(t *testing.T) {
30+
t.Parallel()
31+
32+
ctx := context.TODO()
33+
34+
instance := NewDockerCompose()
35+
36+
type CommandResponse struct {
37+
msg string
38+
code int
39+
}
40+
41+
type Expected struct {
42+
userMsg string
43+
nsMsg string
44+
}
45+
46+
cases := []struct {
47+
description string
48+
test func(compose *DockerCompose) (*Expected, error)
49+
expected Expected
50+
}{
51+
{
52+
description: "succeeds",
53+
test: func(dockerCompose *DockerCompose) (*Expected, error) {
54+
cli := dockerCompose.GetServiceCLI()
55+
56+
// Try to create a new user
57+
_, reader, err := cli.Exec(ctx, strings.Split("./cli user create john_doe secret [email protected]", " "))
58+
if err != nil {
59+
return nil, err
60+
}
61+
62+
var userRes string
63+
if err := ReadToString(reader, &userRes); err != nil {
64+
return nil, err
65+
}
66+
67+
// Try to create a new namespace
68+
_, reader, err = cli.Exec(ctx, strings.Split("./cli namespace create dev john_doe 00000000-0000-4000-0000-000000000000", " "))
69+
if err != nil {
70+
return nil, err
71+
}
72+
73+
var nsRes string
74+
if err := ReadToString(reader, &nsRes); err != nil {
75+
return nil, err
76+
}
77+
78+
userAuth := new(models.UserAuthResponse)
79+
_, err = resty.
80+
New().
81+
R().
82+
SetBody(map[string]string{
83+
"username": "john_doe",
84+
"password": "secret",
85+
}).
86+
SetResult(userAuth).
87+
Post(fmt.Sprintf("http://localhost:%s/api/login", dockerCompose.GetEnv("SHELLHUB_HTTP_PORT")))
88+
if err != nil {
89+
return nil, err
90+
}
91+
92+
devicesList := make([]models.Device, 1)
93+
res, err := resty.
94+
New().
95+
R().
96+
SetHeader("authorization", fmt.Sprintf("Bearer %s", userAuth.Token)).
97+
SetResult(&devicesList).
98+
Get(fmt.Sprintf("http://localhost:%s/api/devices", dockerCompose.GetEnv("SHELLHUB_HTTP_PORT")))
99+
if err != nil {
100+
return nil, err
101+
}
102+
for _, device := range devicesList {
103+
logrus.Infof("%+v", device)
104+
}
105+
106+
logrus.Info("body: ", string(res.Body()))
107+
108+
_, err = resty.
109+
New().
110+
R().
111+
SetHeader("authorization", fmt.Sprintf("Bearer %s", userAuth.Token)).
112+
Patch(fmt.Sprintf("http://localhost:%s/api/devices/%s/accept", dockerCompose.GetEnv("SHELLHUB_HTTP_PORT"), devicesList[0].UID))
113+
if err != nil {
114+
return nil, err
115+
}
116+
117+
devicesList = make([]models.Device, 1)
118+
_, err = resty.
119+
New().
120+
R().
121+
SetHeader("authorization", fmt.Sprintf("Bearer %s", userAuth.Token)).
122+
SetResult(&devicesList).
123+
Get(fmt.Sprintf("http://localhost:%s/api/devices", dockerCompose.GetEnv("SHELLHUB_HTTP_PORT")))
124+
if err != nil {
125+
return nil, err
126+
}
127+
for _, device := range devicesList {
128+
logrus.Infof("%+v", device)
129+
}
130+
131+
return &Expected{
132+
userMsg: userRes,
133+
nsMsg: nsRes,
134+
}, nil
135+
},
136+
expected: Expected{
137+
// TODO: how can we assert the exit's code?
138+
userMsg: "\nUsername: john_doe\nEmail: [email protected]\n",
139+
nsMsg: "Namespace created successfully\nNamespace: dev\nTenant: 00000000-0000-4000-0000-000000000000\nOwner:", // TODO: how can we assert the Owner ID?
140+
},
141+
},
142+
}
143+
144+
for _, tt := range cases {
145+
tc := tt
146+
147+
t.Run(tc.description, func(t *testing.T) {
148+
t.Parallel()
149+
dockerCompose := instance.Clone()
150+
151+
teardown, err := dockerCompose.Start()
152+
if !assert.NoError(t, err) {
153+
t.Fatal(err)
154+
}
155+
defer teardown() // nolint: errcheck
156+
157+
actual, err := tc.test(dockerCompose)
158+
if assert.NoError(t, err) {
159+
assert.Contains(t, actual.userMsg, tc.expected.userMsg)
160+
assert.Contains(t, actual.nsMsg, tc.expected.nsMsg)
161+
}
162+
})
163+
}
164+
}

0 commit comments

Comments
 (0)