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
8c196137
Commit
8c196137
authored
Oct 04, 2018
by
Sean Sullivan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kubectl taint: copy core taintutil dependency into kubectl
parent
c75d772c
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
222 additions
and
7 deletions
+222
-7
BUILD
pkg/kubectl/cmd/taint/BUILD
+10
-3
taint.go
pkg/kubectl/cmd/taint/taint.go
+3
-4
utils.go
pkg/kubectl/cmd/taint/utils.go
+209
-0
utils_test.go
pkg/kubectl/cmd/taint/utils_test.go
+0
-0
No files found.
pkg/kubectl/cmd/taint/BUILD
View file @
8c196137
...
...
@@ -2,7 +2,10 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = ["taint.go"],
srcs = [
"taint.go",
"utils.go",
],
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/taint",
visibility = ["//visibility:public"],
deps = [
...
...
@@ -10,11 +13,12 @@ go_library(
"//pkg/kubectl/scheme:go_default_library",
"//pkg/kubectl/util/i18n:go_default_library",
"//pkg/kubectl/util/templates:go_default_library",
"//pkg/util/taints:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//staging/src/k8s.io/cli-runtime/pkg/genericclioptions:go_default_library",
...
...
@@ -27,7 +31,10 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["taint_test.go"],
srcs = [
"taint_test.go",
"utils_test.go",
],
embed = [":go_default_library"],
deps = [
"//pkg/kubectl/cmd/testing:go_default_library",
...
...
pkg/kubectl/cmd/taint/taint.go
View file @
8c196137
...
...
@@ -37,7 +37,6 @@ import (
"k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
"k8s.io/kubernetes/pkg/kubectl/util/templates"
taintutils
"k8s.io/kubernetes/pkg/util/taints"
)
// TaintOptions have the data required to perform the taint operation
...
...
@@ -159,7 +158,7 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
return
fmt
.
Errorf
(
"at least one taint update is required"
)
}
if
o
.
taintsToAdd
,
o
.
taintsToRemove
,
err
=
taintutils
.
P
arseTaints
(
taintArgs
);
err
!=
nil
{
if
o
.
taintsToAdd
,
o
.
taintsToRemove
,
err
=
p
arseTaints
(
taintArgs
);
err
!=
nil
{
return
cmdutil
.
UsageErrorf
(
cmd
,
err
.
Error
())
}
o
.
builder
=
f
.
NewBuilder
()
.
...
...
@@ -298,11 +297,11 @@ func (o TaintOptions) updateTaints(obj runtime.Object) (string, error) {
return
""
,
fmt
.
Errorf
(
"unexpected type %T, expected Node"
,
obj
)
}
if
!
o
.
overwrite
{
if
exists
:=
taintutils
.
C
heckIfTaintsAlreadyExists
(
node
.
Spec
.
Taints
,
o
.
taintsToAdd
);
len
(
exists
)
!=
0
{
if
exists
:=
c
heckIfTaintsAlreadyExists
(
node
.
Spec
.
Taints
,
o
.
taintsToAdd
);
len
(
exists
)
!=
0
{
return
""
,
fmt
.
Errorf
(
"Node %s already has %v taint(s) with same effect(s) and --overwrite is false"
,
node
.
Name
,
exists
)
}
}
operation
,
newTaints
,
err
:=
taintutils
.
R
eorganizeTaints
(
node
,
o
.
overwrite
,
o
.
taintsToAdd
,
o
.
taintsToRemove
)
operation
,
newTaints
,
err
:=
r
eorganizeTaints
(
node
,
o
.
overwrite
,
o
.
taintsToAdd
,
o
.
taintsToRemove
)
if
err
!=
nil
{
return
""
,
err
}
...
...
pkg/kubectl/cmd/taint/utils.go
0 → 100644
View file @
8c196137
/*
Copyright 2018 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 taints implements utilites for working with taints
package
taint
import
(
"fmt"
"strings"
corev1
"k8s.io/api/core/v1"
utilerrors
"k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation"
)
// Exported taint constant strings
const
(
MODIFIED
=
"modified"
TAINTED
=
"tainted"
UNTAINTED
=
"untainted"
)
// parseTaints takes a spec which is an array and creates slices for new taints to be added, taints to be deleted.
func
parseTaints
(
spec
[]
string
)
([]
corev1
.
Taint
,
[]
corev1
.
Taint
,
error
)
{
var
taints
,
taintsToRemove
[]
corev1
.
Taint
uniqueTaints
:=
map
[
corev1
.
TaintEffect
]
sets
.
String
{}
for
_
,
taintSpec
:=
range
spec
{
if
strings
.
Index
(
taintSpec
,
"="
)
!=
-
1
&&
strings
.
Index
(
taintSpec
,
":"
)
!=
-
1
{
newTaint
,
err
:=
parseTaint
(
taintSpec
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
// validate if taint is unique by <key, effect>
if
len
(
uniqueTaints
[
newTaint
.
Effect
])
>
0
&&
uniqueTaints
[
newTaint
.
Effect
]
.
Has
(
newTaint
.
Key
)
{
return
nil
,
nil
,
fmt
.
Errorf
(
"duplicated taints with the same key and effect: %v"
,
newTaint
)
}
// add taint to existingTaints for uniqueness check
if
len
(
uniqueTaints
[
newTaint
.
Effect
])
==
0
{
uniqueTaints
[
newTaint
.
Effect
]
=
sets
.
String
{}
}
uniqueTaints
[
newTaint
.
Effect
]
.
Insert
(
newTaint
.
Key
)
taints
=
append
(
taints
,
newTaint
)
}
else
if
strings
.
HasSuffix
(
taintSpec
,
"-"
)
{
taintKey
:=
taintSpec
[
:
len
(
taintSpec
)
-
1
]
var
effect
corev1
.
TaintEffect
if
strings
.
Index
(
taintKey
,
":"
)
!=
-
1
{
parts
:=
strings
.
Split
(
taintKey
,
":"
)
taintKey
=
parts
[
0
]
effect
=
corev1
.
TaintEffect
(
parts
[
1
])
}
// If effect is specified, need to validate it.
if
len
(
effect
)
>
0
{
err
:=
validateTaintEffect
(
effect
)
if
err
!=
nil
{
return
nil
,
nil
,
err
}
}
taintsToRemove
=
append
(
taintsToRemove
,
corev1
.
Taint
{
Key
:
taintKey
,
Effect
:
effect
})
}
else
{
return
nil
,
nil
,
fmt
.
Errorf
(
"unknown taint spec: %v"
,
taintSpec
)
}
}
return
taints
,
taintsToRemove
,
nil
}
// parseTaint parses a taint from a string. Taint must be of the format '<key>=<value>:<effect>'.
func
parseTaint
(
st
string
)
(
corev1
.
Taint
,
error
)
{
var
taint
corev1
.
Taint
parts
:=
strings
.
Split
(
st
,
"="
)
if
len
(
parts
)
!=
2
||
len
(
parts
[
1
])
==
0
||
len
(
validation
.
IsQualifiedName
(
parts
[
0
]))
>
0
{
return
taint
,
fmt
.
Errorf
(
"invalid taint spec: %v"
,
st
)
}
parts2
:=
strings
.
Split
(
parts
[
1
],
":"
)
errs
:=
validation
.
IsValidLabelValue
(
parts2
[
0
])
if
len
(
parts2
)
!=
2
||
len
(
errs
)
!=
0
{
return
taint
,
fmt
.
Errorf
(
"invalid taint spec: %v, %s"
,
st
,
strings
.
Join
(
errs
,
"; "
))
}
effect
:=
corev1
.
TaintEffect
(
parts2
[
1
])
if
err
:=
validateTaintEffect
(
effect
);
err
!=
nil
{
return
taint
,
err
}
taint
.
Key
=
parts
[
0
]
taint
.
Value
=
parts2
[
0
]
taint
.
Effect
=
effect
return
taint
,
nil
}
func
validateTaintEffect
(
effect
corev1
.
TaintEffect
)
error
{
if
effect
!=
corev1
.
TaintEffectNoSchedule
&&
effect
!=
corev1
.
TaintEffectPreferNoSchedule
&&
effect
!=
corev1
.
TaintEffectNoExecute
{
return
fmt
.
Errorf
(
"invalid taint effect: %v, unsupported taint effect"
,
effect
)
}
return
nil
}
// ReorganizeTaints returns the updated set of taints, taking into account old taints that were not updated,
// old taints that were updated, old taints that were deleted, and new taints.
func
reorganizeTaints
(
node
*
corev1
.
Node
,
overwrite
bool
,
taintsToAdd
[]
corev1
.
Taint
,
taintsToRemove
[]
corev1
.
Taint
)
(
string
,
[]
corev1
.
Taint
,
error
)
{
newTaints
:=
append
([]
corev1
.
Taint
{},
taintsToAdd
...
)
oldTaints
:=
node
.
Spec
.
Taints
// add taints that already existing but not updated to newTaints
added
:=
addTaints
(
oldTaints
,
&
newTaints
)
allErrs
,
deleted
:=
deleteTaints
(
taintsToRemove
,
&
newTaints
)
if
(
added
&&
deleted
)
||
overwrite
{
return
MODIFIED
,
newTaints
,
utilerrors
.
NewAggregate
(
allErrs
)
}
else
if
added
{
return
TAINTED
,
newTaints
,
utilerrors
.
NewAggregate
(
allErrs
)
}
return
UNTAINTED
,
newTaints
,
utilerrors
.
NewAggregate
(
allErrs
)
}
// deleteTaints deletes the given taints from the node's taintlist.
func
deleteTaints
(
taintsToRemove
[]
corev1
.
Taint
,
newTaints
*
[]
corev1
.
Taint
)
([]
error
,
bool
)
{
allErrs
:=
[]
error
{}
var
removed
bool
for
_
,
taintToRemove
:=
range
taintsToRemove
{
removed
=
false
if
len
(
taintToRemove
.
Effect
)
>
0
{
*
newTaints
,
removed
=
deleteTaint
(
*
newTaints
,
&
taintToRemove
)
}
else
{
*
newTaints
,
removed
=
deleteTaintsByKey
(
*
newTaints
,
taintToRemove
.
Key
)
}
if
!
removed
{
allErrs
=
append
(
allErrs
,
fmt
.
Errorf
(
"taint %q not found"
,
taintToRemove
.
ToString
()))
}
}
return
allErrs
,
removed
}
// addTaints adds the newTaints list to existing ones and updates the newTaints List.
// TODO: This needs a rewrite to take only the new values instead of appended newTaints list to be consistent.
func
addTaints
(
oldTaints
[]
corev1
.
Taint
,
newTaints
*
[]
corev1
.
Taint
)
bool
{
for
_
,
oldTaint
:=
range
oldTaints
{
existsInNew
:=
false
for
_
,
taint
:=
range
*
newTaints
{
if
taint
.
MatchTaint
(
&
oldTaint
)
{
existsInNew
=
true
break
}
}
if
!
existsInNew
{
*
newTaints
=
append
(
*
newTaints
,
oldTaint
)
}
}
return
len
(
oldTaints
)
!=
len
(
*
newTaints
)
}
// CheckIfTaintsAlreadyExists checks if the node already has taints that we want to add and returns a string with taint keys.
func
checkIfTaintsAlreadyExists
(
oldTaints
[]
corev1
.
Taint
,
taints
[]
corev1
.
Taint
)
string
{
var
existingTaintList
=
make
([]
string
,
0
)
for
_
,
taint
:=
range
taints
{
for
_
,
oldTaint
:=
range
oldTaints
{
if
taint
.
Key
==
oldTaint
.
Key
&&
taint
.
Effect
==
oldTaint
.
Effect
{
existingTaintList
=
append
(
existingTaintList
,
taint
.
Key
)
}
}
}
return
strings
.
Join
(
existingTaintList
,
","
)
}
// DeleteTaintsByKey removes all the taints that have the same key to given taintKey
func
deleteTaintsByKey
(
taints
[]
corev1
.
Taint
,
taintKey
string
)
([]
corev1
.
Taint
,
bool
)
{
newTaints
:=
[]
corev1
.
Taint
{}
deleted
:=
false
for
i
:=
range
taints
{
if
taintKey
==
taints
[
i
]
.
Key
{
deleted
=
true
continue
}
newTaints
=
append
(
newTaints
,
taints
[
i
])
}
return
newTaints
,
deleted
}
// DeleteTaint removes all the taints that have the same key and effect to given taintToDelete.
func
deleteTaint
(
taints
[]
corev1
.
Taint
,
taintToDelete
*
corev1
.
Taint
)
([]
corev1
.
Taint
,
bool
)
{
newTaints
:=
[]
corev1
.
Taint
{}
deleted
:=
false
for
i
:=
range
taints
{
if
taintToDelete
.
MatchTaint
(
&
taints
[
i
])
{
deleted
=
true
continue
}
newTaints
=
append
(
newTaints
,
taints
[
i
])
}
return
newTaints
,
deleted
}
pkg/kubectl/cmd/taint/utils_test.go
0 → 100644
View file @
8c196137
This diff is collapsed.
Click to expand it.
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