/
platform_detection.go
183 lines (164 loc) · 5.62 KB
/
platform_detection.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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package platform
import (
"context"
"errors"
"log"
"sync"
configv1 "github.com/openshift/api/config/v1"
secv1 "github.com/openshift/api/security/v1"
configv1Client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/discovery"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
)
var (
once sync.Once
platformInstance *platform
ErrorPlatformNotDetected = errors.New("platform not detected")
// SkipObjectStorePlatforms is a list of all PlatformTypes where CephObjectStores will not be deployed.
SkipObjectStorePlatforms = []configv1.PlatformType{
configv1.AWSPlatformType,
configv1.GCPPlatformType,
configv1.AzurePlatformType,
configv1.IBMCloudPlatformType,
}
)
// platform is used to get the PlatformType of the running cluster in a thread-safe manner
// It is a singleton which is initialized exactly once via Detect() function call.
type platform struct {
isOpenShift bool
platform configv1.PlatformType
// isROSAHCP flag is temporary and needs to be rethought
// open issue: https://github.com/red-hat-storage/ocs-operator/issues/2521
isROSAHCP bool
}
// SetFakePlatformInstanceForTesting can be used to fake a Platform while testing.
// It should only be used for testing. This is not thread-safe.
func SetFakePlatformInstanceForTesting(isOpenShift bool, platformType configv1.PlatformType) {
platformInstance = &platform{
isOpenShift: isOpenShift,
platform: platformType,
isROSAHCP: false,
}
}
// UnsetFakePlatformInstanceForTesting can be used to unset the fake Platform while testing.
// It should only be used for testing. This is not thread-safe.
func UnsetFakePlatformInstanceForTesting() {
platformInstance = &platform{}
}
// Detect instantiates the platform only once. It is thread-safe.
func Detect() {
if platformInstance != nil {
return
}
once.Do(func() {
platformInstance = &platform{}
cfg := ctrl.GetConfigOrDie()
dclient := discovery.NewDiscoveryClientForConfigOrDie(cfg)
_, apis, err := dclient.ServerGroupsAndResources()
if err != nil && !discovery.IsGroupDiscoveryFailedError(err) {
log.Fatal(err)
}
if discovery.IsGroupDiscoveryFailedError(err) {
e := err.(*discovery.ErrGroupDiscoveryFailed)
if _, exists := e.Groups[secv1.GroupVersion]; exists {
platformInstance.isOpenShift = true
}
}
if !platformInstance.isOpenShift {
for _, api := range apis {
if api.GroupVersion == secv1.GroupVersion.String() {
for _, resource := range api.APIResources {
if resource.Name == "securitycontextconstraints" {
platformInstance.isOpenShift = true
break
}
}
}
if platformInstance.isOpenShift {
break
}
}
}
if platformInstance.isOpenShift {
var infrastructure *configv1.Infrastructure
if infrastructure, err = configv1client(cfg).Infrastructures().Get(context.TODO(), "cluster", metav1.GetOptions{}); err != nil {
log.Fatal(err)
}
platformInstance.platform = infrastructure.Status.PlatformStatus.Type
if platformInstance.platform == configv1.AWSPlatformType {
if infrastructure.Status.ControlPlaneTopology == configv1.ExternalTopologyMode {
for _, resourceTags := range infrastructure.Status.PlatformStatus.AWS.ResourceTags {
if resourceTags.Key == "red-hat-clustertype" && resourceTags.Value == "rosa" {
platformInstance.isROSAHCP = true
}
}
}
}
}
})
}
func configv1client(cfg *rest.Config) *configv1Client.ConfigV1Client {
return configv1Client.NewForConfigOrDie(cfg)
}
// IsPlatformOpenShift returns true if platform is detected to be OpenShift.
// It returns false in all other cases, including when platform is not yet detected.
func IsPlatformOpenShift() (bool, error) {
if platformInstance == nil {
return false, ErrorPlatformNotDetected
}
return platformInstance.isOpenShift, nil
}
// GetPlatformType is used to get the PlatformType of the running cluster.
// It returns a PlatformType only when running on OpenShift clusters.
// If it is not running on OpenShift or platform is not yet detected, it return empty PlatformType.
func GetPlatformType() (configv1.PlatformType, error) {
if platformInstance == nil {
return "", ErrorPlatformNotDetected
}
return platformInstance.platform, nil
}
// DevicesDefaultToFastForThisPlatform determines whether we should TuneFastDeviceClass for this platform.
// It returns false if we shouldn't TuneFastDeviceClass or if platform is not yet detected.
func DevicesDefaultToFastForThisPlatform() (bool, error) {
// tuneFastPlatforms is a list of all PlatformTypes where TuneFastDeviceClass has to be set True.
var tuneFastPlatforms = []configv1.PlatformType{
configv1.OvirtPlatformType,
configv1.IBMCloudPlatformType,
configv1.AzurePlatformType,
}
platform, err := GetPlatformType()
if err != nil {
return false, err
}
for _, tfplatform := range tuneFastPlatforms {
if platform == tfplatform {
return true, nil
}
}
return false, nil
}
// PlatformsShouldSkipObjectStore determines whether an object store should be created
// for the platform. It returns false if ObjectStore should not be skipped or if platform is not yet detected.
func PlatformsShouldSkipObjectStore() (bool, error) {
platform, err := GetPlatformType()
if err != nil {
return false, err
}
return SkipObjectStore(platform), nil
}
func SkipObjectStore(p configv1.PlatformType) bool {
for _, platform := range SkipObjectStorePlatforms {
if p == platform {
return true
}
}
return false
}
func IsPlatformROSAHCP() (bool, error) {
if platformInstance == nil {
return false, ErrorPlatformNotDetected
}
return platformInstance.isROSAHCP, nil
}