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
19441898
Commit
19441898
authored
Aug 10, 2017
by
NickrenREN
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add local storage to downwards API
parent
acdf625e
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
85 additions
and
3 deletions
+85
-3
helpers.go
pkg/api/resource/helpers.go
+11
-0
types.go
pkg/api/types.go
+1
-1
helpers.go
pkg/api/v1/resource/helpers.go
+11
-0
validation.go
pkg/api/validation/validation.go
+15
-1
validation_test.go
pkg/api/validation/validation_test.go
+46
-0
types.go
staging/src/k8s.io/api/core/v1/types.go
+1
-1
No files found.
pkg/api/resource/helpers.go
View file @
19441898
...
...
@@ -88,10 +88,14 @@ func ExtractContainerResourceValue(fs *api.ResourceFieldSelector, container *api
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
)
...
...
@@ -110,3 +114,10 @@ func convertResourceMemoryToString(memory *resource.Quantity, divisor resource.Q
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
}
pkg/api/types.go
View file @
19441898
...
...
@@ -1470,7 +1470,7 @@ type EnvVarSource struct {
// +optional
FieldRef
*
ObjectFieldSelector
// Selects a resource of the container: only resources limits and requests
// (limits.cpu, limits.memory,
requests.cpu and requests.memory
) are currently supported.
// (limits.cpu, limits.memory,
limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage
) are currently supported.
// +optional
ResourceFieldRef
*
ResourceFieldSelector
// Selects a key of a ConfigMap.
...
...
pkg/api/v1/resource/helpers.go
View file @
19441898
...
...
@@ -153,10 +153,14 @@ func ExtractContainerResourceValue(fs *v1.ResourceFieldSelector, container *v1.C
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
)
...
...
@@ -176,6 +180,13 @@ func convertResourceMemoryToString(memory *resource.Quantity, divisor resource.Q
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
}
// findContainerInPod finds a container by its name in the provided pod
func
findContainerInPod
(
pod
*
v1
.
Pod
,
containerName
string
)
(
*
v1
.
Container
,
error
)
{
for
_
,
container
:=
range
pod
.
Spec
.
Containers
{
...
...
pkg/api/validation/validation.go
View file @
19441898
...
...
@@ -1644,7 +1644,7 @@ func ValidateEnv(vars []api.EnvVar, fldPath *field.Path) field.ErrorList {
}
var
validFieldPathExpressionsEnv
=
sets
.
NewString
(
"metadata.name"
,
"metadata.namespace"
,
"metadata.uid"
,
"spec.nodeName"
,
"spec.serviceAccountName"
,
"status.hostIP"
,
"status.podIP"
)
var
validContainerResourceFieldPathExpressions
=
sets
.
NewString
(
"limits.cpu"
,
"limits.memory"
,
"
requests.cpu"
,
"requests.memory
"
)
var
validContainerResourceFieldPathExpressions
=
sets
.
NewString
(
"limits.cpu"
,
"limits.memory"
,
"
limits.ephemeral-storage"
,
"requests.cpu"
,
"requests.memory"
,
"requests.ephemeral-storage
"
)
func
validateEnvVarValueFrom
(
ev
api
.
EnvVar
,
fldPath
*
field
.
Path
)
field
.
ErrorList
{
allErrs
:=
field
.
ErrorList
{}
...
...
@@ -1704,6 +1704,13 @@ func validateObjectFieldSelector(fs *api.ObjectFieldSelector, expressions *sets.
return
allErrs
}
func
fsResourceIsEphemeralStorage
(
resource
string
)
bool
{
if
resource
==
"limits.ephemeral-storage"
||
resource
==
"requests.ephemeral-storage"
{
return
true
}
return
false
}
func
validateContainerResourceFieldSelector
(
fs
*
api
.
ResourceFieldSelector
,
expressions
*
sets
.
String
,
fldPath
*
field
.
Path
,
volume
bool
)
field
.
ErrorList
{
allErrs
:=
field
.
ErrorList
{}
...
...
@@ -1713,6 +1720,8 @@ func validateContainerResourceFieldSelector(fs *api.ResourceFieldSelector, expre
allErrs
=
append
(
allErrs
,
field
.
Required
(
fldPath
.
Child
(
"resource"
),
""
))
}
else
if
!
expressions
.
Has
(
fs
.
Resource
)
{
allErrs
=
append
(
allErrs
,
field
.
NotSupported
(
fldPath
.
Child
(
"resource"
),
fs
.
Resource
,
expressions
.
List
()))
}
else
if
fsResourceIsEphemeralStorage
(
fs
.
Resource
)
&&
!
utilfeature
.
DefaultFeatureGate
.
Enabled
(
features
.
LocalStorageCapacityIsolation
)
{
allErrs
=
append
(
allErrs
,
field
.
Forbidden
(
fldPath
,
"Containers' ephemeral storage requests/limits disabled by feature-gate for Downward API"
))
}
allErrs
=
append
(
allErrs
,
validateContainerResourceDivisor
(
fs
.
Resource
,
fs
.
Divisor
,
fldPath
)
...
)
return
allErrs
...
...
@@ -1773,6 +1782,7 @@ func validateSecretEnvSource(secretSource *api.SecretEnvSource, fldPath *field.P
var
validContainerResourceDivisorForCPU
=
sets
.
NewString
(
"1m"
,
"1"
)
var
validContainerResourceDivisorForMemory
=
sets
.
NewString
(
"1"
,
"1k"
,
"1M"
,
"1G"
,
"1T"
,
"1P"
,
"1E"
,
"1Ki"
,
"1Mi"
,
"1Gi"
,
"1Ti"
,
"1Pi"
,
"1Ei"
)
var
validContainerResourceDivisorForEphemeralStorage
=
sets
.
NewString
(
"1"
,
"1k"
,
"1M"
,
"1G"
,
"1T"
,
"1P"
,
"1E"
,
"1Ki"
,
"1Mi"
,
"1Gi"
,
"1Ti"
,
"1Pi"
,
"1Ei"
)
func
validateContainerResourceDivisor
(
rName
string
,
divisor
resource
.
Quantity
,
fldPath
*
field
.
Path
)
field
.
ErrorList
{
allErrs
:=
field
.
ErrorList
{}
...
...
@@ -1789,6 +1799,10 @@ func validateContainerResourceDivisor(rName string, divisor resource.Quantity, f
if
!
validContainerResourceDivisorForMemory
.
Has
(
divisor
.
String
())
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"divisor"
),
rName
,
"only divisor's values 1, 1k, 1M, 1G, 1T, 1P, 1E, 1Ki, 1Mi, 1Gi, 1Ti, 1Pi, 1Ei are supported with the memory resource"
))
}
case
"limits.ephemeral-storage"
,
"requests.ephemeral-storage"
:
if
!
validContainerResourceDivisorForEphemeralStorage
.
Has
(
divisor
.
String
())
{
allErrs
=
append
(
allErrs
,
field
.
Invalid
(
fldPath
.
Child
(
"divisor"
),
rName
,
"only divisor's values 1, 1k, 1M, 1G, 1T, 1P, 1E, 1Ki, 1Mi, 1Gi, 1Ti, 1Pi, 1Ei are supported with the local ephemeral storage resource"
))
}
}
return
allErrs
}
...
...
pkg/api/validation/validation_test.go
View file @
19441898
...
...
@@ -2807,6 +2807,52 @@ func TestValidatePorts(t *testing.T) {
}
}
func
TestLocalStorageEnvWithFeatureGate
(
t
*
testing
.
T
)
{
testCases
:=
[]
api
.
EnvVar
{
{
Name
:
"ephemeral-storage-limits"
,
ValueFrom
:
&
api
.
EnvVarSource
{
ResourceFieldRef
:
&
api
.
ResourceFieldSelector
{
ContainerName
:
"test-container"
,
Resource
:
"limits.ephemeral-storage"
,
},
},
},
{
Name
:
"ephemeral-storage-requests"
,
ValueFrom
:
&
api
.
EnvVarSource
{
ResourceFieldRef
:
&
api
.
ResourceFieldSelector
{
ContainerName
:
"test-container"
,
Resource
:
"requests.ephemeral-storage"
,
},
},
},
}
// Enable alpha feature LocalStorageCapacityIsolation
err
:=
utilfeature
.
DefaultFeatureGate
.
Set
(
"LocalStorageCapacityIsolation=true"
)
if
err
!=
nil
{
t
.
Errorf
(
"Failed to enable feature gate for LocalStorageCapacityIsolation: %v"
,
err
)
return
}
for
_
,
testCase
:=
range
testCases
{
if
errs
:=
validateEnvVarValueFrom
(
testCase
,
field
.
NewPath
(
"field"
));
len
(
errs
)
!=
0
{
t
.
Errorf
(
"expected success, got: %v"
,
errs
)
}
}
// Disable alpha feature LocalStorageCapacityIsolation
err
=
utilfeature
.
DefaultFeatureGate
.
Set
(
"LocalStorageCapacityIsolation=false"
)
if
err
!=
nil
{
t
.
Errorf
(
"Failed to disable feature gate for LocalStorageCapacityIsolation: %v"
,
err
)
return
}
for
_
,
testCase
:=
range
testCases
{
if
errs
:=
validateEnvVarValueFrom
(
testCase
,
field
.
NewPath
(
"field"
));
len
(
errs
)
==
0
{
t
.
Errorf
(
"expected failure for %v"
,
testCase
.
Name
)
}
}
}
func
TestValidateEnv
(
t
*
testing
.
T
)
{
successCase
:=
[]
api
.
EnvVar
{
{
Name
:
"abc"
,
Value
:
"value"
},
...
...
staging/src/k8s.io/api/core/v1/types.go
View file @
19441898
...
...
@@ -1573,7 +1573,7 @@ type EnvVarSource struct {
// +optional
FieldRef
*
ObjectFieldSelector
`json:"fieldRef,omitempty" protobuf:"bytes,1,opt,name=fieldRef"`
// Selects a resource of the container: only resources limits and requests
// (limits.cpu, limits.memory,
requests.cpu and requests.memory
) are currently supported.
// (limits.cpu, limits.memory,
limits.ephemeral-storage, requests.cpu, requests.memory and requests.ephemeral-storage
) are currently supported.
// +optional
ResourceFieldRef
*
ResourceFieldSelector
`json:"resourceFieldRef,omitempty" protobuf:"bytes,2,opt,name=resourceFieldRef"`
// Selects a key of a ConfigMap.
...
...
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