Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
b4633b06
Commit
b4633b06
authored
May 25, 2017
by
Zihong Zheng
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create nodes health checks for non-OnlyLocal services
parent
7bc6da0b
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
256 additions
and
40 deletions
+256
-40
gce.go
pkg/cloudprovider/providers/gce/gce.go
+9
-3
gce_clusterid.go
pkg/cloudprovider/providers/gce/gce_clusterid.go
+37
-37
gce_healthchecks.go
pkg/cloudprovider/providers/gce/gce_healthchecks.go
+68
-0
gce_healthchecks_test.go
pkg/cloudprovider/providers/gce/gce_healthchecks_test.go
+123
-0
gce_loadbalancer.go
pkg/cloudprovider/providers/gce/gce_loadbalancer.go
+0
-0
gce_util.go
pkg/cloudprovider/providers/gce/gce_util.go
+19
-0
No files found.
pkg/cloudprovider/providers/gce/gce.go
View file @
b4633b06
...
@@ -22,6 +22,7 @@ import (
...
@@ -22,6 +22,7 @@ import (
"net/http"
"net/http"
"regexp"
"regexp"
"strings"
"strings"
"sync"
"time"
"time"
"cloud.google.com/go/compute/metadata"
"cloud.google.com/go/compute/metadata"
...
@@ -80,7 +81,7 @@ type GCECloud struct {
...
@@ -80,7 +81,7 @@ type GCECloud struct {
serviceBeta
*
computebeta
.
Service
serviceBeta
*
computebeta
.
Service
containerService
*
container
.
Service
containerService
*
container
.
Service
clientBuilder
controller
.
ControllerClientBuilder
clientBuilder
controller
.
ControllerClientBuilder
ClusterI
d
ClusterId
ClusterI
D
ClusterID
projectID
string
projectID
string
region
string
region
string
localZone
string
// The zone in which we are running
localZone
string
// The zone in which we are running
...
@@ -92,6 +93,11 @@ type GCECloud struct {
...
@@ -92,6 +93,11 @@ type GCECloud struct {
useMetadataServer
bool
useMetadataServer
bool
operationPollRateLimiter
flowcontrol
.
RateLimiter
operationPollRateLimiter
flowcontrol
.
RateLimiter
manager
ServiceManager
manager
ServiceManager
// sharedResourceLock is used to serialize GCE operations that may mutate shared state to
// prevent inconsistencies. For example, load balancers manipulation methods will take the
// lock to prevent shared resources from being prematurely deleted while the operation is
// in progress.
sharedResourceLock
sync
.
Mutex
}
}
type
ServiceManager
interface
{
type
ServiceManager
interface
{
...
@@ -270,10 +276,10 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo
...
@@ -270,10 +276,10 @@ func CreateGCECloud(projectID, region, zone string, managedZones []string, netwo
}
}
// Initialize takes in a clientBuilder and spawns a goroutine for watching the clusterid configmap.
// Initialize takes in a clientBuilder and spawns a goroutine for watching the clusterid configmap.
// This must be called before utilizing the funcs of gce.ClusterI
d
// This must be called before utilizing the funcs of gce.ClusterI
D
func
(
gce
*
GCECloud
)
Initialize
(
clientBuilder
controller
.
ControllerClientBuilder
)
{
func
(
gce
*
GCECloud
)
Initialize
(
clientBuilder
controller
.
ControllerClientBuilder
)
{
gce
.
clientBuilder
=
clientBuilder
gce
.
clientBuilder
=
clientBuilder
go
gce
.
watchClusterI
d
()
go
gce
.
watchClusterI
D
()
}
}
// LoadBalancer returns an implementation of LoadBalancer for Google Compute Engine.
// LoadBalancer returns an implementation of LoadBalancer for Google Compute Engine.
...
...
pkg/cloudprovider/providers/gce/gce_clusterid.go
View file @
b4633b06
/*
/*
Copyright 201
4
The Kubernetes Authors.
Copyright 201
7
The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
you may not use this file except in compliance with the License.
...
@@ -49,18 +49,18 @@ const (
...
@@ -49,18 +49,18 @@ const (
updateFuncFrequency
=
10
*
time
.
Minute
updateFuncFrequency
=
10
*
time
.
Minute
)
)
type
ClusterI
d
struct
{
type
ClusterI
D
struct
{
idLock
sync
.
RWMutex
idLock
sync
.
RWMutex
client
clientset
.
Interface
client
clientset
.
Interface
cfgMapKey
string
cfgMapKey
string
store
cache
.
Store
store
cache
.
Store
providerI
d
*
string
providerI
D
*
string
clusterI
d
*
string
clusterI
D
*
string
}
}
// Continually watches for changes to the cluser id config map
// Continually watches for changes to the clus
t
er id config map
func
(
gce
*
GCECloud
)
watchClusterI
d
()
{
func
(
gce
*
GCECloud
)
watchClusterI
D
()
{
gce
.
ClusterI
d
=
ClusterId
{
gce
.
ClusterI
D
=
ClusterID
{
cfgMapKey
:
fmt
.
Sprintf
(
"%v/%v"
,
UIDNamespace
,
UIDConfigMapName
),
cfgMapKey
:
fmt
.
Sprintf
(
"%v/%v"
,
UIDNamespace
,
UIDConfigMapName
),
client
:
gce
.
clientBuilder
.
ClientOrDie
(
"cloud-provider"
),
client
:
gce
.
clientBuilder
.
ClientOrDie
(
"cloud-provider"
),
}
}
...
@@ -77,8 +77,8 @@ func (gce *GCECloud) watchClusterId() {
...
@@ -77,8 +77,8 @@ func (gce *GCECloud) watchClusterId() {
return
return
}
}
glog
.
V
(
4
)
.
Infof
(
"Observed new configmap for clusteri
d
: %v, %v; setting local values"
,
m
.
Name
,
m
.
Data
)
glog
.
V
(
4
)
.
Infof
(
"Observed new configmap for clusteri
D
: %v, %v; setting local values"
,
m
.
Name
,
m
.
Data
)
gce
.
ClusterI
d
.
setIds
(
m
)
gce
.
ClusterI
D
.
update
(
m
)
},
},
UpdateFunc
:
func
(
old
,
cur
interface
{})
{
UpdateFunc
:
func
(
old
,
cur
interface
{})
{
m
,
ok
:=
cur
.
(
*
v1
.
ConfigMap
)
m
,
ok
:=
cur
.
(
*
v1
.
ConfigMap
)
...
@@ -96,71 +96,71 @@ func (gce *GCECloud) watchClusterId() {
...
@@ -96,71 +96,71 @@ func (gce *GCECloud) watchClusterId() {
return
return
}
}
glog
.
V
(
4
)
.
Infof
(
"Observed updated configmap for clusteri
d
%v, %v; setting local values"
,
m
.
Name
,
m
.
Data
)
glog
.
V
(
4
)
.
Infof
(
"Observed updated configmap for clusteri
D
%v, %v; setting local values"
,
m
.
Name
,
m
.
Data
)
gce
.
ClusterI
d
.
setIds
(
m
)
gce
.
ClusterI
D
.
update
(
m
)
},
},
}
}
listerWatcher
:=
cache
.
NewListWatchFromClient
(
gce
.
ClusterI
d
.
client
.
Core
()
.
RESTClient
(),
"configmaps"
,
UIDNamespace
,
fields
.
Everything
())
listerWatcher
:=
cache
.
NewListWatchFromClient
(
gce
.
ClusterI
D
.
client
.
Core
()
.
RESTClient
(),
"configmaps"
,
UIDNamespace
,
fields
.
Everything
())
var
controller
cache
.
Controller
var
controller
cache
.
Controller
gce
.
ClusterI
d
.
store
,
controller
=
cache
.
NewInformer
(
newSingleObjectListerWatcher
(
listerWatcher
,
UIDConfigMapName
),
&
v1
.
ConfigMap
{},
updateFuncFrequency
,
mapEventHandler
)
gce
.
ClusterI
D
.
store
,
controller
=
cache
.
NewInformer
(
newSingleObjectListerWatcher
(
listerWatcher
,
UIDConfigMapName
),
&
v1
.
ConfigMap
{},
updateFuncFrequency
,
mapEventHandler
)
controller
.
Run
(
nil
)
controller
.
Run
(
nil
)
}
}
// GetI
d
returns the id which is unique to this cluster
// GetI
D
returns the id which is unique to this cluster
// if federated, return the provider id (unique to the cluster)
// if federated, return the provider id (unique to the cluster)
// if not federated, return the cluster id
// if not federated, return the cluster id
func
(
ci
*
ClusterI
d
)
GetId
()
(
string
,
error
)
{
func
(
ci
*
ClusterI
D
)
GetID
()
(
string
,
error
)
{
if
err
:=
ci
.
getOrInitialize
();
err
!=
nil
{
if
err
:=
ci
.
getOrInitialize
();
err
!=
nil
{
return
""
,
err
return
""
,
err
}
}
ci
.
idLock
.
RLock
()
ci
.
idLock
.
RLock
()
defer
ci
.
idLock
.
RUnlock
()
defer
ci
.
idLock
.
RUnlock
()
if
ci
.
clusterI
d
==
nil
{
if
ci
.
clusterI
D
==
nil
{
return
""
,
errors
.
New
(
"Could not retrieve cluster id"
)
return
""
,
errors
.
New
(
"Could not retrieve cluster id"
)
}
}
// If provider ID is set, (Federation is enabled) use this field
// If provider ID is set, (Federation is enabled) use this field
if
ci
.
providerI
d
!=
nil
&&
*
ci
.
providerId
!=
*
ci
.
clusterId
{
if
ci
.
providerI
D
!=
nil
{
return
*
ci
.
providerI
d
,
nil
return
*
ci
.
providerI
D
,
nil
}
}
// providerI
d
is not set, use the cluster id
// providerI
D
is not set, use the cluster id
return
*
ci
.
clusterI
d
,
nil
return
*
ci
.
clusterI
D
,
nil
}
}
// GetFederationId returns the id which could represent the entire Federation
// GetFederationId returns the id which could represent the entire Federation
// or just the cluster if not federated.
// or just the cluster if not federated.
func
(
ci
*
ClusterI
d
)
GetFederationId
()
(
string
,
bool
,
error
)
{
func
(
ci
*
ClusterI
D
)
GetFederationId
()
(
string
,
bool
,
error
)
{
if
err
:=
ci
.
getOrInitialize
();
err
!=
nil
{
if
err
:=
ci
.
getOrInitialize
();
err
!=
nil
{
return
""
,
false
,
err
return
""
,
false
,
err
}
}
ci
.
idLock
.
RLock
()
ci
.
idLock
.
RLock
()
defer
ci
.
idLock
.
RUnlock
()
defer
ci
.
idLock
.
RUnlock
()
if
ci
.
clusterI
d
==
nil
{
if
ci
.
clusterI
D
==
nil
{
return
""
,
false
,
errors
.
New
(
"Could not retrieve cluster id"
)
return
""
,
false
,
errors
.
New
(
"Could not retrieve cluster id"
)
}
}
// If provider ID is not set, return false
// If provider ID is not set, return false
if
ci
.
providerI
d
==
nil
||
*
ci
.
clusterId
==
*
ci
.
providerId
{
if
ci
.
providerI
D
==
nil
||
*
ci
.
clusterID
==
*
ci
.
providerID
{
return
""
,
false
,
nil
return
""
,
false
,
nil
}
}
return
*
ci
.
clusterI
d
,
true
,
nil
return
*
ci
.
clusterI
D
,
true
,
nil
}
}
// getOrInitialize either grabs the configmaps current value or defines the value
// getOrInitialize either grabs the configmaps current value or defines the value
// and sets the configmap. This is for the case of the user calling GetClusterI
d
()
// and sets the configmap. This is for the case of the user calling GetClusterI
D
()
// before the watch has begun.
// before the watch has begun.
func
(
ci
*
ClusterI
d
)
getOrInitialize
()
error
{
func
(
ci
*
ClusterI
D
)
getOrInitialize
()
error
{
if
ci
.
store
==
nil
{
if
ci
.
store
==
nil
{
return
errors
.
New
(
"GCECloud.ClusterI
d
is not ready. Call Initialize() before using."
)
return
errors
.
New
(
"GCECloud.ClusterI
D
is not ready. Call Initialize() before using."
)
}
}
if
ci
.
clusterI
d
!=
nil
{
if
ci
.
clusterI
D
!=
nil
{
return
nil
return
nil
}
}
...
@@ -177,7 +177,7 @@ func (ci *ClusterId) getOrInitialize() error {
...
@@ -177,7 +177,7 @@ func (ci *ClusterId) getOrInitialize() error {
return
err
return
err
}
}
glog
.
V
(
4
)
.
Infof
(
"Creating clusteri
d
: %v"
,
newId
)
glog
.
V
(
4
)
.
Infof
(
"Creating clusteri
D
: %v"
,
newId
)
cfg
:=
&
v1
.
ConfigMap
{
cfg
:=
&
v1
.
ConfigMap
{
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
UIDConfigMapName
,
Name
:
UIDConfigMapName
,
...
@@ -194,12 +194,12 @@ func (ci *ClusterId) getOrInitialize() error {
...
@@ -194,12 +194,12 @@ func (ci *ClusterId) getOrInitialize() error {
return
err
return
err
}
}
glog
.
V
(
2
)
.
Infof
(
"Created a config map containing clusteri
d
: %v"
,
newId
)
glog
.
V
(
2
)
.
Infof
(
"Created a config map containing clusteri
D
: %v"
,
newId
)
ci
.
setIds
(
cfg
)
ci
.
update
(
cfg
)
return
nil
return
nil
}
}
func
(
ci
*
ClusterI
d
)
getConfigMap
()
(
bool
,
error
)
{
func
(
ci
*
ClusterI
D
)
getConfigMap
()
(
bool
,
error
)
{
item
,
exists
,
err
:=
ci
.
store
.
GetByKey
(
ci
.
cfgMapKey
)
item
,
exists
,
err
:=
ci
.
store
.
GetByKey
(
ci
.
cfgMapKey
)
if
err
!=
nil
{
if
err
!=
nil
{
return
false
,
err
return
false
,
err
...
@@ -214,18 +214,18 @@ func (ci *ClusterId) getConfigMap() (bool, error) {
...
@@ -214,18 +214,18 @@ func (ci *ClusterId) getConfigMap() (bool, error) {
glog
.
Error
(
err
)
glog
.
Error
(
err
)
return
false
,
err
return
false
,
err
}
}
ci
.
setIds
(
m
)
ci
.
update
(
m
)
return
true
,
nil
return
true
,
nil
}
}
func
(
ci
*
ClusterI
d
)
setIds
(
m
*
v1
.
ConfigMap
)
{
func
(
ci
*
ClusterI
D
)
update
(
m
*
v1
.
ConfigMap
)
{
ci
.
idLock
.
Lock
()
ci
.
idLock
.
Lock
()
defer
ci
.
idLock
.
Unlock
()
defer
ci
.
idLock
.
Unlock
()
if
clusterI
d
,
exists
:=
m
.
Data
[
UIDCluster
];
exists
{
if
clusterI
D
,
exists
:=
m
.
Data
[
UIDCluster
];
exists
{
ci
.
clusterI
d
=
&
clusterId
ci
.
clusterI
D
=
&
clusterID
}
}
if
provId
,
exists
:=
m
.
Data
[
UIDProvider
];
exists
{
if
provId
,
exists
:=
m
.
Data
[
UIDProvider
];
exists
{
ci
.
providerI
d
=
&
provId
ci
.
providerI
D
=
&
provId
}
}
}
}
...
...
pkg/cloudprovider/providers/gce/gce_healthchecks.go
View file @
b4633b06
...
@@ -17,11 +17,23 @@ limitations under the License.
...
@@ -17,11 +17,23 @@ limitations under the License.
package
gce
package
gce
import
(
import
(
"fmt"
"time"
"time"
"k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/master/ports"
utilversion
"k8s.io/kubernetes/pkg/util/version"
"github.com/golang/glog"
compute
"google.golang.org/api/compute/v1"
compute
"google.golang.org/api/compute/v1"
)
)
const
(
minNodesHealthCheckVersion
=
"1.7.0"
nodesHealthCheckPath
=
"/healthz"
lbNodesHealthCheckPort
=
ports
.
ProxyHealthzPort
)
func
newHealthcheckMetricContext
(
request
string
)
*
metricContext
{
func
newHealthcheckMetricContext
(
request
string
)
*
metricContext
{
return
&
metricContext
{
return
&
metricContext
{
start
:
time
.
Now
(),
start
:
time
.
Now
(),
...
@@ -178,3 +190,59 @@ func (gce *GCECloud) ListHealthChecks() (*compute.HealthCheckList, error) {
...
@@ -178,3 +190,59 @@ func (gce *GCECloud) ListHealthChecks() (*compute.HealthCheckList, error) {
v
,
err
:=
gce
.
service
.
HealthChecks
.
List
(
gce
.
projectID
)
.
Do
()
v
,
err
:=
gce
.
service
.
HealthChecks
.
List
(
gce
.
projectID
)
.
Do
()
return
v
,
mc
.
Observe
(
err
)
return
v
,
mc
.
Observe
(
err
)
}
}
// GetNodesHealthCheckPort returns the health check port used by the GCE load
// balancers (l4) for performing health checks on nodes.
func
GetNodesHealthCheckPort
()
int32
{
return
lbNodesHealthCheckPort
}
// getNodesHealthCheckPath returns the health check path used by the GCE load
// balancers (l4) for performing health checks on nodes.
func
getNodesHealthCheckPath
()
string
{
return
nodesHealthCheckPath
}
// makeNodesHealthCheckName returns name of the health check resource used by
// the GCE load balancers (l4) for performing health checks on nodes.
func
makeNodesHealthCheckName
(
clusterID
string
)
string
{
return
fmt
.
Sprintf
(
"k8s-%v-node"
,
clusterID
)
}
// MakeHealthCheckFirewallName returns the firewall name used by the GCE load
// balancers (l4) for performing health checks.
func
MakeHealthCheckFirewallName
(
clusterID
,
hcName
string
,
isNodesHealthCheck
bool
)
string
{
// TODO: Change below fwName to match the proposed schema: k8s-{clusteriD}-{namespace}-{name}-{shortid}-hc.
fwName
:=
"k8s-"
+
hcName
+
"-http-hc"
if
isNodesHealthCheck
{
fwName
=
makeNodesHealthCheckName
(
clusterID
)
+
"-http-hc"
}
return
fwName
}
// isAtLeastMinNodesHealthCheckVersion checks if a version is higher than
// `minNodesHealthCheckVersion`.
func
isAtLeastMinNodesHealthCheckVersion
(
vstring
string
)
bool
{
minVersion
,
err
:=
utilversion
.
ParseGeneric
(
minNodesHealthCheckVersion
)
if
err
!=
nil
{
glog
.
Errorf
(
"MinNodesHealthCheckVersion (%s) is not a valid version string: %v"
,
minNodesHealthCheckVersion
,
err
)
return
false
}
version
,
err
:=
utilversion
.
ParseGeneric
(
vstring
)
if
err
!=
nil
{
glog
.
Errorf
(
"vstring (%s) is not a valid version string: %v"
,
vstring
,
err
)
return
false
}
return
version
.
AtLeast
(
minVersion
)
}
// supportsNodesHealthCheck returns false if anyone of the nodes has version
// lower than `minNodesHealthCheckVersion`.
func
supportsNodesHealthCheck
(
nodes
[]
*
v1
.
Node
)
bool
{
for
_
,
node
:=
range
nodes
{
if
!
isAtLeastMinNodesHealthCheckVersion
(
node
.
Status
.
NodeInfo
.
KubeProxyVersion
)
{
return
false
}
}
return
true
}
pkg/cloudprovider/providers/gce/gce_healthchecks_test.go
0 → 100644
View file @
b4633b06
/*
Copyright 2017 The Kubernetes 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
gce
import
(
"testing"
"k8s.io/kubernetes/pkg/api/v1"
)
func
TestIsAtLeastMinNodesHealthCheckVersion
(
t
*
testing
.
T
)
{
testCases
:=
[]
struct
{
version
string
expect
bool
}{
{
"v1.7.1"
,
true
},
{
"v1.7.0-alpha.2.597+276d289b90d322"
,
true
},
{
"v1.6.0-beta.3.472+831q821c907t31a"
,
false
},
{
"v1.5.2"
,
false
},
}
for
_
,
tc
:=
range
testCases
{
if
res
:=
isAtLeastMinNodesHealthCheckVersion
(
tc
.
version
);
res
!=
tc
.
expect
{
t
.
Errorf
(
"%v: want %v, got %v"
,
tc
.
version
,
tc
.
expect
,
res
)
}
}
}
func
TestSupportsNodesHealthCheck
(
t
*
testing
.
T
)
{
testCases
:=
[]
struct
{
desc
string
nodes
[]
*
v1
.
Node
expect
bool
}{
{
"All nodes support nodes health check"
,
[]
*
v1
.
Node
{
{
Status
:
v1
.
NodeStatus
{
NodeInfo
:
v1
.
NodeSystemInfo
{
KubeProxyVersion
:
"v1.7.1"
,
},
},
},
{
Status
:
v1
.
NodeStatus
{
NodeInfo
:
v1
.
NodeSystemInfo
{
KubeProxyVersion
:
"v1.7.0-alpha.2.597+276d289b90d322"
,
},
},
},
},
true
,
},
{
"All nodes don't support nodes health check"
,
[]
*
v1
.
Node
{
{
Status
:
v1
.
NodeStatus
{
NodeInfo
:
v1
.
NodeSystemInfo
{
KubeProxyVersion
:
"v1.6.0-beta.3.472+831q821c907t31a"
,
},
},
},
{
Status
:
v1
.
NodeStatus
{
NodeInfo
:
v1
.
NodeSystemInfo
{
KubeProxyVersion
:
"v1.5.2"
,
},
},
},
},
false
,
},
{
"One node doesn't support nodes health check"
,
[]
*
v1
.
Node
{
{
Status
:
v1
.
NodeStatus
{
NodeInfo
:
v1
.
NodeSystemInfo
{
KubeProxyVersion
:
"v1.7.1"
,
},
},
},
{
Status
:
v1
.
NodeStatus
{
NodeInfo
:
v1
.
NodeSystemInfo
{
KubeProxyVersion
:
"v1.7.0-alpha.2.597+276d289b90d322"
,
},
},
},
{
Status
:
v1
.
NodeStatus
{
NodeInfo
:
v1
.
NodeSystemInfo
{
KubeProxyVersion
:
"v1.5.2"
,
},
},
},
},
false
,
},
}
for
_
,
tc
:=
range
testCases
{
if
res
:=
supportsNodesHealthCheck
(
tc
.
nodes
);
res
!=
tc
.
expect
{
t
.
Errorf
(
"%v: want %v, got %v"
,
tc
.
desc
,
tc
.
expect
,
res
)
}
}
}
pkg/cloudprovider/providers/gce/gce_loadbalancer.go
View file @
b4633b06
This diff is collapsed.
Click to expand it.
pkg/cloudprovider/providers/gce/gce_util.go
View file @
b4633b06
...
@@ -19,10 +19,12 @@ package gce
...
@@ -19,10 +19,12 @@ package gce
import
(
import
(
"errors"
"errors"
"fmt"
"fmt"
"net/http"
"regexp"
"regexp"
"strings"
"strings"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"cloud.google.com/go/compute/metadata"
"cloud.google.com/go/compute/metadata"
compute
"google.golang.org/api/compute/v1"
compute
"google.golang.org/api/compute/v1"
...
@@ -105,6 +107,14 @@ func isHTTPErrorCode(err error, code int) bool {
...
@@ -105,6 +107,14 @@ func isHTTPErrorCode(err error, code int) bool {
return
ok
&&
apiErr
.
Code
==
code
return
ok
&&
apiErr
.
Code
==
code
}
}
func
isInUsedByError
(
err
error
)
bool
{
apiErr
,
ok
:=
err
.
(
*
googleapi
.
Error
)
if
!
ok
||
apiErr
.
Code
!=
http
.
StatusBadRequest
{
return
false
}
return
strings
.
Contains
(
apiErr
.
Message
,
"being used by"
)
}
// splitProviderID splits a provider's id into core components.
// splitProviderID splits a provider's id into core components.
// A providerID is build out of '${ProviderName}://${project-id}/${zone}/${instance-name}'
// A providerID is build out of '${ProviderName}://${project-id}/${zone}/${instance-name}'
// See cloudprovider.GetInstanceProviderID.
// See cloudprovider.GetInstanceProviderID.
...
@@ -115,3 +125,12 @@ func splitProviderID(providerID string) (project, zone, instance string, err err
...
@@ -115,3 +125,12 @@ func splitProviderID(providerID string) (project, zone, instance string, err err
}
}
return
matches
[
1
],
matches
[
2
],
matches
[
3
],
nil
return
matches
[
1
],
matches
[
2
],
matches
[
3
],
nil
}
}
func
equalStringSets
(
x
,
y
[]
string
)
bool
{
if
len
(
x
)
!=
len
(
y
)
{
return
false
}
xString
:=
sets
.
NewString
(
x
...
)
yString
:=
sets
.
NewString
(
y
...
)
return
xString
.
Equal
(
yString
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment