add builder files
add missing vendor folder
This commit is contained in:
34
pkg/apis/v1alpha/install.go
Normal file
34
pkg/apis/v1alpha/install.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package v1alpha
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/nodes"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
ws := new(restful.WebService)
|
||||
ws.Path("/api/v1alpha")
|
||||
|
||||
nodes.Register(ws,"/nodes")
|
||||
|
||||
// add webservice to default container
|
||||
restful.Add(ws)
|
||||
|
||||
}
|
||||
33
pkg/apis/v1alpha/nodes/nodes_handler.go
Normal file
33
pkg/apis/v1alpha/nodes/nodes_handler.go
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package nodes
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
"kubesphere.io/kubesphere/pkg/filter/route"
|
||||
)
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
ws.Route(ws.GET(subPath).To(models.HandleNodes).Filter(route.RouteLogging)).
|
||||
Consumes(restful.MIME_JSON, restful.MIME_XML).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
}
|
||||
|
||||
|
||||
89
pkg/app/app.go
Normal file
89
pkg/app/app.go
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
_ "kubesphere.io/kubesphere/pkg/apis/v1alpha"
|
||||
"kubesphere.io/kubesphere/pkg/options"
|
||||
"net"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type kubeSphereServer struct {
|
||||
insecureBindAddress net.IP
|
||||
bindAddress net.IP
|
||||
insecurePort int
|
||||
port int
|
||||
certFile string
|
||||
keyFile string
|
||||
container *restful.Container
|
||||
}
|
||||
|
||||
func newKubeSphereServer(options *options.ServerRunOptions) *kubeSphereServer {
|
||||
|
||||
s := kubeSphereServer{
|
||||
insecureBindAddress: options.GetInsecureBindAddress(),
|
||||
bindAddress: options.GetBindAddress(),
|
||||
insecurePort: options.GetInsecurePort(),
|
||||
port: options.GetPort(),
|
||||
certFile: options.GetCertFile(),
|
||||
keyFile: options.GetKeyFile(),
|
||||
}
|
||||
|
||||
return &s
|
||||
}
|
||||
|
||||
func (server *kubeSphereServer) run() {
|
||||
|
||||
if len(server.certFile) > 0 && len(server.keyFile) > 0 {
|
||||
servingCert, err := tls.LoadX509KeyPair(server.certFile, server.keyFile)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
secureAddr := fmt.Sprintf("%s:%d", server.bindAddress, server.port)
|
||||
glog.Infof("Serving securely on addr: %s", secureAddr)
|
||||
|
||||
httpServer := &http.Server{
|
||||
Addr: secureAddr,
|
||||
Handler: restful.DefaultContainer,
|
||||
TLSConfig: &tls.Config{Certificates: []tls.Certificate{servingCert}},
|
||||
}
|
||||
|
||||
go func() { glog.Fatal(httpServer.ListenAndServeTLS("", "")) }()
|
||||
|
||||
} else {
|
||||
insecureAddr := fmt.Sprintf("%s:%d", server.insecureBindAddress, server.insecurePort)
|
||||
glog.Infof("Serving insecurely on addr: %s", insecureAddr)
|
||||
|
||||
go func() { glog.Fatal(http.ListenAndServe(insecureAddr, nil)) }()
|
||||
}
|
||||
|
||||
select {}
|
||||
}
|
||||
|
||||
func Run() {
|
||||
|
||||
server := newKubeSphereServer(options.ServerOptions)
|
||||
|
||||
server.run()
|
||||
}
|
||||
43
pkg/client/heapsterclient.go
Normal file
43
pkg/client/heapsterclient.go
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"os"
|
||||
"io/ioutil"
|
||||
)
|
||||
|
||||
|
||||
func GetHeapsterMetrics(url string) string {
|
||||
response, err := http.Get(url)
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
os.Exit(1)
|
||||
} else {
|
||||
defer response.Body.Close()
|
||||
contents, err := ioutil.ReadAll(response.Body)
|
||||
if err != nil {
|
||||
fmt.Printf("%s", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
return string(contents)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
17
pkg/client/k8sclient.go
Normal file
17
pkg/client/k8sclient.go
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
30
pkg/constants/common.go
Normal file
30
pkg/constants/common.go
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package constants
|
||||
|
||||
type ResultMessage struct {
|
||||
|
||||
Kind string `json:"kind"`
|
||||
ApiVersion string `json:"apiVersion"`
|
||||
Data interface{} `json:"data"`
|
||||
|
||||
|
||||
}
|
||||
|
||||
const APIVERSION = "v1alpha"
|
||||
|
||||
const KIND = "kubesphere"
|
||||
25
pkg/filter/container/install.go
Normal file
25
pkg/filter/container/install.go
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package container
|
||||
|
||||
import "github.com/emicklei/go-restful"
|
||||
|
||||
// add filter to default container
|
||||
func init() {
|
||||
|
||||
restful.Filter(logFilter())
|
||||
}
|
||||
37
pkg/filter/container/logFilter.go
Normal file
37
pkg/filter/container/logFilter.go
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package container
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func logFilter() restful.FilterFunction {
|
||||
return func(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
chain.ProcessFilter(req, resp)
|
||||
glog.Infof("%s - \"%s %s %s\" %d %d",
|
||||
strings.Split(req.Request.RemoteAddr, ":")[0],
|
||||
req.Request.Method,
|
||||
req.Request.URL.RequestURI(),
|
||||
req.Request.Proto,
|
||||
resp.StatusCode(),
|
||||
resp.ContentLength(),
|
||||
)
|
||||
}
|
||||
}
|
||||
38
pkg/filter/route/route_fliter.go
Normal file
38
pkg/filter/route/route_fliter.go
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package route
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Route Filter (defines FilterFunction)
|
||||
func RouteLogging(req *restful.Request, resp *restful.Response, chain *restful.FilterChain) {
|
||||
|
||||
chain.ProcessFilter(req, resp)
|
||||
glog.Infof("%s - \"%s %s %s\" %d %d",
|
||||
strings.Split(req.Request.RemoteAddr, ":")[0],
|
||||
req.Request.Method,
|
||||
req.Request.URL.RequestURI(),
|
||||
req.Request.Proto,
|
||||
resp.StatusCode(),
|
||||
resp.ContentLength(),
|
||||
)
|
||||
|
||||
}
|
||||
52
pkg/logs/logs.go
Normal file
52
pkg/logs/logs.go
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package logs
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"log"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
||||
flag.Set("logtostderr", "true")
|
||||
}
|
||||
|
||||
// GlogWriter serves as a bridge between the standard log package and the glog package.
|
||||
type GlogWriter struct{}
|
||||
|
||||
// Write implements the io.Writer interface.
|
||||
func (writer GlogWriter) Write(data []byte) (n int, err error) {
|
||||
|
||||
glog.Info(string(data))
|
||||
return len(data), nil
|
||||
}
|
||||
|
||||
// InitLogs initializes logs the way we want for kubeSphere.
|
||||
func InitLogs() {
|
||||
|
||||
log.SetOutput(GlogWriter{})
|
||||
log.SetFlags(0)
|
||||
}
|
||||
|
||||
// FlushLogs flushes logs immediately.
|
||||
func FlushLogs() {
|
||||
|
||||
glog.Flush()
|
||||
}
|
||||
49
pkg/models/nodes.go
Normal file
49
pkg/models/nodes.go
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
type ResultMessage struct {
|
||||
Ret int `json:"ret"`
|
||||
Msg string `json:"msg"`
|
||||
Data interface{} `json:"data"`
|
||||
}
|
||||
|
||||
func HandleNodes(request *restful.Request, response *restful.Response) {
|
||||
|
||||
var result ResultMessage
|
||||
|
||||
|
||||
data := make(map[string]string)
|
||||
|
||||
|
||||
data["output"] = client.GetHeapsterMetrics("http://139.198.0.79/api/monitor/v1/model/namespaces/kube-system/pods/qingcloud-volume-provisioner-i-o5pmakm7/metrics/cpu/request")
|
||||
|
||||
result.Data = data
|
||||
result.Ret = http.StatusOK
|
||||
result.Msg = "success"
|
||||
glog.Infoln(result)
|
||||
response.WriteAsJson(result)
|
||||
}
|
||||
107
pkg/options/options.go
Normal file
107
pkg/options/options.go
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2018 The Kubesphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package options contains flags and options for initializing an apiserver
|
||||
package options
|
||||
|
||||
import (
|
||||
goflag "flag"
|
||||
"github.com/spf13/pflag"
|
||||
"net"
|
||||
)
|
||||
|
||||
// ServerRunOptions runs a kubernetes api server.
|
||||
type ServerRunOptions struct {
|
||||
apiServerHost string
|
||||
insecurePort int
|
||||
port int
|
||||
insecureBindAddress net.IP
|
||||
bindAddress net.IP
|
||||
certFile string
|
||||
keyFile string
|
||||
kubeConfigFile string
|
||||
}
|
||||
|
||||
// NewServerRunOptions creates a new ServerRunOptions object with default parameters
|
||||
func NewServerRunOptions() *ServerRunOptions {
|
||||
s := ServerRunOptions{}
|
||||
return &s
|
||||
}
|
||||
|
||||
// AddFlags adds flags for a specific APIServer to the specified FlagSet
|
||||
func (s *ServerRunOptions) addFlags(fs *pflag.FlagSet) {
|
||||
fs.StringVar(&s.apiServerHost, "apiserver-host", "", "The address of the Kubernetes"+
|
||||
"Apiserver to connect to in the format of protocol://address:port, e.g., "+
|
||||
"http://localhost:8080. If not specified, the assumption is that the binary runs inside")
|
||||
|
||||
fs.IntVar(&s.insecurePort, "insecure-port", 9090, "The port to listen to for incoming HTTP requests.")
|
||||
|
||||
fs.IntVar(&s.port, "port", 8443, "The secure port to listen to for incoming HTTPS requests.")
|
||||
|
||||
fs.IPVar(&s.insecureBindAddress, "insecure-bind-address", net.IPv4(0, 0, 0, 0),
|
||||
"The IP address on which to serve the --port (set to 0.0.0.0 for all interfaces).")
|
||||
|
||||
fs.IPVar(&s.bindAddress, "bind-address", net.IPv4(0, 0, 0, 0),
|
||||
"The IP address on which to serve the --secure-port (set to 0.0.0.0 for all interfaces).")
|
||||
|
||||
fs.StringVar(&s.certFile, "tls-cert-file", "",
|
||||
"File containing the default x509 Certificate for HTTPS.")
|
||||
|
||||
fs.StringVar(&s.keyFile, "tls-key-file", "",
|
||||
"File containing the default x509 private key matching --tls-cert-file.")
|
||||
|
||||
fs.StringVar(&s.kubeConfigFile, "kubeconfig", "",
|
||||
"Path to kubeconfig file with authorization and master location information.")
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetApiServerHost() string {
|
||||
return s.apiServerHost
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetInsecurePort() int {
|
||||
return s.insecurePort
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetPort() int {
|
||||
return s.port
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetInsecureBindAddress() net.IP {
|
||||
return s.insecureBindAddress
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetBindAddress() net.IP {
|
||||
return s.bindAddress
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetCertFile() string {
|
||||
return s.certFile
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetKeyFile() string {
|
||||
return s.keyFile
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetKubeConfigFile() string {
|
||||
return s.kubeConfigFile
|
||||
}
|
||||
|
||||
var ServerOptions = NewServerRunOptions()
|
||||
|
||||
func AddFlags(fs *pflag.FlagSet) {
|
||||
ServerOptions.addFlags(fs)
|
||||
pflag.CommandLine.AddGoFlagSet(goflag.CommandLine)
|
||||
}
|
||||
39
pkg/version/version.go
Normal file
39
pkg/version/version.go
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package version
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/spf13/pflag"
|
||||
"os"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
var (
|
||||
versionFlag = pflag.Bool("version", false, "print the version of kubesphere")
|
||||
)
|
||||
|
||||
// PrintAndExitIfRequested will check if the -version flag was passed
|
||||
// and, if so, print the version and exit.
|
||||
|
||||
func PrintAndExitIfRequested() {
|
||||
|
||||
if *versionFlag {
|
||||
fmt.Printf("Kubesphere %s\n", constants.APIVERSION)
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user