Skip to content

Commit b7614b6

Browse files
authored
Merge M3 into MCS (#187)
* Merge M3 into MCS * Fix Linting * Add missing cluster folder
1 parent be069ed commit b7614b6

File tree

125 files changed

+9895
-343
lines changed

Some content is hidden

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

125 files changed

+9895
-343
lines changed

.golangci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,7 @@ linters:
2222

2323
service:
2424
golangci-lint-version: 1.21.0 # use the fixed version to not introduce new linters unexpectedly
25+
26+
run:
27+
skip-dirs:
28+
- pkg/clientgen

cluster/cluster.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// This file is part of MinIO Kubernetes Cloud
2+
// Copyright (c) 2019 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 cluster
18+
19+
import (
20+
operator "github.com/minio/minio-operator/pkg/client/clientset/versioned"
21+
"k8s.io/client-go/kubernetes"
22+
"k8s.io/client-go/rest"
23+
certutil "k8s.io/client-go/util/cert"
24+
)
25+
26+
func GetK8sConfig(token string) *rest.Config {
27+
// if m3 is running inside k8s by default he will have access to the ca cert from the k8s local authority
28+
const (
29+
rootCAFile = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
30+
)
31+
tlsClientConfig := rest.TLSClientConfig{Insecure: getK8sAPIServerInsecure()}
32+
if _, err := certutil.NewPool(rootCAFile); err == nil {
33+
tlsClientConfig.CAFile = rootCAFile
34+
}
35+
config := &rest.Config{
36+
Host: getK8sAPIServer(),
37+
TLSClientConfig: tlsClientConfig,
38+
APIPath: "/",
39+
BearerToken: token,
40+
}
41+
return config
42+
}
43+
44+
// OperatorClient returns an operator client using GetK8sConfig for its config
45+
func OperatorClient(token string) (*operator.Clientset, error) {
46+
return operator.NewForConfig(GetK8sConfig(token))
47+
}
48+
49+
// K8sClient returns kubernetes client using GetK8sConfig for its config
50+
func K8sClient(token string) (*kubernetes.Clientset, error) {
51+
return kubernetes.NewForConfig(GetK8sConfig(token))
52+
}

cluster/config.go

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// This file is part of MinIO Kubernetes Cloud
2+
// Copyright (c) 2019 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 cluster
18+
19+
import (
20+
"errors"
21+
"fmt"
22+
"io/ioutil"
23+
"net"
24+
"net/http"
25+
"regexp"
26+
"strings"
27+
"time"
28+
29+
"github.com/minio/minio/pkg/env"
30+
)
31+
32+
var (
33+
errCantDetermineMinIOImage = errors.New("can't determine MinIO Image")
34+
errCantDetermineMCImage = errors.New("can't determine MC Image")
35+
)
36+
37+
func getK8sAPIServer() string {
38+
// if m3 is running inside a k8s pod KUBERNETES_SERVICE_HOST and KUBERNETES_SERVICE_PORT will contain the k8s api server apiServerAddress
39+
// if m3 is not running inside k8s by default will look for the k8s api server on localhost:8001 (kubectl proxy)
40+
// NOTE: using kubectl proxy is for local development only, since every request send to localhost:8001 will bypass service account authentication
41+
// more info here: https://kubernetes.io/docs/tasks/access-application-cluster/access-cluster/#directly-accessing-the-rest-api
42+
// you can override this using M3_K8S_API_SERVER, ie use the k8s cluster from `kubectl config view`
43+
host, port := env.Get("KUBERNETES_SERVICE_HOST", ""), env.Get("KUBERNETES_SERVICE_PORT", "")
44+
apiServerAddress := "http://localhost:8001"
45+
if host != "" && port != "" {
46+
apiServerAddress = "https://" + net.JoinHostPort(host, port)
47+
}
48+
return env.Get(M3K8sAPIServer, apiServerAddress)
49+
}
50+
51+
// getK8sAPIServerInsecure allow to tell the k8s client to skip TLS certificate verification, ie: when connecting to a k8s cluster
52+
// that uses certificate not trusted by your machine
53+
func getK8sAPIServerInsecure() bool {
54+
return strings.ToLower(env.Get(m3k8SAPIServerInsecure, "off")) == "on"
55+
}
56+
57+
// GetNsFromFile assumes mkube is running inside a k8s pod and extract the current namespace from the
58+
// /var/run/secrets/kubernetes.io/serviceaccount/namespace file
59+
func GetNsFromFile() string {
60+
dat, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace")
61+
if err != nil {
62+
return "default"
63+
}
64+
return string(dat)
65+
}
66+
67+
// This operation will run only once at mkube startup
68+
var namespace = GetNsFromFile()
69+
70+
// Returns the namespace in which the controller is installed
71+
func GetNs() string {
72+
return env.Get(M3Namespace, namespace)
73+
}
74+
75+
// getLatestMinIOImage returns the latest docker image for MinIO if found on the internet
76+
func getLatestMinIOImage(client HTTPClientI) (*string, error) {
77+
resp, err := client.Get("https://dl.min.io/server/minio/release/linux-amd64/")
78+
if err != nil {
79+
return nil, err
80+
}
81+
defer resp.Body.Close()
82+
83+
body, err := ioutil.ReadAll(resp.Body)
84+
if err != nil {
85+
return nil, err
86+
}
87+
var re = regexp.MustCompile(`(?m)\.\/minio\.(RELEASE.*?Z)"`)
88+
// look for a single match
89+
matches := re.FindAllStringSubmatch(string(body), 1)
90+
for i := range matches {
91+
release := matches[i][1]
92+
dockerImage := fmt.Sprintf("minio/minio:%s", release)
93+
return &dockerImage, nil
94+
}
95+
return nil, errCantDetermineMinIOImage
96+
}
97+
98+
var latestMinIOImage, errLatestMinIOImage = getLatestMinIOImage(
99+
&HTTPClient{
100+
Client: &http.Client{
101+
Timeout: 4 * time.Second,
102+
},
103+
})
104+
105+
// GetMinioImage returns the image URL to be used when deploying a MinIO instance, if there is
106+
// a preferred image to be used (configured via ENVIRONMENT VARIABLES) GetMinioImage will return that
107+
// if not, GetMinioImage will try to obtain the image URL for the latest version of MinIO and return that
108+
func GetMinioImage() (*string, error) {
109+
image := strings.TrimSpace(env.Get(M3MinioImage, ""))
110+
// if there is a preferred image configured by the user we'll always return that
111+
if image != "" {
112+
return &image, nil
113+
}
114+
if errLatestMinIOImage != nil {
115+
return nil, errLatestMinIOImage
116+
}
117+
return latestMinIOImage, nil
118+
}
119+
120+
// GetLatestMinioImage returns the latest image URL on minio repository
121+
func GetLatestMinioImage(client HTTPClientI) (*string, error) {
122+
latestMinIOImage, err := getLatestMinIOImage(client)
123+
if err != nil {
124+
return nil, err
125+
}
126+
return latestMinIOImage, nil
127+
}
128+
129+
// getLatestMCImage returns the latest docker image for MC if found on the internet
130+
func getLatestMCImage() (*string, error) {
131+
// Create an http client with a 4 second timeout
132+
client := http.Client{
133+
Timeout: 4 * time.Second,
134+
}
135+
resp, err := client.Get("https://dl.min.io/client/mc/release/linux-amd64/")
136+
if err != nil {
137+
return nil, err
138+
}
139+
defer resp.Body.Close()
140+
141+
body, err := ioutil.ReadAll(resp.Body)
142+
if err != nil {
143+
return nil, err
144+
}
145+
var re = regexp.MustCompile(`(?m)\.\/mc\.(RELEASE.*?Z)"`)
146+
// look for a single match
147+
matches := re.FindAllStringSubmatch(string(body), 1)
148+
for i := range matches {
149+
release := matches[i][1]
150+
dockerImage := fmt.Sprintf("minio/mc:%s", release)
151+
return &dockerImage, nil
152+
}
153+
return nil, errCantDetermineMCImage
154+
}
155+
156+
var latestMCImage, errLatestMCImage = getLatestMCImage()
157+
158+
func GetMCImage() (*string, error) {
159+
image := strings.TrimSpace(env.Get(M3MCImage, ""))
160+
// if there is a preferred image configured by the user we'll always return that
161+
if image != "" {
162+
return &image, nil
163+
}
164+
if errLatestMCImage != nil {
165+
return nil, errLatestMCImage
166+
}
167+
return latestMCImage, nil
168+
}

cluster/const.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// This file is part of MinIO Kubernetes Cloud
2+
// Copyright (c) 2019 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 cluster
18+
19+
const (
20+
M3K8sAPIServer = "M3_K8S_API_SERVER"
21+
m3k8SAPIServerInsecure = "M3_K8S_API_SERVER_INSECURE"
22+
M3MinioImage = "M3_MINIO_IMAGE"
23+
M3MCImage = "M3_MC_IMAGE"
24+
M3Namespace = "M3_NAMESPACE"
25+
)

cluster/http_client.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// This file is part of MinIO Kubernetes Cloud
2+
// Copyright (c) 2020 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 cluster
18+
19+
import (
20+
"net/http"
21+
)
22+
23+
// HTTPClientI interface with all functions to be implemented
24+
// by mock when testing, it should include all HttpClient respective api calls
25+
// that are used within this project.
26+
type HTTPClientI interface {
27+
Get(url string) (resp *http.Response, err error)
28+
}
29+
30+
// HTTPClient Interface implementation
31+
//
32+
// Define the structure of a http client and define the functions that are actually used
33+
type HTTPClient struct {
34+
Client *http.Client
35+
}
36+
37+
// Get implements http.Client.Get()
38+
func (c *HTTPClient) Get(url string) (resp *http.Response, err error) {
39+
return c.Client.Get(url)
40+
}

go.mod

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,29 @@ require (
66
github.com/coreos/go-oidc v2.2.1+incompatible
77
github.com/dgrijalva/jwt-go v3.2.0+incompatible
88
github.com/elazarl/go-bindata-assetfs v1.0.0
9-
github.com/go-openapi/errors v0.19.4
9+
github.com/go-openapi/errors v0.19.6
1010
github.com/go-openapi/loads v0.19.5
11-
github.com/go-openapi/runtime v0.19.12
12-
github.com/go-openapi/spec v0.19.7
11+
github.com/go-openapi/runtime v0.19.19
12+
github.com/go-openapi/spec v0.19.8
1313
github.com/go-openapi/strfmt v0.19.5
14-
github.com/go-openapi/swag v0.19.8
15-
github.com/go-openapi/validate v0.19.7
14+
github.com/go-openapi/swag v0.19.9
15+
github.com/go-openapi/validate v0.19.10
1616
github.com/gorilla/websocket v1.4.2
1717
github.com/jessevdk/go-flags v1.4.0
1818
github.com/json-iterator/go v1.1.9
1919
github.com/minio/cli v1.22.0
2020
github.com/minio/mc v0.0.0-20200515235434-3b479cf92ed6
2121
github.com/minio/minio v0.0.0-20200603201854-5686a7e27319
2222
github.com/minio/minio-go/v6 v6.0.56
23+
github.com/minio/minio-operator v0.0.0-20200520220606-60eca6e7beab
2324
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35 // indirect
2425
github.com/satori/go.uuid v1.2.0
25-
github.com/stretchr/testify v1.5.1
26+
github.com/stretchr/testify v1.6.1
2627
github.com/unrolled/secure v1.0.7
27-
golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6
28-
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
29-
golang.org/x/oauth2 v0.0.0-20190402181905-9f3314589c9a
28+
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
29+
golang.org/x/net v0.0.0-20200602114024-627f9648deb9
30+
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
31+
k8s.io/api v0.18.0
32+
k8s.io/apimachinery v0.18.0
33+
k8s.io/client-go v0.18.0
3034
)

0 commit comments

Comments
 (0)