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
50c5b379
Commit
50c5b379
authored
Oct 04, 2018
by
Sean Sullivan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
kubectl env resolve: copy core fieldpath and resource dependencies into kubectl
parent
d4c48718
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
155 additions
and
17 deletions
+155
-17
BUILD
pkg/kubectl/cmd/set/env/BUILD
+3
-2
env_resolve.go
pkg/kubectl/cmd/set/env/env_resolve.go
+152
-15
No files found.
pkg/kubectl/cmd/set/env/BUILD
View file @
50c5b379
...
@@ -10,12 +10,13 @@ go_library(
...
@@ -10,12 +10,13 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/set/env",
importpath = "k8s.io/kubernetes/pkg/kubectl/cmd/set/env",
visibility = ["//visibility:public"],
visibility = ["//visibility:public"],
deps = [
deps = [
"//pkg/api/v1/resource:go_default_library",
"//pkg/fieldpath:go_default_library",
"//staging/src/k8s.io/api/core/v1: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/api/resource:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
],
],
)
)
...
...
pkg/kubectl/cmd/set/env/env_resolve.go
View file @
50c5b379
...
@@ -18,31 +18,36 @@ package env
...
@@ -18,31 +18,36 @@ package env
import
(
import
(
"fmt"
"fmt"
"math"
"strconv"
"strings"
"k8s.io/api/core/v1"
corev1
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/api/resource"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/validation"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/api/v1/resource"
"k8s.io/kubernetes/pkg/fieldpath"
)
)
// ResourceStore defines a new resource store data structure.
// ResourceStore defines a new resource store data structure.
type
ResourceStore
struct
{
type
ResourceStore
struct
{
SecretStore
map
[
string
]
*
v1
.
Secret
SecretStore
map
[
string
]
*
core
v1
.
Secret
ConfigMapStore
map
[
string
]
*
v1
.
ConfigMap
ConfigMapStore
map
[
string
]
*
core
v1
.
ConfigMap
}
}
// NewResourceStore returns a pointer to a new resource store data structure.
// NewResourceStore returns a pointer to a new resource store data structure.
func
NewResourceStore
()
*
ResourceStore
{
func
NewResourceStore
()
*
ResourceStore
{
return
&
ResourceStore
{
return
&
ResourceStore
{
SecretStore
:
make
(
map
[
string
]
*
v1
.
Secret
),
SecretStore
:
make
(
map
[
string
]
*
core
v1
.
Secret
),
ConfigMapStore
:
make
(
map
[
string
]
*
v1
.
ConfigMap
),
ConfigMapStore
:
make
(
map
[
string
]
*
core
v1
.
ConfigMap
),
}
}
}
}
// getSecretRefValue returns the value of a secret in the supplied namespace
// getSecretRefValue returns the value of a secret in the supplied namespace
func
getSecretRefValue
(
client
kubernetes
.
Interface
,
namespace
string
,
store
*
ResourceStore
,
secretSelector
*
v1
.
SecretKeySelector
)
(
string
,
error
)
{
func
getSecretRefValue
(
client
kubernetes
.
Interface
,
namespace
string
,
store
*
ResourceStore
,
secretSelector
*
core
v1
.
SecretKeySelector
)
(
string
,
error
)
{
secret
,
ok
:=
store
.
SecretStore
[
secretSelector
.
Name
]
secret
,
ok
:=
store
.
SecretStore
[
secretSelector
.
Name
]
if
!
ok
{
if
!
ok
{
var
err
error
var
err
error
...
@@ -60,7 +65,7 @@ func getSecretRefValue(client kubernetes.Interface, namespace string, store *Res
...
@@ -60,7 +65,7 @@ func getSecretRefValue(client kubernetes.Interface, namespace string, store *Res
}
}
// getConfigMapRefValue returns the value of a configmap in the supplied namespace
// getConfigMapRefValue returns the value of a configmap in the supplied namespace
func
getConfigMapRefValue
(
client
kubernetes
.
Interface
,
namespace
string
,
store
*
ResourceStore
,
configMapSelector
*
v1
.
ConfigMapKeySelector
)
(
string
,
error
)
{
func
getConfigMapRefValue
(
client
kubernetes
.
Interface
,
namespace
string
,
store
*
ResourceStore
,
configMapSelector
*
core
v1
.
ConfigMapKeySelector
)
(
string
,
error
)
{
configMap
,
ok
:=
store
.
ConfigMapStore
[
configMapSelector
.
Name
]
configMap
,
ok
:=
store
.
ConfigMapStore
[
configMapSelector
.
Name
]
if
!
ok
{
if
!
ok
{
var
err
error
var
err
error
...
@@ -77,17 +82,149 @@ func getConfigMapRefValue(client kubernetes.Interface, namespace string, store *
...
@@ -77,17 +82,149 @@ func getConfigMapRefValue(client kubernetes.Interface, namespace string, store *
}
}
// getFieldRef returns the value of the supplied path in the given object
// getFieldRef returns the value of the supplied path in the given object
func
getFieldRef
(
obj
runtime
.
Object
,
from
*
v1
.
EnvVarSource
)
(
string
,
error
)
{
func
getFieldRef
(
obj
runtime
.
Object
,
from
*
corev1
.
EnvVarSource
)
(
string
,
error
)
{
return
fieldpath
.
ExtractFieldPathAsString
(
obj
,
from
.
FieldRef
.
FieldPath
)
return
extractFieldPathAsString
(
obj
,
from
.
FieldRef
.
FieldPath
)
}
// extractFieldPathAsString extracts the field from the given object
// and returns it as a string. The object must be a pointer to an
// API type.
func
extractFieldPathAsString
(
obj
interface
{},
fieldPath
string
)
(
string
,
error
)
{
accessor
,
err
:=
meta
.
Accessor
(
obj
)
if
err
!=
nil
{
return
""
,
nil
}
if
path
,
subscript
,
ok
:=
splitMaybeSubscriptedPath
(
fieldPath
);
ok
{
switch
path
{
case
"metadata.annotations"
:
if
errs
:=
validation
.
IsQualifiedName
(
strings
.
ToLower
(
subscript
));
len
(
errs
)
!=
0
{
return
""
,
fmt
.
Errorf
(
"invalid key subscript in %s: %s"
,
fieldPath
,
strings
.
Join
(
errs
,
";"
))
}
return
accessor
.
GetAnnotations
()[
subscript
],
nil
case
"metadata.labels"
:
if
errs
:=
validation
.
IsQualifiedName
(
subscript
);
len
(
errs
)
!=
0
{
return
""
,
fmt
.
Errorf
(
"invalid key subscript in %s: %s"
,
fieldPath
,
strings
.
Join
(
errs
,
";"
))
}
return
accessor
.
GetLabels
()[
subscript
],
nil
default
:
return
""
,
fmt
.
Errorf
(
"fieldPath %q does not support subscript"
,
fieldPath
)
}
}
switch
fieldPath
{
case
"metadata.annotations"
:
return
formatMap
(
accessor
.
GetAnnotations
()),
nil
case
"metadata.labels"
:
return
formatMap
(
accessor
.
GetLabels
()),
nil
case
"metadata.name"
:
return
accessor
.
GetName
(),
nil
case
"metadata.namespace"
:
return
accessor
.
GetNamespace
(),
nil
case
"metadata.uid"
:
return
string
(
accessor
.
GetUID
()),
nil
}
return
""
,
fmt
.
Errorf
(
"unsupported fieldPath: %v"
,
fieldPath
)
}
// splitMaybeSubscriptedPath checks whether the specified fieldPath is
// subscripted, and
// - if yes, this function splits the fieldPath into path and subscript, and
// returns (path, subscript, true).
// - if no, this function returns (fieldPath, "", false).
//
// Example inputs and outputs:
// - "metadata.annotations['myKey']" --> ("metadata.annotations", "myKey", true)
// - "metadata.annotations['a[b]c']" --> ("metadata.annotations", "a[b]c", true)
// - "metadata.labels['']" --> ("metadata.labels", "", true)
// - "metadata.labels" --> ("metadata.labels", "", false)
func
splitMaybeSubscriptedPath
(
fieldPath
string
)
(
string
,
string
,
bool
)
{
if
!
strings
.
HasSuffix
(
fieldPath
,
"']"
)
{
return
fieldPath
,
""
,
false
}
s
:=
strings
.
TrimSuffix
(
fieldPath
,
"']"
)
parts
:=
strings
.
SplitN
(
s
,
"['"
,
2
)
if
len
(
parts
)
<
2
{
return
fieldPath
,
""
,
false
}
if
len
(
parts
[
0
])
==
0
{
return
fieldPath
,
""
,
false
}
return
parts
[
0
],
parts
[
1
],
true
}
// formatMap formats map[string]string to a string.
func
formatMap
(
m
map
[
string
]
string
)
(
fmtStr
string
)
{
// output with keys in sorted order to provide stable output
keys
:=
sets
.
NewString
()
for
key
:=
range
m
{
keys
.
Insert
(
key
)
}
for
_
,
key
:=
range
keys
.
List
()
{
fmtStr
+=
fmt
.
Sprintf
(
"%v=%q
\n
"
,
key
,
m
[
key
])
}
fmtStr
=
strings
.
TrimSuffix
(
fmtStr
,
"
\n
"
)
return
}
}
// getResourceFieldRef returns the value of a resource in the given container
// getResourceFieldRef returns the value of a resource in the given container
func
getResourceFieldRef
(
from
*
v1
.
EnvVarSource
,
c
*
v1
.
Container
)
(
string
,
error
)
{
func
getResourceFieldRef
(
from
*
corev1
.
EnvVarSource
,
container
*
corev1
.
Container
)
(
string
,
error
)
{
return
resource
.
ExtractContainerResourceValue
(
from
.
ResourceFieldRef
,
c
)
return
extractContainerResourceValue
(
from
.
ResourceFieldRef
,
container
)
}
// ExtractContainerResourceValue extracts the value of a resource
// in an already known container
func
extractContainerResourceValue
(
fs
*
corev1
.
ResourceFieldSelector
,
container
*
corev1
.
Container
)
(
string
,
error
)
{
divisor
:=
resource
.
Quantity
{}
if
divisor
.
Cmp
(
fs
.
Divisor
)
==
0
{
divisor
=
resource
.
MustParse
(
"1"
)
}
else
{
divisor
=
fs
.
Divisor
}
switch
fs
.
Resource
{
case
"limits.cpu"
:
return
convertResourceCPUToString
(
container
.
Resources
.
Limits
.
Cpu
(),
divisor
)
case
"limits.memory"
:
return
convertResourceMemoryToString
(
container
.
Resources
.
Limits
.
Memory
(),
divisor
)
case
"limits.ephemeral-storage"
:
return
convertResourceEphemeralStorageToString
(
container
.
Resources
.
Limits
.
StorageEphemeral
(),
divisor
)
case
"requests.cpu"
:
return
convertResourceCPUToString
(
container
.
Resources
.
Requests
.
Cpu
(),
divisor
)
case
"requests.memory"
:
return
convertResourceMemoryToString
(
container
.
Resources
.
Requests
.
Memory
(),
divisor
)
case
"requests.ephemeral-storage"
:
return
convertResourceEphemeralStorageToString
(
container
.
Resources
.
Requests
.
StorageEphemeral
(),
divisor
)
}
return
""
,
fmt
.
Errorf
(
"Unsupported container resource : %v"
,
fs
.
Resource
)
}
// convertResourceCPUToString converts cpu value to the format of divisor and returns
// ceiling of the value.
func
convertResourceCPUToString
(
cpu
*
resource
.
Quantity
,
divisor
resource
.
Quantity
)
(
string
,
error
)
{
c
:=
int64
(
math
.
Ceil
(
float64
(
cpu
.
MilliValue
())
/
float64
(
divisor
.
MilliValue
())))
return
strconv
.
FormatInt
(
c
,
10
),
nil
}
// convertResourceMemoryToString converts memory value to the format of divisor and returns
// ceiling of the value.
func
convertResourceMemoryToString
(
memory
*
resource
.
Quantity
,
divisor
resource
.
Quantity
)
(
string
,
error
)
{
m
:=
int64
(
math
.
Ceil
(
float64
(
memory
.
Value
())
/
float64
(
divisor
.
Value
())))
return
strconv
.
FormatInt
(
m
,
10
),
nil
}
// convertResourceEphemeralStorageToString converts ephemeral storage value to the format of divisor and returns
// ceiling of the value.
func
convertResourceEphemeralStorageToString
(
ephemeralStorage
*
resource
.
Quantity
,
divisor
resource
.
Quantity
)
(
string
,
error
)
{
m
:=
int64
(
math
.
Ceil
(
float64
(
ephemeralStorage
.
Value
())
/
float64
(
divisor
.
Value
())))
return
strconv
.
FormatInt
(
m
,
10
),
nil
}
}
// GetEnvVarRefValue returns the value referenced by the supplied EnvVarSource given the other supplied information.
// GetEnvVarRefValue returns the value referenced by the supplied EnvVarSource given the other supplied information.
func
GetEnvVarRefValue
(
kc
kubernetes
.
Interface
,
ns
string
,
store
*
ResourceStore
,
from
*
v1
.
EnvVarSource
,
obj
runtime
.
Object
,
c
*
v1
.
Container
)
(
string
,
error
)
{
func
GetEnvVarRefValue
(
kc
kubernetes
.
Interface
,
ns
string
,
store
*
ResourceStore
,
from
*
corev1
.
EnvVarSource
,
obj
runtime
.
Object
,
c
*
core
v1
.
Container
)
(
string
,
error
)
{
if
from
.
SecretKeyRef
!=
nil
{
if
from
.
SecretKeyRef
!=
nil
{
return
getSecretRefValue
(
kc
,
ns
,
store
,
from
.
SecretKeyRef
)
return
getSecretRefValue
(
kc
,
ns
,
store
,
from
.
SecretKeyRef
)
}
}
...
@@ -108,7 +245,7 @@ func GetEnvVarRefValue(kc kubernetes.Interface, ns string, store *ResourceStore,
...
@@ -108,7 +245,7 @@ func GetEnvVarRefValue(kc kubernetes.Interface, ns string, store *ResourceStore,
}
}
// GetEnvVarRefString returns a text description of whichever field is set within the supplied EnvVarSource argument.
// GetEnvVarRefString returns a text description of whichever field is set within the supplied EnvVarSource argument.
func
GetEnvVarRefString
(
from
*
v1
.
EnvVarSource
)
string
{
func
GetEnvVarRefString
(
from
*
core
v1
.
EnvVarSource
)
string
{
if
from
.
ConfigMapKeyRef
!=
nil
{
if
from
.
ConfigMapKeyRef
!=
nil
{
return
fmt
.
Sprintf
(
"configmap %s, key %s"
,
from
.
ConfigMapKeyRef
.
Name
,
from
.
ConfigMapKeyRef
.
Key
)
return
fmt
.
Sprintf
(
"configmap %s, key %s"
,
from
.
ConfigMapKeyRef
.
Name
,
from
.
ConfigMapKeyRef
.
Key
)
}
}
...
...
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