Skip to content

Commit 982ff0d

Browse files
authored
Split Operator and Management API into different Swagger files (#875)
* Split Operator and Management API into different Swagger files Signed-off-by: Daniel Valdivia <[email protected]> * Linting Signed-off-by: Daniel Valdivia <[email protected]>
1 parent 63582de commit 982ff0d

File tree

228 files changed

+24142
-13148
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

228 files changed

+24142
-13148
lines changed

Makefile

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,22 @@ install: console
4343
@mkdir -p $(GOPATH)/bin && cp -f $(PWD)/console $(GOPATH)/bin/console
4444
@echo "Installation successful. To learn more, try \"console --help\"."
4545

46-
swagger-gen:
47-
@echo "Generating swagger server code from yaml"
46+
swagger-gen: clean-swagger swagger-console swagger-operator
47+
@echo "Done Generating swagger server code from yaml"
48+
49+
clean-swagger:
50+
@echo "cleaning"
4851
@rm -rf models
4952
@rm -rf restapi/operations
50-
@swagger generate server -A console --main-package=console --exclude-main -P models.Principal -f ./swagger.yml -r NOTICE
53+
@rm -rf operatorapi/operations
54+
55+
swagger-console:
56+
@echo "Generating swagger server code from yaml"
57+
@swagger generate server -A console --main-package=management --server-package=restapi --exclude-main -P models.Principal -f ./swagger-console.yml -r NOTICE
58+
59+
swagger-operator:
60+
@echo "Generating swagger server code from yaml"
61+
@swagger generate server -A operator --main-package=operator --server-package=operatorapi --exclude-main -P models.Principal -f ./swagger-operator.yml -r NOTICE
5162

5263
assets:
5364
@(cd portal-ui; yarn install; make build-static; yarn prettier --write . --loglevel warn; cd ..)

cmd/console/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ VERSION:
5353
var appCmds = []cli.Command{
5454
serverCmd,
5555
updateCmd,
56+
operatorCmd,
5657
}
5758

5859
func newApp(name string) *cli.App {

cmd/console/operator.go

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// This file is part of MinIO Console Server
2+
// Copyright (c) 2021 MinIO, Inc.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package main
18+
19+
import (
20+
"fmt"
21+
"io/ioutil"
22+
"path/filepath"
23+
"strconv"
24+
"time"
25+
26+
"github.com/minio/console/restapi"
27+
28+
"github.com/go-openapi/loads"
29+
"github.com/jessevdk/go-flags"
30+
"github.com/minio/cli"
31+
"github.com/minio/console/operatorapi"
32+
"github.com/minio/console/operatorapi/operations"
33+
"github.com/minio/console/pkg/certs"
34+
)
35+
36+
// starts the server
37+
var operatorCmd = cli.Command{
38+
Name: "operator",
39+
Aliases: []string{"opr"},
40+
Usage: "Start MinIO Operator UI server",
41+
Action: startOperatorServer,
42+
Flags: []cli.Flag{
43+
cli.StringFlag{
44+
Name: "host",
45+
Value: restapi.GetHostname(),
46+
Usage: "bind to a specific HOST, HOST can be an IP or hostname",
47+
},
48+
cli.IntFlag{
49+
Name: "port",
50+
Value: restapi.GetPort(),
51+
Usage: "bind to specific HTTP port",
52+
},
53+
// This is kept here for backward compatibility,
54+
// hostname's do not have HTTP or HTTPs
55+
// hostnames are opaque so using --host
56+
// works for both HTTP and HTTPS setup.
57+
cli.StringFlag{
58+
Name: "tls-host",
59+
Value: restapi.GetHostname(),
60+
Hidden: true,
61+
},
62+
cli.StringFlag{
63+
Name: "certs-dir",
64+
Value: certs.GlobalCertsCADir.Get(),
65+
Usage: "path to certs directory",
66+
},
67+
cli.IntFlag{
68+
Name: "tls-port",
69+
Value: restapi.GetTLSPort(),
70+
Usage: "bind to specific HTTPS port",
71+
},
72+
cli.StringFlag{
73+
Name: "tls-redirect",
74+
Value: restapi.GetTLSRedirect(),
75+
Usage: "toggle HTTP->HTTPS redirect",
76+
},
77+
cli.StringFlag{
78+
Name: "tls-certificate",
79+
Value: "",
80+
Usage: "path to TLS public certificate",
81+
Hidden: true,
82+
},
83+
cli.StringFlag{
84+
Name: "tls-key",
85+
Value: "",
86+
Usage: "path to TLS private key",
87+
Hidden: true,
88+
},
89+
cli.StringFlag{
90+
Name: "tls-ca",
91+
Value: "",
92+
Usage: "path to TLS Certificate Authority",
93+
Hidden: true,
94+
},
95+
},
96+
}
97+
98+
func buildOperatorServer() (*operatorapi.Server, error) {
99+
swaggerSpec, err := loads.Embedded(operatorapi.SwaggerJSON, operatorapi.FlatSwaggerJSON)
100+
if err != nil {
101+
return nil, err
102+
}
103+
104+
api := operations.NewOperatorAPI(swaggerSpec)
105+
api.Logger = operatorapi.LogInfo
106+
server := operatorapi.NewServer(api)
107+
108+
parser := flags.NewParser(server, flags.Default)
109+
parser.ShortDescription = "MinIO Console Server"
110+
parser.LongDescription = swaggerSpec.Spec().Info.Description
111+
112+
server.ConfigureFlags()
113+
114+
// register all APIs
115+
server.ConfigureAPI()
116+
117+
for _, optsGroup := range api.CommandLineOptionsGroups {
118+
_, err := parser.AddGroup(optsGroup.ShortDescription, optsGroup.LongDescription, optsGroup.Options)
119+
if err != nil {
120+
return nil, err
121+
}
122+
}
123+
124+
if _, err := parser.Parse(); err != nil {
125+
return nil, err
126+
}
127+
128+
return server, nil
129+
}
130+
131+
func loadOperatorAllCerts(ctx *cli.Context) error {
132+
var err error
133+
// Set all certs and CAs directories path
134+
certs.GlobalCertsDir, _, err = certs.NewConfigDirFromCtx(ctx, "certs-dir", certs.DefaultCertsDir.Get)
135+
if err != nil {
136+
return err
137+
}
138+
139+
certs.GlobalCertsCADir = &certs.ConfigDir{Path: filepath.Join(certs.GlobalCertsDir.Get(), certs.CertsCADir)}
140+
// check if certs and CAs directories exists or can be created
141+
if err = certs.MkdirAllIgnorePerm(certs.GlobalCertsCADir.Get()); err != nil {
142+
return fmt.Errorf("unable to create certs CA directory at %s: failed with %w", certs.GlobalCertsCADir.Get(), err)
143+
}
144+
145+
// load the certificates and the CAs
146+
operatorapi.GlobalRootCAs, operatorapi.GlobalPublicCerts, operatorapi.GlobalTLSCertsManager, err = certs.GetAllCertificatesAndCAs()
147+
if err != nil {
148+
return fmt.Errorf("unable to load certificates at %s: failed with %w", certs.GlobalCertsDir.Get(), err)
149+
}
150+
151+
{
152+
// TLS flags from swagger server, used to support VMware vsphere operator version.
153+
swaggerServerCertificate := ctx.String("tls-certificate")
154+
swaggerServerCertificateKey := ctx.String("tls-key")
155+
swaggerServerCACertificate := ctx.String("tls-ca")
156+
// load tls cert and key from swagger server tls-certificate and tls-key flags
157+
if swaggerServerCertificate != "" && swaggerServerCertificateKey != "" {
158+
if err = operatorapi.GlobalTLSCertsManager.AddCertificate(swaggerServerCertificate, swaggerServerCertificateKey); err != nil {
159+
return err
160+
}
161+
x509Certs, err := certs.ParsePublicCertFile(swaggerServerCertificate)
162+
if err == nil {
163+
operatorapi.GlobalPublicCerts = append(operatorapi.GlobalPublicCerts, x509Certs...)
164+
}
165+
}
166+
167+
// load ca cert from swagger server tls-ca flag
168+
if swaggerServerCACertificate != "" {
169+
caCert, caCertErr := ioutil.ReadFile(swaggerServerCACertificate)
170+
if caCertErr == nil {
171+
operatorapi.GlobalRootCAs.AppendCertsFromPEM(caCert)
172+
}
173+
}
174+
}
175+
176+
return nil
177+
}
178+
179+
// StartServer starts the console service
180+
func startOperatorServer(ctx *cli.Context) error {
181+
if err := loadOperatorAllCerts(ctx); err != nil {
182+
// Log this as a warning and continue running console without TLS certificates
183+
operatorapi.LogError("Unable to load certs: %v", err)
184+
}
185+
186+
var rctx operatorapi.Context
187+
if err := rctx.Load(ctx); err != nil {
188+
operatorapi.LogError("argument validation failed: %v", err)
189+
return err
190+
}
191+
192+
server, err := buildOperatorServer()
193+
if err != nil {
194+
operatorapi.LogError("Unable to initialize console server: %v", err)
195+
return err
196+
}
197+
198+
server.Host = rctx.Host
199+
server.Port = rctx.HTTPPort
200+
// set conservative timesout for uploads
201+
server.ReadTimeout = 1 * time.Hour
202+
// no timeouts for response for downloads
203+
server.WriteTimeout = 0
204+
operatorapi.Port = strconv.Itoa(server.Port)
205+
operatorapi.Hostname = server.Host
206+
207+
if len(operatorapi.GlobalPublicCerts) > 0 {
208+
// If TLS certificates are provided enforce the HTTPS schema, meaning console will redirect
209+
// plain HTTP connections to HTTPS server
210+
server.EnabledListeners = []string{"http", "https"}
211+
server.TLSPort = rctx.HTTPSPort
212+
// Need to store tls-port, tls-host un config variables so secure.middleware can read from there
213+
operatorapi.TLSPort = strconv.Itoa(server.TLSPort)
214+
operatorapi.Hostname = rctx.Host
215+
operatorapi.TLSRedirect = rctx.TLSRedirect
216+
}
217+
218+
defer server.Shutdown()
219+
220+
// subnet license refresh process
221+
go func() {
222+
// start refreshing subnet license after 5 seconds..
223+
time.Sleep(time.Second * 5)
224+
225+
failedAttempts := 0
226+
for {
227+
if err := operatorapi.RefreshLicense(); err != nil {
228+
operatorapi.LogError("Refreshing subnet license failed: %v", err)
229+
failedAttempts++
230+
// end license refresh after 3 consecutive failed attempts
231+
if failedAttempts >= 3 {
232+
return
233+
}
234+
// wait 5 minutes and retry again
235+
time.Sleep(time.Minute * 5)
236+
continue
237+
}
238+
// if license refreshed successfully reset the counter
239+
failedAttempts = 0
240+
// try to refresh license every 24 hrs
241+
time.Sleep(time.Hour * 24)
242+
}
243+
}()
244+
245+
return server.Serve()
246+
}

cmd/console/server.go

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package main
1919
import (
2020
"fmt"
2121
"io/ioutil"
22+
"os"
2223
"path/filepath"
2324
"strconv"
2425
"time"
@@ -156,7 +157,8 @@ func loadAllCerts(ctx *cli.Context) error {
156157
if err = restapi.GlobalTLSCertsManager.AddCertificate(swaggerServerCertificate, swaggerServerCertificateKey); err != nil {
157158
return err
158159
}
159-
if x509Certs, err := certs.ParsePublicCertFile(swaggerServerCertificate); err == nil {
160+
x509Certs, err := certs.ParsePublicCertFile(swaggerServerCertificate)
161+
if err == nil {
160162
restapi.GlobalPublicCerts = append(restapi.GlobalPublicCerts, x509Certs...)
161163
}
162164
}
@@ -175,6 +177,10 @@ func loadAllCerts(ctx *cli.Context) error {
175177

176178
// StartServer starts the console service
177179
func StartServer(ctx *cli.Context) error {
180+
if os.Getenv("CONSOLE_OPERATOR_MODE") != "" && os.Getenv("CONSOLE_OPERATOR_MODE") == "on" {
181+
return startOperatorServer(ctx)
182+
}
183+
178184
if err := loadAllCerts(ctx); err != nil {
179185
// Log this as a warning and continue running console without TLS certificates
180186
restapi.LogError("Unable to load certs: %v", err)
@@ -214,30 +220,5 @@ func StartServer(ctx *cli.Context) error {
214220

215221
defer server.Shutdown()
216222

217-
// subnet license refresh process
218-
go func() {
219-
// start refreshing subnet license after 5 seconds..
220-
time.Sleep(time.Second * 5)
221-
222-
failedAttempts := 0
223-
for {
224-
if err := restapi.RefreshLicense(); err != nil {
225-
restapi.LogError("Refreshing subnet license failed: %v", err)
226-
failedAttempts++
227-
// end license refresh after 3 consecutive failed attempts
228-
if failedAttempts >= 3 {
229-
return
230-
}
231-
// wait 5 minutes and retry again
232-
time.Sleep(time.Minute * 5)
233-
continue
234-
}
235-
// if license refreshed successfully reset the counter
236-
failedAttempts = 0
237-
// try to refresh license every 24 hrs
238-
time.Sleep(time.Hour * 24)
239-
}
240-
}()
241-
242223
return server.Serve()
243224
}

0 commit comments

Comments
 (0)