/
context.go
120 lines (94 loc) · 3.8 KB
/
context.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
Copyright 2021 The Topolvm-Operator Authors. All rights reserved.
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 cluster
import (
"fmt"
"github.com/alauda/topolvm-operator/pkg/util/exec"
"github.com/coreos/pkg/capnslog"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"os"
"sigs.k8s.io/controller-runtime/pkg/client"
)
var (
logger = capnslog.NewPackageLogger("topolvm/operator", "cluster-info")
)
const (
terminationLog = "/dev/termination-log"
)
type Context struct {
// The kubernetes config used for this context
KubeConfig *rest.Config
// Clientset is a connection to the core kubernetes API
Clientset kubernetes.Interface
Client client.Client
// APIExtensionClientset is a connection to the API Extension kubernetes API
APIExtensionClientset apiextensionsclient.Interface
// The implementation of executing a console command
Executor exec.Executor
// A value indicating the desired logging/tracing level
LogLevel capnslog.LogLevel
}
func NewContext() *Context {
var err error
context := &Context{
Executor: &exec.CommandExecutor{},
}
// Try to read config from in-cluster env
context.KubeConfig, err = rest.InClusterConfig()
if err != nil {
// **Not** running inside a cluster - running the operator outside of the cluster.
// This mode is for developers running the operator on their dev machines
// for faster development, or to run operator cli tools manually to a remote cluster.
// We setup the API server config from default user file locations (most notably ~/.kube/config),
// and also change the executor to work remotely and run kubernetes jobs.
logger.Info("setting up the context to outside of the cluster")
// Try to read config from user config files
context.KubeConfig, err = clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
clientcmd.NewDefaultClientConfigLoadingRules(),
&clientcmd.ConfigOverrides{}).ClientConfig()
TerminateOnError(err, "failed to get k8s config")
}
context.Clientset, err = kubernetes.NewForConfig(context.KubeConfig)
TerminateOnError(err, "failed to create k8s clientset")
context.APIExtensionClientset, err = apiextensionsclient.NewForConfig(context.KubeConfig)
TerminateOnError(err, "failed to create k8s API extension clientset")
return context
}
// TerminateOnError terminates if err is not nil
func TerminateOnError(err error, msg string) {
if err != nil {
TerminateFatal(fmt.Errorf("%s: %+v", msg, err))
}
}
// TerminateFatal terminates the process with an exit code of 1
// and writes the given reason to stderr and the termination log file.
func TerminateFatal(reason error) {
fmt.Fprintln(os.Stderr, reason)
file, err := os.OpenFile(terminationLog, os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
fmt.Fprintln(os.Stderr, fmt.Errorf("failed to write message to termination log: %+v", err))
} else {
// #nosec G307 Calling defer to close the file without checking the error return is not a risk for a simple file open and close
defer file.Close()
if _, err = file.WriteString(reason.Error()); err != nil {
fmt.Fprintln(os.Stderr, fmt.Errorf("failed to write message to termination log: %+v", err))
}
if err := file.Close(); err != nil {
logger.Errorf("failed to close file. %v", err)
}
}
os.Exit(1)
}