2014-10-27 19:56:34 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2014 The Kubernetes Authors .
2014-10-27 19:56:34 +00:00
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 .
* /
2017-02-19 03:40:38 +00:00
package internalversion
2014-10-27 19:56:34 +00:00
import (
2015-04-02 15:42:19 +00:00
"bytes"
2015-02-26 18:50:12 +00:00
"fmt"
"reflect"
2017-05-15 06:27:14 +00:00
"regexp"
2014-10-27 19:56:34 +00:00
"strings"
"testing"
2014-12-16 22:20:51 +00:00
"time"
2014-10-27 19:56:34 +00:00
2018-03-20 16:45:19 +00:00
appsv1 "k8s.io/api/apps/v1"
2017-06-22 18:24:23 +00:00
"k8s.io/api/core/v1"
2017-01-25 13:39:54 +00:00
apiequality "k8s.io/apimachinery/pkg/api/equality"
2017-01-25 13:13:07 +00:00
"k8s.io/apimachinery/pkg/api/resource"
2017-01-11 14:09:48 +00:00
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2017-04-07 00:14:16 +00:00
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2017-01-27 20:42:17 +00:00
"k8s.io/apimachinery/pkg/util/intstr"
2017-06-23 20:56:37 +00:00
versionedfake "k8s.io/client-go/kubernetes/fake"
2018-05-15 04:42:13 +00:00
"k8s.io/kubernetes/pkg/apis/apps"
2016-11-30 20:58:58 +00:00
"k8s.io/kubernetes/pkg/apis/autoscaling"
2017-11-08 22:34:54 +00:00
api "k8s.io/kubernetes/pkg/apis/core"
2015-10-09 22:04:41 +00:00
"k8s.io/kubernetes/pkg/apis/extensions"
2017-06-05 04:12:21 +00:00
"k8s.io/kubernetes/pkg/apis/networking"
2016-11-09 12:39:16 +00:00
"k8s.io/kubernetes/pkg/apis/policy"
2016-09-08 11:03:12 +00:00
"k8s.io/kubernetes/pkg/apis/storage"
2016-09-08 15:50:53 +00:00
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
2016-02-16 22:16:45 +00:00
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
2017-02-19 22:37:24 +00:00
"k8s.io/kubernetes/pkg/printers"
2017-06-29 08:39:26 +00:00
utilpointer "k8s.io/kubernetes/pkg/util/pointer"
2014-10-27 19:56:34 +00:00
)
type describeClient struct {
T * testing . T
Namespace string
Err error
2016-09-08 15:50:53 +00:00
internalclientset . Interface
2014-10-27 19:56:34 +00:00
}
func TestDescribePod ( t * testing . T ) {
2016-09-08 15:50:53 +00:00
fake := fake . NewSimpleClientset ( & api . Pod {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2015-04-06 23:27:53 +00:00
Name : "bar" ,
Namespace : "foo" ,
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
2014-11-14 01:42:50 +00:00
d := PodDescriber { c }
2017-02-19 22:37:24 +00:00
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
2014-10-27 19:56:34 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "bar" ) || ! strings . Contains ( out , "Status:" ) {
t . Errorf ( "unexpected out: %s" , out )
}
}
2017-05-13 13:59:04 +00:00
func TestDescribePodNode ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & api . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
Spec : api . PodSpec {
NodeName : "all-in-one" ,
} ,
Status : api . PodStatus {
2018-01-25 21:23:56 +00:00
HostIP : "127.0.0.1" ,
NominatedNodeName : "nodeA" ,
2017-05-13 13:59:04 +00:00
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := PodDescriber { c }
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "all-in-one/127.0.0.1" ) {
t . Errorf ( "unexpected out: %s" , out )
}
2018-01-25 21:23:56 +00:00
if ! strings . Contains ( out , "nodeA" ) {
t . Errorf ( "unexpected out: %s" , out )
}
2017-05-13 13:59:04 +00:00
}
2016-08-10 17:39:11 +00:00
func TestDescribePodTolerations ( t * testing . T ) {
2016-09-08 15:50:53 +00:00
fake := fake . NewSimpleClientset ( & api . Pod {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-08-10 17:39:11 +00:00
Name : "bar" ,
Namespace : "foo" ,
2017-02-07 14:08:45 +00:00
} ,
Spec : api . PodSpec {
Tolerations : [ ] api . Toleration {
2017-06-12 22:30:02 +00:00
{ Key : "key0" , Operator : api . TolerationOpExists } ,
2017-02-07 14:08:45 +00:00
{ Key : "key1" , Value : "value1" } ,
2017-06-12 22:30:02 +00:00
{ Key : "key2" , Operator : api . TolerationOpEqual , Value : "value2" , Effect : api . TaintEffectNoSchedule } ,
{ Key : "key3" , Value : "value3" , Effect : api . TaintEffectNoExecute , TolerationSeconds : & [ ] int64 { 300 } [ 0 ] } ,
{ Key : "key4" , Effect : api . TaintEffectNoExecute , TolerationSeconds : & [ ] int64 { 60 } [ 0 ] } ,
2016-08-10 17:39:11 +00:00
} ,
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := PodDescriber { c }
2017-02-19 22:37:24 +00:00
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { } )
2016-08-10 17:39:11 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2017-06-12 22:30:02 +00:00
if ! strings . Contains ( out , "key0\n" ) ||
! strings . Contains ( out , "key1=value1\n" ) ||
! strings . Contains ( out , "key2=value2:NoSchedule\n" ) ||
! strings . Contains ( out , "key3=value3:NoExecute for 300s\n" ) ||
! strings . Contains ( out , "key4:NoExecute for 60s\n" ) ||
! strings . Contains ( out , "Tolerations:" ) {
t . Errorf ( "unexpected out:\n%s" , out )
2016-09-15 22:08:57 +00:00
}
}
2017-08-25 01:32:28 +00:00
func TestDescribeSecret ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & api . Secret {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
Data : map [ string ] [ ] byte {
"username" : [ ] byte ( "YWRtaW4=" ) ,
"password" : [ ] byte ( "MWYyZDFlMmU2N2Rm" ) ,
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := SecretDescriber { c }
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "bar" ) || ! strings . Contains ( out , "foo" ) || ! strings . Contains ( out , "username" ) || ! strings . Contains ( out , "8 bytes" ) || ! strings . Contains ( out , "password" ) || ! strings . Contains ( out , "16 bytes" ) {
t . Errorf ( "unexpected out: %s" , out )
}
if strings . Contains ( out , "YWRtaW4=" ) || strings . Contains ( out , "MWYyZDFlMmU2N2Rm" ) {
t . Errorf ( "sensitive data should not be shown, unexpected out: %s" , out )
}
}
2016-09-15 22:08:57 +00:00
func TestDescribeNamespace ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & api . Namespace {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-09-15 22:08:57 +00:00
Name : "myns" ,
} ,
} )
c := & describeClient { T : t , Namespace : "" , Interface : fake }
d := NamespaceDescriber { c }
2017-02-19 22:37:24 +00:00
out , err := d . Describe ( "" , "myns" , printers . DescriberSettings { ShowEvents : true } )
2016-09-15 22:08:57 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "myns" ) {
2016-08-10 17:39:11 +00:00
t . Errorf ( "unexpected out: %s" , out )
}
}
2017-10-26 09:01:46 +00:00
func TestDescribePodPriority ( t * testing . T ) {
priority := int32 ( 1000 )
fake := fake . NewSimpleClientset ( & api . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
} ,
Spec : api . PodSpec {
PriorityClassName : "high-priority" ,
Priority : & priority ,
} ,
} )
c := & describeClient { T : t , Namespace : "" , Interface : fake }
d := PodDescriber { c }
out , err := d . Describe ( "" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "high-priority" ) || ! strings . Contains ( out , "1000" ) {
t . Errorf ( "unexpected out: %s" , out )
}
}
2017-05-17 14:16:56 +00:00
func TestDescribeConfigMap ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & api . ConfigMap {
ObjectMeta : metav1 . ObjectMeta {
Name : "mycm" ,
Namespace : "foo" ,
} ,
Data : map [ string ] string {
"key1" : "value1" ,
"key2" : "value2" ,
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := ConfigMapDescriber { c }
out , err := d . Describe ( "foo" , "mycm" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "foo" ) || ! strings . Contains ( out , "mycm" ) || ! strings . Contains ( out , "key1" ) || ! strings . Contains ( out , "value1" ) || ! strings . Contains ( out , "key2" ) || ! strings . Contains ( out , "value2" ) {
t . Errorf ( "unexpected out: %s" , out )
}
}
2017-08-19 07:30:36 +00:00
func TestDescribeLimitRange ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & api . LimitRange {
ObjectMeta : metav1 . ObjectMeta {
Name : "mylr" ,
Namespace : "foo" ,
} ,
Spec : api . LimitRangeSpec {
Limits : [ ] api . LimitRangeItem {
{
Type : api . LimitTypePod ,
Max : getResourceList ( "100m" , "10000Mi" ) ,
Min : getResourceList ( "5m" , "100Mi" ) ,
MaxLimitRequestRatio : getResourceList ( "10" , "" ) ,
} ,
{
Type : api . LimitTypeContainer ,
Max : getResourceList ( "100m" , "10000Mi" ) ,
Min : getResourceList ( "5m" , "100Mi" ) ,
Default : getResourceList ( "50m" , "500Mi" ) ,
DefaultRequest : getResourceList ( "10m" , "200Mi" ) ,
MaxLimitRequestRatio : getResourceList ( "10" , "" ) ,
} ,
{
Type : api . LimitTypePersistentVolumeClaim ,
Max : getStorageResourceList ( "10Gi" ) ,
Min : getStorageResourceList ( "5Gi" ) ,
} ,
} ,
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := LimitRangeDescriber { c }
out , err := d . Describe ( "foo" , "mylr" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
checks := [ ] string { "foo" , "mylr" , "Pod" , "cpu" , "5m" , "100m" , "memory" , "100Mi" , "10000Mi" , "10" , "Container" , "cpu" , "10m" , "50m" , "200Mi" , "500Mi" , "PersistentVolumeClaim" , "storage" , "5Gi" , "10Gi" }
for _ , check := range checks {
if ! strings . Contains ( out , check ) {
t . Errorf ( "unexpected out: %s" , out )
}
}
}
func getStorageResourceList ( storage string ) api . ResourceList {
res := api . ResourceList { }
if storage != "" {
res [ api . ResourceStorage ] = resource . MustParse ( storage )
}
return res
}
func getResourceList ( cpu , memory string ) api . ResourceList {
res := api . ResourceList { }
if cpu != "" {
res [ api . ResourceCPU ] = resource . MustParse ( cpu )
}
if memory != "" {
res [ api . ResourceMemory ] = resource . MustParse ( memory )
}
return res
}
2014-10-27 19:56:34 +00:00
func TestDescribeService ( t * testing . T ) {
2017-10-25 08:58:49 +00:00
testCases := [ ] struct {
2018-05-14 07:11:48 +00:00
name string
2017-10-25 08:58:49 +00:00
service * api . Service
expect [ ] string
} {
{
2018-05-14 07:11:48 +00:00
name : "test1" ,
2017-10-25 08:58:49 +00:00
service : & api . Service {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
Spec : api . ServiceSpec {
Type : api . ServiceTypeLoadBalancer ,
Ports : [ ] api . ServicePort { {
Name : "port-tcp" ,
Port : 8080 ,
Protocol : api . ProtocolTCP ,
TargetPort : intstr . FromInt ( 9527 ) ,
NodePort : 31111 ,
} } ,
Selector : map [ string ] string { "blah" : "heh" } ,
ClusterIP : "1.2.3.4" ,
LoadBalancerIP : "5.6.7.8" ,
SessionAffinity : "None" ,
ExternalTrafficPolicy : "Local" ,
HealthCheckNodePort : 32222 ,
} ,
} ,
expect : [ ] string {
"Name" , "bar" ,
"Namespace" , "foo" ,
"Selector" , "blah=heh" ,
"Type" , "LoadBalancer" ,
"IP" , "1.2.3.4" ,
"Port" , "port-tcp" , "8080/TCP" ,
"TargetPort" , "9527/TCP" ,
"NodePort" , "port-tcp" , "31111/TCP" ,
"Session Affinity" , "None" ,
"External Traffic Policy" , "Local" ,
"HealthCheck NodePort" , "32222" ,
} ,
2015-04-06 23:27:53 +00:00
} ,
2017-10-25 08:58:49 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test2" ,
2017-10-25 08:58:49 +00:00
service : & api . Service {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
Spec : api . ServiceSpec {
Type : api . ServiceTypeLoadBalancer ,
Ports : [ ] api . ServicePort { {
Name : "port-tcp" ,
Port : 8080 ,
Protocol : api . ProtocolTCP ,
TargetPort : intstr . FromString ( "targetPort" ) ,
NodePort : 31111 ,
} } ,
Selector : map [ string ] string { "blah" : "heh" } ,
ClusterIP : "1.2.3.4" ,
LoadBalancerIP : "5.6.7.8" ,
SessionAffinity : "None" ,
ExternalTrafficPolicy : "Local" ,
HealthCheckNodePort : 32222 ,
} ,
} ,
expect : [ ] string {
"Name" , "bar" ,
"Namespace" , "foo" ,
"Selector" , "blah=heh" ,
"Type" , "LoadBalancer" ,
"IP" , "1.2.3.4" ,
"Port" , "port-tcp" , "8080/TCP" ,
"TargetPort" , "targetPort/TCP" ,
"NodePort" , "port-tcp" , "31111/TCP" ,
"Session Affinity" , "None" ,
"External Traffic Policy" , "Local" ,
"HealthCheck NodePort" , "32222" ,
} ,
2017-08-03 08:18:54 +00:00
} ,
}
2017-10-25 08:58:49 +00:00
for _ , testCase := range testCases {
2018-05-14 07:11:48 +00:00
t . Run ( testCase . name , func ( t * testing . T ) {
fake := fake . NewSimpleClientset ( testCase . service )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := ServiceDescriber { c }
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
2017-10-25 08:58:49 +00:00
}
2018-05-14 07:11:48 +00:00
for _ , expected := range testCase . expect {
if ! strings . Contains ( out , expected ) {
t . Errorf ( "expected to find %q in output: %q" , expected , out )
}
}
} )
2014-10-27 19:56:34 +00:00
}
}
2014-12-16 22:20:51 +00:00
func TestPodDescribeResultsSorted ( t * testing . T ) {
// Arrange
2016-09-08 15:50:53 +00:00
fake := fake . NewSimpleClientset (
& api . EventList {
Items : [ ] api . Event {
{
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "one" } ,
2016-09-08 15:50:53 +00:00
Source : api . EventSource { Component : "kubelet" } ,
Message : "Item 1" ,
2016-12-03 18:57:26 +00:00
FirstTimestamp : metav1 . NewTime ( time . Date ( 2014 , time . January , 15 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
LastTimestamp : metav1 . NewTime ( time . Date ( 2014 , time . January , 15 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
2016-09-08 15:50:53 +00:00
Count : 1 ,
Type : api . EventTypeNormal ,
} ,
{
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "two" } ,
2016-09-08 15:50:53 +00:00
Source : api . EventSource { Component : "scheduler" } ,
Message : "Item 2" ,
2016-12-03 18:57:26 +00:00
FirstTimestamp : metav1 . NewTime ( time . Date ( 1987 , time . June , 17 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
LastTimestamp : metav1 . NewTime ( time . Date ( 1987 , time . June , 17 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
2016-09-08 15:50:53 +00:00
Count : 1 ,
Type : api . EventTypeNormal ,
} ,
{
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta { Name : "three" } ,
2016-09-08 15:50:53 +00:00
Source : api . EventSource { Component : "kubelet" } ,
Message : "Item 3" ,
2016-12-03 18:57:26 +00:00
FirstTimestamp : metav1 . NewTime ( time . Date ( 2002 , time . December , 25 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
LastTimestamp : metav1 . NewTime ( time . Date ( 2002 , time . December , 25 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
2016-09-08 15:50:53 +00:00
Count : 1 ,
Type : api . EventTypeNormal ,
} ,
2014-12-16 22:20:51 +00:00
} ,
} ,
2017-01-17 03:38:19 +00:00
& api . Pod { ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } } ,
2016-09-08 15:50:53 +00:00
)
2015-04-06 23:27:53 +00:00
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
2014-12-16 22:20:51 +00:00
d := PodDescriber { c }
// Act
2017-02-19 22:37:24 +00:00
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
2014-12-16 22:20:51 +00:00
// Assert
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
VerifyDatesInOrder ( out , "\n" /* rowDelimiter */ , "\t" /* columnDelimiter */ , t )
}
2015-02-26 18:50:12 +00:00
2016-09-15 15:56:40 +00:00
// VerifyDatesInOrder checks the start of each line for a RFC1123Z date
// and posts error if all subsequent dates are not equal or increasing
func VerifyDatesInOrder (
resultToTest , rowDelimiter , columnDelimiter string , t * testing . T ) {
lines := strings . Split ( resultToTest , rowDelimiter )
var previousTime time . Time
for _ , str := range lines {
columns := strings . Split ( str , columnDelimiter )
if len ( columns ) > 0 {
currentTime , err := time . Parse ( time . RFC1123Z , columns [ 0 ] )
if err == nil {
if previousTime . After ( currentTime ) {
t . Errorf (
"Output is not sorted by time. %s should be listed after %s. Complete output: %s" ,
previousTime . Format ( time . RFC1123Z ) ,
currentTime . Format ( time . RFC1123Z ) ,
resultToTest )
}
previousTime = currentTime
}
}
}
}
2015-04-02 15:42:19 +00:00
func TestDescribeContainers ( t * testing . T ) {
2017-01-17 00:30:22 +00:00
trueVal := true
2015-04-02 15:42:19 +00:00
testCases := [ ] struct {
2018-05-14 07:11:48 +00:00
name string
2015-06-05 04:49:01 +00:00
container api . Container
status api . ContainerStatus
2015-04-02 15:42:19 +00:00
expectedElements [ ] string
} {
// Running state.
{
2018-05-14 07:11:48 +00:00
name : "test1" ,
2015-06-05 04:49:01 +00:00
container : api . Container { Name : "test" , Image : "image" } ,
status : api . ContainerStatus {
2015-04-02 15:42:19 +00:00
Name : "test" ,
State : api . ContainerState {
Running : & api . ContainerStateRunning {
2016-12-03 18:57:26 +00:00
StartedAt : metav1 . NewTime ( time . Now ( ) ) ,
2015-04-02 15:42:19 +00:00
} ,
} ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "test" , "State" , "Running" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "Started" } ,
} ,
// Waiting state.
{
2018-05-14 07:11:48 +00:00
name : "test2" ,
2015-06-05 04:49:01 +00:00
container : api . Container { Name : "test" , Image : "image" } ,
status : api . ContainerStatus {
2015-04-02 15:42:19 +00:00
Name : "test" ,
State : api . ContainerState {
Waiting : & api . ContainerStateWaiting {
Reason : "potato" ,
} ,
} ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "Reason" , "potato" } ,
} ,
// Terminated state.
{
2018-05-14 07:11:48 +00:00
name : "test3" ,
2015-06-05 04:49:01 +00:00
container : api . Container { Name : "test" , Image : "image" } ,
status : api . ContainerStatus {
2015-04-02 15:42:19 +00:00
Name : "test" ,
State : api . ContainerState {
2015-05-27 22:02:11 +00:00
Terminated : & api . ContainerStateTerminated {
2016-12-03 18:57:26 +00:00
StartedAt : metav1 . NewTime ( time . Now ( ) ) ,
FinishedAt : metav1 . NewTime ( time . Now ( ) ) ,
2015-04-02 15:42:19 +00:00
Reason : "potato" ,
ExitCode : 2 ,
} ,
} ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "test" , "State" , "Terminated" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "Reason" , "potato" , "Started" , "Finished" , "Exit Code" , "2" } ,
} ,
2015-08-07 01:45:20 +00:00
// Last Terminated
{
2018-05-14 07:11:48 +00:00
name : "test4" ,
2015-08-07 01:45:20 +00:00
container : api . Container { Name : "test" , Image : "image" } ,
status : api . ContainerStatus {
Name : "test" ,
State : api . ContainerState {
Running : & api . ContainerStateRunning {
2016-12-03 18:57:26 +00:00
StartedAt : metav1 . NewTime ( time . Now ( ) ) ,
2015-08-07 01:45:20 +00:00
} ,
} ,
LastTerminationState : api . ContainerState {
Terminated : & api . ContainerStateTerminated {
2016-12-03 18:57:26 +00:00
StartedAt : metav1 . NewTime ( time . Now ( ) . Add ( time . Second * 3 ) ) ,
FinishedAt : metav1 . NewTime ( time . Now ( ) ) ,
2015-08-07 01:45:20 +00:00
Reason : "crashing" ,
ExitCode : 3 ,
} ,
} ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "test" , "State" , "Terminated" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "Started" , "Finished" , "Exit Code" , "2" , "crashing" , "3" } ,
} ,
2015-04-02 15:42:19 +00:00
// No state defaults to waiting.
{
2018-05-14 07:11:48 +00:00
name : "test5" ,
2015-06-05 04:49:01 +00:00
container : api . Container { Name : "test" , Image : "image" } ,
status : api . ContainerStatus {
2015-04-02 15:42:19 +00:00
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" } ,
} ,
2015-10-11 19:14:06 +00:00
// Env
2015-07-04 14:31:15 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test6" ,
2016-11-30 02:57:35 +00:00
container : api . Container { Name : "test" , Image : "image" , Env : [ ] api . EnvVar { { Name : "envname" , Value : "xyz" } } , EnvFrom : [ ] api . EnvFromSource { { ConfigMapRef : & api . ConfigMapEnvSource { LocalObjectReference : api . LocalObjectReference { Name : "a123" } } } } } ,
2015-07-04 14:31:15 +00:00
status : api . ContainerStatus {
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
2017-01-17 00:30:22 +00:00
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "envname" , "xyz" , "a123\tConfigMap\tOptional: false" } ,
2016-11-30 02:57:35 +00:00
} ,
{
2018-05-14 07:11:48 +00:00
name : "test7" ,
2016-11-30 02:57:35 +00:00
container : api . Container { Name : "test" , Image : "image" , Env : [ ] api . EnvVar { { Name : "envname" , Value : "xyz" } } , EnvFrom : [ ] api . EnvFromSource { { Prefix : "p_" , ConfigMapRef : & api . ConfigMapEnvSource { LocalObjectReference : api . LocalObjectReference { Name : "a123" } } } } } ,
status : api . ContainerStatus {
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
2017-01-17 00:30:22 +00:00
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "envname" , "xyz" , "a123\tConfigMap with prefix 'p_'\tOptional: false" } ,
2015-07-04 14:31:15 +00:00
} ,
2017-01-04 20:50:11 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test8" ,
2017-01-17 00:30:22 +00:00
container : api . Container { Name : "test" , Image : "image" , Env : [ ] api . EnvVar { { Name : "envname" , Value : "xyz" } } , EnvFrom : [ ] api . EnvFromSource { { ConfigMapRef : & api . ConfigMapEnvSource { Optional : & trueVal , LocalObjectReference : api . LocalObjectReference { Name : "a123" } } } } } ,
2017-01-04 20:50:11 +00:00
status : api . ContainerStatus {
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
2017-01-17 00:30:22 +00:00
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "envname" , "xyz" , "a123\tConfigMap\tOptional: true" } ,
} ,
{
2018-05-14 07:11:48 +00:00
name : "test9" ,
2017-01-17 00:30:22 +00:00
container : api . Container { Name : "test" , Image : "image" , Env : [ ] api . EnvVar { { Name : "envname" , Value : "xyz" } } , EnvFrom : [ ] api . EnvFromSource { { SecretRef : & api . SecretEnvSource { LocalObjectReference : api . LocalObjectReference { Name : "a123" } , Optional : & trueVal } } } } ,
status : api . ContainerStatus {
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "envname" , "xyz" , "a123\tSecret\tOptional: true" } ,
2017-01-04 20:50:11 +00:00
} ,
{
2018-05-14 07:11:48 +00:00
name : "test10" ,
2017-01-04 20:50:11 +00:00
container : api . Container { Name : "test" , Image : "image" , Env : [ ] api . EnvVar { { Name : "envname" , Value : "xyz" } } , EnvFrom : [ ] api . EnvFromSource { { Prefix : "p_" , SecretRef : & api . SecretEnvSource { LocalObjectReference : api . LocalObjectReference { Name : "a123" } } } } } ,
status : api . ContainerStatus {
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
2017-01-17 00:30:22 +00:00
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "envname" , "xyz" , "a123\tSecret with prefix 'p_'\tOptional: false" } ,
2017-01-04 20:50:11 +00:00
} ,
2015-10-11 19:14:06 +00:00
// Command
{
2018-05-14 07:11:48 +00:00
name : "test11" ,
2015-10-11 19:14:06 +00:00
container : api . Container { Name : "test" , Image : "image" , Command : [ ] string { "sleep" , "1000" } } ,
status : api . ContainerStatus {
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "sleep" , "1000" } ,
} ,
// Args
{
2018-05-14 07:11:48 +00:00
name : "test12" ,
2015-10-11 19:14:06 +00:00
container : api . Container { Name : "test" , Image : "image" , Args : [ ] string { "time" , "1000" } } ,
status : api . ContainerStatus {
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "test" , "State" , "Waiting" , "Ready" , "True" , "Restart Count" , "7" , "Image" , "image" , "time" , "1000" } ,
} ,
2015-06-05 04:49:01 +00:00
// Using limits.
{
2018-05-14 07:11:48 +00:00
name : "test13" ,
2015-06-05 04:49:01 +00:00
container : api . Container {
Name : "test" ,
Image : "image" ,
Resources : api . ResourceRequirements {
Limits : api . ResourceList {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "1000" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "4G" ) ,
api . ResourceName ( api . ResourceStorage ) : resource . MustParse ( "20G" ) ,
} ,
} ,
} ,
status : api . ContainerStatus {
Name : "test" ,
Ready : true ,
RestartCount : 7 ,
} ,
expectedElements : [ ] string { "cpu" , "1k" , "memory" , "4G" , "storage" , "20G" } ,
} ,
2016-05-21 21:47:47 +00:00
// Using requests.
{
2018-05-14 07:11:48 +00:00
name : "test14" ,
2016-05-21 21:47:47 +00:00
container : api . Container {
Name : "test" ,
Image : "image" ,
Resources : api . ResourceRequirements {
Requests : api . ResourceList {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "1000" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "4G" ) ,
api . ResourceName ( api . ResourceStorage ) : resource . MustParse ( "20G" ) ,
} ,
} ,
} ,
expectedElements : [ ] string { "cpu" , "1k" , "memory" , "4G" , "storage" , "20G" } ,
} ,
2017-11-05 02:31:29 +00:00
// volumeMounts read/write
{
2018-05-14 07:11:48 +00:00
name : "test15" ,
2017-11-05 02:31:29 +00:00
container : api . Container {
Name : "test" ,
Image : "image" ,
VolumeMounts : [ ] api . VolumeMount {
{
Name : "mounted-volume" ,
MountPath : "/opt/" ,
} ,
} ,
} ,
expectedElements : [ ] string { "mounted-volume" , "/opt/" , "(rw)" } ,
} ,
// volumeMounts readonly
{
2018-05-14 07:11:48 +00:00
name : "test16" ,
2017-11-05 02:31:29 +00:00
container : api . Container {
Name : "test" ,
Image : "image" ,
VolumeMounts : [ ] api . VolumeMount {
{
Name : "mounted-volume" ,
MountPath : "/opt/" ,
ReadOnly : true ,
} ,
} ,
} ,
expectedElements : [ ] string { "Mounts" , "mounted-volume" , "/opt/" , "(ro)" } ,
} ,
// volumeDevices
{
2018-05-14 07:11:48 +00:00
name : "test17" ,
2017-11-05 02:31:29 +00:00
container : api . Container {
Name : "test" ,
Image : "image" ,
VolumeDevices : [ ] api . VolumeDevice {
{
Name : "volume-device" ,
DevicePath : "/dev/xvda" ,
} ,
} ,
} ,
expectedElements : [ ] string { "Devices" , "volume-device" , "/dev/xvda" } ,
} ,
2015-04-02 15:42:19 +00:00
}
for i , testCase := range testCases {
2018-05-14 07:11:48 +00:00
t . Run ( testCase . name , func ( t * testing . T ) {
out := new ( bytes . Buffer )
pod := api . Pod {
Spec : api . PodSpec {
Containers : [ ] api . Container { testCase . container } ,
} ,
Status : api . PodStatus {
ContainerStatuses : [ ] api . ContainerStatus { testCase . status } ,
} ,
2015-04-02 15:42:19 +00:00
}
2018-05-14 07:11:48 +00:00
writer := NewPrefixWriter ( out )
describeContainers ( "Containers" , pod . Spec . Containers , pod . Status . ContainerStatuses , EnvValueRetriever ( & pod ) , writer , "" )
output := out . String ( )
for _ , expected := range testCase . expectedElements {
if ! strings . Contains ( output , expected ) {
t . Errorf ( "Test case %d: expected to find %q in output: %q" , i , expected , output )
}
}
} )
2015-04-02 15:42:19 +00:00
}
}
2015-02-26 18:50:12 +00:00
func TestDescribers ( t * testing . T ) {
first := & api . Event { }
second := & api . Pod { }
var third * api . Pod
testErr := fmt . Errorf ( "test" )
d := Describers { }
d . Add (
func ( e * api . Event , p * api . Pod ) ( string , error ) {
if e != first {
t . Errorf ( "first argument not equal: %#v" , e )
}
if p != second {
t . Errorf ( "second argument not equal: %#v" , p )
}
return "test" , testErr
} ,
)
if out , err := d . DescribeObject ( first , second ) ; out != "test" || err != testErr {
t . Errorf ( "unexpected result: %s %v" , out , err )
}
if out , err := d . DescribeObject ( first , second , third ) ; out != "" || err == nil {
t . Errorf ( "unexpected result: %s %v" , out , err )
} else {
2017-02-19 22:37:24 +00:00
if noDescriber , ok := err . ( printers . ErrNoDescriber ) ; ok {
2017-11-08 22:34:54 +00:00
if ! reflect . DeepEqual ( noDescriber . Types , [ ] string { "*core.Event" , "*core.Pod" , "*core.Pod" } ) {
2015-02-26 18:50:12 +00:00
t . Errorf ( "unexpected describer: %v" , err )
}
} else {
t . Errorf ( "unexpected error type: %v" , err )
}
}
d . Add (
func ( e * api . Event ) ( string , error ) {
if e != first {
t . Errorf ( "first argument not equal: %#v" , e )
}
return "simpler" , testErr
} ,
)
if out , err := d . DescribeObject ( first ) ; out != "simpler" || err != testErr {
t . Errorf ( "unexpected result: %s %v" , out , err )
}
}
func TestDefaultDescribers ( t * testing . T ) {
2017-01-17 03:38:19 +00:00
out , err := DefaultObjectDescriber . DescribeObject ( & api . Pod { ObjectMeta : metav1 . ObjectMeta { Name : "foo" } } )
2015-02-26 18:50:12 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "foo" ) {
t . Errorf ( "unexpected output: %s" , out )
}
2017-01-17 03:38:19 +00:00
out , err = DefaultObjectDescriber . DescribeObject ( & api . Service { ObjectMeta : metav1 . ObjectMeta { Name : "foo" } } )
2015-02-26 18:50:12 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "foo" ) {
t . Errorf ( "unexpected output: %s" , out )
}
2017-01-17 03:38:19 +00:00
out , err = DefaultObjectDescriber . DescribeObject ( & api . ReplicationController { ObjectMeta : metav1 . ObjectMeta { Name : "foo" } } )
2015-02-26 18:50:12 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "foo" ) {
t . Errorf ( "unexpected output: %s" , out )
}
2017-01-17 03:38:19 +00:00
out , err = DefaultObjectDescriber . DescribeObject ( & api . Node { ObjectMeta : metav1 . ObjectMeta { Name : "foo" } } )
2015-02-26 18:50:12 +00:00
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "foo" ) {
t . Errorf ( "unexpected output: %s" , out )
}
}
2015-07-30 02:19:17 +00:00
func TestGetPodsTotalRequests ( t * testing . T ) {
testCases := [ ] struct {
2018-05-14 07:11:48 +00:00
name string
2018-01-15 08:02:35 +00:00
pods * api . PodList
expectedReqs map [ api . ResourceName ] resource . Quantity
2015-07-30 02:19:17 +00:00
} {
{
2018-05-14 07:11:48 +00:00
name : "test1" ,
2015-07-30 21:33:48 +00:00
pods : & api . PodList {
Items : [ ] api . Pod {
{
Spec : api . PodSpec {
Containers : [ ] api . Container {
{
Resources : api . ResourceRequirements {
Requests : api . ResourceList {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "1" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "300Mi" ) ,
api . ResourceName ( api . ResourceStorage ) : resource . MustParse ( "1G" ) ,
} ,
2015-07-30 02:19:17 +00:00
} ,
} ,
2015-07-30 21:33:48 +00:00
{
Resources : api . ResourceRequirements {
Requests : api . ResourceList {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "90m" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "120Mi" ) ,
api . ResourceName ( api . ResourceStorage ) : resource . MustParse ( "200M" ) ,
} ,
2015-07-30 02:19:17 +00:00
} ,
} ,
} ,
} ,
} ,
2015-07-30 21:33:48 +00:00
{
Spec : api . PodSpec {
Containers : [ ] api . Container {
{
Resources : api . ResourceRequirements {
Requests : api . ResourceList {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "60m" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "43Mi" ) ,
api . ResourceName ( api . ResourceStorage ) : resource . MustParse ( "500M" ) ,
} ,
2015-07-30 02:19:17 +00:00
} ,
} ,
2015-07-30 21:33:48 +00:00
{
Resources : api . ResourceRequirements {
Requests : api . ResourceList {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "34m" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "83Mi" ) ,
api . ResourceName ( api . ResourceStorage ) : resource . MustParse ( "700M" ) ,
} ,
2015-07-30 02:19:17 +00:00
} ,
} ,
} ,
} ,
} ,
} ,
} ,
expectedReqs : map [ api . ResourceName ] resource . Quantity {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "1.184" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "546Mi" ) ,
api . ResourceName ( api . ResourceStorage ) : resource . MustParse ( "2.4G" ) ,
} ,
} ,
}
for _ , testCase := range testCases {
2018-05-14 07:11:48 +00:00
t . Run ( testCase . name , func ( t * testing . T ) {
reqs , _ := getPodsTotalRequestsAndLimits ( testCase . pods )
if ! apiequality . Semantic . DeepEqual ( reqs , testCase . expectedReqs ) {
t . Errorf ( "Expected %v, got %v" , testCase . expectedReqs , reqs )
}
} )
2015-07-30 02:19:17 +00:00
}
}
2015-08-14 15:28:16 +00:00
func TestPersistentVolumeDescriber ( t * testing . T ) {
2017-11-05 02:31:29 +00:00
block := api . PersistentVolumeBlock
file := api . PersistentVolumeFilesystem
testCases := [ ] struct {
2018-05-14 07:11:48 +00:00
name string
2017-11-05 02:31:29 +00:00
plugin string
pv * api . PersistentVolume
expectedElements [ ] string
unexpectedElements [ ] string
} {
{
2018-05-14 07:11:48 +00:00
name : "test0" ,
2017-11-05 02:31:29 +00:00
plugin : "hostpath" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
HostPath : & api . HostPathVolumeSource { Type : new ( api . HostPathType ) } ,
} ,
2015-08-14 15:28:16 +00:00
} ,
} ,
2017-11-05 02:31:29 +00:00
unexpectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test1" ,
2017-11-05 02:31:29 +00:00
plugin : "gce" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
GCEPersistentDisk : & api . GCEPersistentDiskVolumeSource { } ,
} ,
VolumeMode : & file ,
2015-08-14 15:28:16 +00:00
} ,
} ,
2017-11-05 02:31:29 +00:00
expectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test2" ,
2017-11-05 02:31:29 +00:00
plugin : "ebs" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
AWSElasticBlockStore : & api . AWSElasticBlockStoreVolumeSource { } ,
} ,
2015-08-14 15:28:16 +00:00
} ,
} ,
2017-11-05 02:31:29 +00:00
unexpectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test3" ,
2017-11-05 02:31:29 +00:00
plugin : "nfs" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
NFS : & api . NFSVolumeSource { } ,
} ,
2015-08-14 15:28:16 +00:00
} ,
} ,
2017-11-05 02:31:29 +00:00
unexpectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test4" ,
2017-11-05 02:31:29 +00:00
plugin : "iscsi" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
ISCSI : & api . ISCSIPersistentVolumeSource { } ,
} ,
VolumeMode : & block ,
2015-08-14 15:28:16 +00:00
} ,
} ,
2017-11-05 02:31:29 +00:00
expectedElements : [ ] string { "VolumeMode" , "Block" } ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test5" ,
2017-11-05 02:31:29 +00:00
plugin : "gluster" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Glusterfs : & api . GlusterfsVolumeSource { } ,
} ,
2015-08-14 15:28:16 +00:00
} ,
} ,
2017-11-05 02:31:29 +00:00
unexpectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test6" ,
2017-11-05 02:31:29 +00:00
plugin : "rbd" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
RBD : & api . RBDPersistentVolumeSource { } ,
} ,
2015-08-14 15:28:16 +00:00
} ,
2016-04-20 08:38:19 +00:00
} ,
2017-11-05 02:31:29 +00:00
unexpectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
2016-04-20 08:38:19 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test7" ,
2017-11-05 02:31:29 +00:00
plugin : "quobyte" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Quobyte : & api . QuobyteVolumeSource { } ,
} ,
2016-04-20 08:38:19 +00:00
} ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
unexpectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test8" ,
2017-11-05 02:31:29 +00:00
plugin : "cinder" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Cinder : & api . CinderVolumeSource { } ,
} ,
2016-08-30 15:22:50 +00:00
} ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
unexpectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
2015-08-14 15:28:16 +00:00
} ,
2017-11-05 02:31:29 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test9" ,
2017-11-05 02:31:29 +00:00
plugin : "fc" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
FC : & api . FCVolumeSource { } ,
} ,
VolumeMode : & block ,
2017-07-12 10:34:43 +00:00
} ,
} ,
2017-11-05 02:31:29 +00:00
expectedElements : [ ] string { "VolumeMode" , "Block" } ,
2017-07-12 10:34:43 +00:00
} ,
2018-02-21 18:10:42 +00:00
{
2018-05-14 07:11:48 +00:00
name : "test10" ,
2018-02-21 18:10:42 +00:00
plugin : "local" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Local : & api . LocalVolumeSource { } ,
} ,
} ,
} ,
expectedElements : [ ] string { "Node Affinity: <none>" } ,
unexpectedElements : [ ] string { "Required Terms" , "Term " } ,
} ,
{
2018-05-14 07:11:48 +00:00
name : "test11" ,
2018-02-21 18:10:42 +00:00
plugin : "local" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Local : & api . LocalVolumeSource { } ,
} ,
NodeAffinity : & api . VolumeNodeAffinity { } ,
} ,
} ,
expectedElements : [ ] string { "Node Affinity: <none>" } ,
unexpectedElements : [ ] string { "Required Terms" , "Term " } ,
} ,
{
2018-05-14 07:11:48 +00:00
name : "test12" ,
2018-02-21 18:10:42 +00:00
plugin : "local" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Local : & api . LocalVolumeSource { } ,
} ,
NodeAffinity : & api . VolumeNodeAffinity {
Required : & api . NodeSelector { } ,
} ,
} ,
} ,
expectedElements : [ ] string { "Node Affinity" , "Required Terms: <none>" } ,
unexpectedElements : [ ] string { "Term " } ,
} ,
{
2018-05-14 07:11:48 +00:00
name : "test13" ,
2018-02-21 18:10:42 +00:00
plugin : "local" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Local : & api . LocalVolumeSource { } ,
} ,
NodeAffinity : & api . VolumeNodeAffinity {
Required : & api . NodeSelector {
NodeSelectorTerms : [ ] api . NodeSelectorTerm {
{
MatchExpressions : [ ] api . NodeSelectorRequirement { } ,
} ,
{
MatchExpressions : [ ] api . NodeSelectorRequirement { } ,
} ,
} ,
} ,
} ,
} ,
} ,
expectedElements : [ ] string { "Node Affinity" , "Required Terms" , "Term 0" , "Term 1" } ,
} ,
{
2018-05-14 07:11:48 +00:00
name : "test14" ,
2018-02-21 18:10:42 +00:00
plugin : "local" ,
pv : & api . PersistentVolume {
ObjectMeta : metav1 . ObjectMeta { Name : "bar" } ,
Spec : api . PersistentVolumeSpec {
PersistentVolumeSource : api . PersistentVolumeSource {
Local : & api . LocalVolumeSource { } ,
} ,
NodeAffinity : & api . VolumeNodeAffinity {
Required : & api . NodeSelector {
NodeSelectorTerms : [ ] api . NodeSelectorTerm {
{
MatchExpressions : [ ] api . NodeSelectorRequirement {
{
Key : "foo" ,
Operator : "In" ,
Values : [ ] string { "val1" , "val2" } ,
} ,
{
Key : "foo" ,
Operator : "Exists" ,
} ,
} ,
} ,
} ,
} ,
} ,
} ,
} ,
expectedElements : [ ] string { "Node Affinity" , "Required Terms" , "Term 0" ,
"foo in [val1, val2]" ,
"foo exists" } ,
} ,
2015-08-14 15:28:16 +00:00
}
2017-11-05 02:31:29 +00:00
for _ , test := range testCases {
2018-05-14 07:11:48 +00:00
t . Run ( test . name , func ( t * testing . T ) {
fake := fake . NewSimpleClientset ( test . pv )
c := PersistentVolumeDescriber { fake }
str , err := c . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "Unexpected error for test %s: %v" , test . plugin , err )
2017-11-05 02:31:29 +00:00
}
2018-05-14 07:11:48 +00:00
if str == "" {
t . Errorf ( "Unexpected empty string for test %s. Expected PV Describer output" , test . plugin )
2017-11-05 02:31:29 +00:00
}
2018-05-14 07:11:48 +00:00
for _ , expected := range test . expectedElements {
if ! strings . Contains ( str , expected ) {
t . Errorf ( "expected to find %q in output: %q" , expected , str )
}
}
for _ , unexpected := range test . unexpectedElements {
if strings . Contains ( str , unexpected ) {
t . Errorf ( "unexpected to find %q in output: %q" , unexpected , str )
}
}
} )
2017-11-05 02:31:29 +00:00
}
}
func TestPersistentVolumeClaimDescriber ( t * testing . T ) {
block := api . PersistentVolumeBlock
file := api . PersistentVolumeFilesystem
goldClassName := "gold"
2018-03-17 07:26:30 +00:00
now := time . Now ( )
2017-11-05 02:31:29 +00:00
testCases := [ ] struct {
name string
pvc * api . PersistentVolumeClaim
expectedElements [ ] string
unexpectedElements [ ] string
} {
{
name : "default" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume1" ,
StorageClassName : & goldClassName ,
} ,
Status : api . PersistentVolumeClaimStatus {
Phase : api . ClaimBound ,
} ,
} ,
unexpectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
} ,
{
name : "filesystem" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume2" ,
StorageClassName : & goldClassName ,
VolumeMode : & file ,
} ,
Status : api . PersistentVolumeClaimStatus {
Phase : api . ClaimBound ,
} ,
} ,
expectedElements : [ ] string { "VolumeMode" , "Filesystem" } ,
} ,
{
name : "block" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume3" ,
StorageClassName : & goldClassName ,
VolumeMode : & block ,
} ,
Status : api . PersistentVolumeClaimStatus {
Phase : api . ClaimBound ,
} ,
} ,
expectedElements : [ ] string { "VolumeMode" , "Block" } ,
} ,
2018-03-17 07:26:30 +00:00
// Tests for Status.Condition.
{
name : "condition-type" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume4" ,
StorageClassName : & goldClassName ,
} ,
Status : api . PersistentVolumeClaimStatus {
Conditions : [ ] api . PersistentVolumeClaimCondition {
{ Type : api . PersistentVolumeClaimResizing } ,
} ,
} ,
} ,
expectedElements : [ ] string { "Conditions" , "Type" , "Resizing" } ,
} ,
{
name : "condition-status" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume5" ,
StorageClassName : & goldClassName ,
} ,
Status : api . PersistentVolumeClaimStatus {
Conditions : [ ] api . PersistentVolumeClaimCondition {
{ Status : api . ConditionTrue } ,
} ,
} ,
} ,
expectedElements : [ ] string { "Conditions" , "Status" , "True" } ,
} ,
{
name : "condition-last-probe-time" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume6" ,
StorageClassName : & goldClassName ,
} ,
Status : api . PersistentVolumeClaimStatus {
Conditions : [ ] api . PersistentVolumeClaimCondition {
{ LastProbeTime : metav1 . Time { Time : now } } ,
} ,
} ,
} ,
expectedElements : [ ] string { "Conditions" , "LastProbeTime" , now . Format ( time . RFC1123Z ) } ,
} ,
{
name : "condition-last-transition-time" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume7" ,
StorageClassName : & goldClassName ,
} ,
Status : api . PersistentVolumeClaimStatus {
Conditions : [ ] api . PersistentVolumeClaimCondition {
{ LastTransitionTime : metav1 . Time { Time : now } } ,
} ,
} ,
} ,
expectedElements : [ ] string { "Conditions" , "LastTransitionTime" , now . Format ( time . RFC1123Z ) } ,
} ,
{
name : "condition-reason" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume8" ,
StorageClassName : & goldClassName ,
} ,
Status : api . PersistentVolumeClaimStatus {
Conditions : [ ] api . PersistentVolumeClaimCondition {
{ Reason : "OfflineResize" } ,
} ,
} ,
} ,
expectedElements : [ ] string { "Conditions" , "Reason" , "OfflineResize" } ,
} ,
{
name : "condition-message" ,
pvc : & api . PersistentVolumeClaim {
ObjectMeta : metav1 . ObjectMeta { Namespace : "foo" , Name : "bar" } ,
Spec : api . PersistentVolumeClaimSpec {
VolumeName : "volume9" ,
StorageClassName : & goldClassName ,
} ,
Status : api . PersistentVolumeClaimStatus {
Conditions : [ ] api . PersistentVolumeClaimCondition {
{ Message : "User request resize" } ,
} ,
} ,
} ,
expectedElements : [ ] string { "Conditions" , "Message" , "User request resize" } ,
} ,
2017-11-05 02:31:29 +00:00
}
for _ , test := range testCases {
2018-05-14 07:11:48 +00:00
t . Run ( test . name , func ( t * testing . T ) {
fake := fake . NewSimpleClientset ( test . pvc )
c := PersistentVolumeClaimDescriber { fake }
str , err := c . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "Unexpected error for test %s: %v" , test . name , err )
2017-11-05 02:31:29 +00:00
}
2018-05-14 07:11:48 +00:00
if str == "" {
t . Errorf ( "Unexpected empty string for test %s. Expected PVC Describer output" , test . name )
2017-11-05 02:31:29 +00:00
}
2018-05-14 07:11:48 +00:00
for _ , expected := range test . expectedElements {
if ! strings . Contains ( str , expected ) {
t . Errorf ( "expected to find %q in output: %q" , expected , str )
}
}
for _ , unexpected := range test . unexpectedElements {
if strings . Contains ( str , unexpected ) {
t . Errorf ( "unexpected to find %q in output: %q" , unexpected , str )
}
}
} )
2015-09-18 20:35:56 +00:00
}
}
2015-08-14 15:28:16 +00:00
2015-09-18 20:35:56 +00:00
func TestDescribeDeployment ( t * testing . T ) {
2016-11-18 20:58:22 +00:00
fake := fake . NewSimpleClientset ( )
2018-03-20 16:45:19 +00:00
versionedFake := versionedfake . NewSimpleClientset ( & appsv1 . Deployment {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2015-09-18 20:35:56 +00:00
Name : "bar" ,
Namespace : "foo" ,
} ,
2018-03-20 16:45:19 +00:00
Spec : appsv1 . DeploymentSpec {
2017-06-29 08:39:26 +00:00
Replicas : utilpointer . Int32Ptr ( 1 ) ,
2016-12-03 18:57:26 +00:00
Selector : & metav1 . LabelSelector { } ,
2017-02-28 22:52:28 +00:00
Template : v1 . PodTemplateSpec {
Spec : v1 . PodSpec {
Containers : [ ] v1 . Container {
{ Image : "mytest-image:latest" } ,
} ,
} ,
} ,
2015-09-18 20:35:56 +00:00
} ,
} )
2018-04-17 18:47:55 +00:00
d := DeploymentDescriber { fake , versionedFake }
2017-02-19 22:37:24 +00:00
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
2015-09-18 20:35:56 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2017-02-28 22:52:28 +00:00
if ! strings . Contains ( out , "bar" ) || ! strings . Contains ( out , "foo" ) || ! strings . Contains ( out , "Containers:" ) || ! strings . Contains ( out , "mytest-image:latest" ) {
2015-09-18 20:35:56 +00:00
t . Errorf ( "unexpected out: %s" , out )
2015-08-14 15:28:16 +00:00
}
}
2016-04-20 17:27:32 +00:00
2016-09-08 11:03:12 +00:00
func TestDescribeStorageClass ( t * testing . T ) {
2017-08-30 07:48:10 +00:00
reclaimPolicy := api . PersistentVolumeReclaimRetain
2017-10-04 17:34:34 +00:00
bindingMode := storage . VolumeBindingMode ( "bindingmode" )
2016-09-08 15:50:53 +00:00
f := fake . NewSimpleClientset ( & storage . StorageClass {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-09-08 11:03:12 +00:00
Name : "foo" ,
ResourceVersion : "4" ,
Annotations : map [ string ] string {
"name" : "foo" ,
} ,
} ,
Provisioner : "my-provisioner" ,
Parameters : map [ string ] string {
"param1" : "value1" ,
"param2" : "value2" ,
} ,
2017-10-04 17:34:34 +00:00
ReclaimPolicy : & reclaimPolicy ,
VolumeBindingMode : & bindingMode ,
2016-09-08 11:03:12 +00:00
} )
s := StorageClassDescriber { f }
2017-02-19 22:37:24 +00:00
out , err := s . Describe ( "" , "foo" , printers . DescriberSettings { ShowEvents : true } )
2016-09-08 11:03:12 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2017-10-04 17:34:34 +00:00
if ! strings . Contains ( out , "foo" ) ||
! strings . Contains ( out , "my-provisioner" ) ||
! strings . Contains ( out , "param1" ) ||
! strings . Contains ( out , "param2" ) ||
! strings . Contains ( out , "value1" ) ||
! strings . Contains ( out , "value2" ) ||
! strings . Contains ( out , "Retain" ) ||
! strings . Contains ( out , "bindingmode" ) {
2016-09-08 11:03:12 +00:00
t . Errorf ( "unexpected out: %s" , out )
}
}
2016-11-09 12:39:16 +00:00
func TestDescribePodDisruptionBudget ( t * testing . T ) {
2017-05-15 23:50:23 +00:00
minAvailable := intstr . FromInt ( 22 )
2016-11-09 12:39:16 +00:00
f := fake . NewSimpleClientset ( & policy . PodDisruptionBudget {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-11-09 12:39:16 +00:00
Namespace : "ns1" ,
Name : "pdb1" ,
2016-12-03 18:57:26 +00:00
CreationTimestamp : metav1 . Time { Time : time . Now ( ) . Add ( 1.9e9 ) } ,
2016-11-09 12:39:16 +00:00
} ,
Spec : policy . PodDisruptionBudgetSpec {
2017-05-15 23:50:23 +00:00
MinAvailable : & minAvailable ,
2016-11-09 12:39:16 +00:00
} ,
Status : policy . PodDisruptionBudgetStatus {
PodDisruptionsAllowed : 5 ,
} ,
} )
s := PodDisruptionBudgetDescriber { f }
2017-02-19 22:37:24 +00:00
out , err := s . Describe ( "ns1" , "pdb1" , printers . DescriberSettings { ShowEvents : true } )
2016-11-09 12:39:16 +00:00
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
2017-07-25 07:50:54 +00:00
if ! strings . Contains ( out , "pdb1" ) ||
! strings . Contains ( out , "ns1" ) ||
! strings . Contains ( out , "22" ) ||
! strings . Contains ( out , "5" ) {
2016-11-09 12:39:16 +00:00
t . Errorf ( "unexpected out: %s" , out )
}
}
2016-11-30 20:58:58 +00:00
func TestDescribeHorizontalPodAutoscaler ( t * testing . T ) {
minReplicasVal := int32 ( 2 )
targetUtilizationVal := int32 ( 80 )
currentUtilizationVal := int32 ( 50 )
tests := [ ] struct {
name string
hpa autoscaling . HorizontalPodAutoscaler
} {
{
"minReplicas unset" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MaxReplicas : 10 ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
} ,
} ,
} ,
2018-02-23 15:42:59 +00:00
{
"external source type, target average value (no current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ExternalMetricSourceType ,
External : & autoscaling . ExternalMetricSource {
MetricSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"label" : "value" ,
} ,
} ,
MetricName : "some-external-metric" ,
TargetAverageValue : resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
} ,
} ,
} ,
{
"external source type, target average value (with current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ExternalMetricSourceType ,
External : & autoscaling . ExternalMetricSource {
MetricSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"label" : "value" ,
} ,
} ,
MetricName : "some-external-metric" ,
TargetAverageValue : resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
CurrentMetrics : [ ] autoscaling . MetricStatus {
{
Type : autoscaling . ExternalMetricSourceType ,
External : & autoscaling . ExternalMetricStatus {
MetricSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"label" : "value" ,
} ,
} ,
MetricName : "some-external-metric" ,
CurrentAverageValue : resource . NewMilliQuantity ( 50 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
} ,
} ,
{
"external source type, target value (no current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ExternalMetricSourceType ,
External : & autoscaling . ExternalMetricSource {
MetricSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"label" : "value" ,
} ,
} ,
MetricName : "some-external-metric" ,
TargetValue : resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
} ,
} ,
} ,
{
"external source type, target value (with current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ExternalMetricSourceType ,
External : & autoscaling . ExternalMetricSource {
MetricSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"label" : "value" ,
} ,
} ,
MetricName : "some-external-metric" ,
TargetValue : resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
CurrentMetrics : [ ] autoscaling . MetricStatus {
{
Type : autoscaling . ExternalMetricSourceType ,
External : & autoscaling . ExternalMetricStatus {
MetricSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"label" : "value" ,
} ,
} ,
MetricName : "some-external-metric" ,
CurrentValue : * resource . NewMilliQuantity ( 50 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
} ,
} ,
2016-11-30 20:58:58 +00:00
{
"pods source type (no current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . PodsMetricSourceType ,
Pods : & autoscaling . PodsMetricSource {
MetricName : "some-pods-metric" ,
TargetAverageValue : * resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
} ,
} ,
} ,
{
"pods source type (with current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . PodsMetricSourceType ,
Pods : & autoscaling . PodsMetricSource {
MetricName : "some-pods-metric" ,
TargetAverageValue : * resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
CurrentMetrics : [ ] autoscaling . MetricStatus {
{
Type : autoscaling . PodsMetricSourceType ,
Pods : & autoscaling . PodsMetricStatus {
MetricName : "some-pods-metric" ,
CurrentAverageValue : * resource . NewMilliQuantity ( 50 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
} ,
} ,
{
"object source type (no current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ObjectMetricSourceType ,
Object : & autoscaling . ObjectMetricSource {
Target : autoscaling . CrossVersionObjectReference {
Name : "some-service" ,
Kind : "Service" ,
} ,
MetricName : "some-service-metric" ,
TargetValue : * resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
} ,
} ,
} ,
{
"object source type (with current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ObjectMetricSourceType ,
Object : & autoscaling . ObjectMetricSource {
Target : autoscaling . CrossVersionObjectReference {
Name : "some-service" ,
Kind : "Service" ,
} ,
MetricName : "some-service-metric" ,
TargetValue : * resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
CurrentMetrics : [ ] autoscaling . MetricStatus {
{
Type : autoscaling . ObjectMetricSourceType ,
Object : & autoscaling . ObjectMetricStatus {
Target : autoscaling . CrossVersionObjectReference {
Name : "some-service" ,
Kind : "Service" ,
} ,
MetricName : "some-service-metric" ,
CurrentValue : * resource . NewMilliQuantity ( 50 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
} ,
} ,
{
"resource source type, target average value (no current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ResourceMetricSourceType ,
Resource : & autoscaling . ResourceMetricSource {
Name : api . ResourceCPU ,
TargetAverageValue : resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
} ,
} ,
} ,
{
"resource source type, target average value (with current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ResourceMetricSourceType ,
Resource : & autoscaling . ResourceMetricSource {
Name : api . ResourceCPU ,
TargetAverageValue : resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
CurrentMetrics : [ ] autoscaling . MetricStatus {
{
Type : autoscaling . ResourceMetricSourceType ,
Resource : & autoscaling . ResourceMetricStatus {
Name : api . ResourceCPU ,
CurrentAverageValue : * resource . NewMilliQuantity ( 50 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
} ,
} ,
{
"resource source type, target utilization (no current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ResourceMetricSourceType ,
Resource : & autoscaling . ResourceMetricSource {
Name : api . ResourceCPU ,
TargetAverageUtilization : & targetUtilizationVal ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
} ,
} ,
} ,
{
"resource source type, target utilization (with current)" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . ResourceMetricSourceType ,
Resource : & autoscaling . ResourceMetricSource {
Name : api . ResourceCPU ,
TargetAverageUtilization : & targetUtilizationVal ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
CurrentMetrics : [ ] autoscaling . MetricStatus {
{
Type : autoscaling . ResourceMetricSourceType ,
Resource : & autoscaling . ResourceMetricStatus {
Name : api . ResourceCPU ,
CurrentAverageUtilization : & currentUtilizationVal ,
CurrentAverageValue : * resource . NewMilliQuantity ( 40 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
} ,
} ,
{
"multiple metrics" ,
autoscaling . HorizontalPodAutoscaler {
Spec : autoscaling . HorizontalPodAutoscalerSpec {
ScaleTargetRef : autoscaling . CrossVersionObjectReference {
Name : "some-rc" ,
Kind : "ReplicationController" ,
} ,
MinReplicas : & minReplicasVal ,
MaxReplicas : 10 ,
Metrics : [ ] autoscaling . MetricSpec {
{
Type : autoscaling . PodsMetricSourceType ,
Pods : & autoscaling . PodsMetricSource {
MetricName : "some-pods-metric" ,
TargetAverageValue : * resource . NewMilliQuantity ( 100 , resource . DecimalSI ) ,
} ,
} ,
{
Type : autoscaling . ResourceMetricSourceType ,
Resource : & autoscaling . ResourceMetricSource {
Name : api . ResourceCPU ,
TargetAverageUtilization : & targetUtilizationVal ,
} ,
} ,
{
Type : autoscaling . PodsMetricSourceType ,
Pods : & autoscaling . PodsMetricSource {
MetricName : "other-pods-metric" ,
TargetAverageValue : * resource . NewMilliQuantity ( 400 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
Status : autoscaling . HorizontalPodAutoscalerStatus {
CurrentReplicas : 4 ,
DesiredReplicas : 5 ,
CurrentMetrics : [ ] autoscaling . MetricStatus {
{
Type : autoscaling . PodsMetricSourceType ,
Pods : & autoscaling . PodsMetricStatus {
MetricName : "some-pods-metric" ,
CurrentAverageValue : * resource . NewMilliQuantity ( 50 , resource . DecimalSI ) ,
} ,
} ,
{
Type : autoscaling . ResourceMetricSourceType ,
Resource : & autoscaling . ResourceMetricStatus {
Name : api . ResourceCPU ,
CurrentAverageUtilization : & currentUtilizationVal ,
CurrentAverageValue : * resource . NewMilliQuantity ( 40 , resource . DecimalSI ) ,
} ,
} ,
} ,
} ,
} ,
} ,
}
for _ , test := range tests {
2018-05-14 07:11:48 +00:00
t . Run ( test . name , func ( t * testing . T ) {
test . hpa . ObjectMeta = metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
}
fake := fake . NewSimpleClientset ( & test . hpa )
desc := HorizontalPodAutoscalerDescriber { fake }
str , err := desc . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "Unexpected error for test %s: %v" , test . name , err )
}
if str == "" {
t . Errorf ( "Unexpected empty string for test %s. Expected HPA Describer output" , test . name )
}
t . Logf ( "Description for %q:\n%s" , test . name , str )
} )
2016-11-30 20:58:58 +00:00
}
}
2016-04-20 17:27:32 +00:00
func TestDescribeEvents ( t * testing . T ) {
events := & api . EventList {
Items : [ ] api . Event {
{
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-06-02 01:47:36 +00:00
Namespace : "foo" ,
} ,
2016-04-20 17:27:32 +00:00
Source : api . EventSource { Component : "kubelet" } ,
Message : "Item 1" ,
2016-12-03 18:57:26 +00:00
FirstTimestamp : metav1 . NewTime ( time . Date ( 2014 , time . January , 15 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
LastTimestamp : metav1 . NewTime ( time . Date ( 2014 , time . January , 15 , 0 , 0 , 0 , 0 , time . UTC ) ) ,
2016-04-20 17:27:32 +00:00
Count : 1 ,
Type : api . EventTypeNormal ,
} ,
} ,
}
2017-02-19 22:37:24 +00:00
m := map [ string ] printers . Describer {
2016-04-20 17:27:32 +00:00
"DaemonSetDescriber" : & DaemonSetDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & extensions . DaemonSet {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-04-20 17:27:32 +00:00
Name : "bar" ,
Namespace : "foo" ,
} ,
} , events ) ,
} ,
"DeploymentDescriber" : & DeploymentDescriber {
2016-11-18 20:58:22 +00:00
fake . NewSimpleClientset ( events ) ,
2018-03-20 16:45:19 +00:00
versionedfake . NewSimpleClientset ( & appsv1 . Deployment {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-04-20 17:27:32 +00:00
Name : "bar" ,
Namespace : "foo" ,
} ,
2018-03-20 16:45:19 +00:00
Spec : appsv1 . DeploymentSpec {
2017-06-29 08:39:26 +00:00
Replicas : utilpointer . Int32Ptr ( 1 ) ,
2016-12-03 18:57:26 +00:00
Selector : & metav1 . LabelSelector { } ,
2016-11-18 20:58:22 +00:00
} ,
2018-04-17 18:47:55 +00:00
} ) ,
2016-04-20 17:27:32 +00:00
} ,
"EndpointsDescriber" : & EndpointsDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & api . Endpoints {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-04-20 17:27:32 +00:00
Name : "bar" ,
Namespace : "foo" ,
} ,
} , events ) ,
} ,
// TODO(jchaloup): add tests for:
// - IngressDescriber
// - JobDescriber
"NodeDescriber" : & NodeDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & api . Node {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-09-08 15:50:53 +00:00
Name : "bar" ,
SelfLink : "url/url/url" ,
2016-04-20 17:27:32 +00:00
} ,
} , events ) ,
} ,
2016-06-15 12:17:02 +00:00
"PersistentVolumeDescriber" : & PersistentVolumeDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & api . PersistentVolume {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-09-08 15:50:53 +00:00
Name : "bar" ,
SelfLink : "url/url/url" ,
2016-06-15 12:17:02 +00:00
} ,
} , events ) ,
} ,
2016-04-20 17:27:32 +00:00
"PodDescriber" : & PodDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & api . Pod {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-04-20 17:27:32 +00:00
Name : "bar" ,
Namespace : "foo" ,
SelfLink : "url/url/url" ,
} ,
} , events ) ,
} ,
"ReplicaSetDescriber" : & ReplicaSetDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & extensions . ReplicaSet {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-04-20 17:27:32 +00:00
Name : "bar" ,
Namespace : "foo" ,
} ,
} , events ) ,
} ,
"ReplicationControllerDescriber" : & ReplicationControllerDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & api . ReplicationController {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-04-20 17:27:32 +00:00
Name : "bar" ,
Namespace : "foo" ,
} ,
} , events ) ,
} ,
"Service" : & ServiceDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & api . Service {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-04-20 17:27:32 +00:00
Name : "bar" ,
Namespace : "foo" ,
} ,
} , events ) ,
} ,
2016-09-08 11:03:12 +00:00
"StorageClass" : & StorageClassDescriber {
2016-09-08 15:50:53 +00:00
fake . NewSimpleClientset ( & storage . StorageClass {
2017-01-17 03:38:19 +00:00
ObjectMeta : metav1 . ObjectMeta {
2016-09-08 15:50:53 +00:00
Name : "bar" ,
2016-09-08 11:03:12 +00:00
} ,
} , events ) ,
} ,
2016-11-30 20:58:58 +00:00
"HorizontalPodAutoscaler" : & HorizontalPodAutoscalerDescriber {
fake . NewSimpleClientset ( & autoscaling . HorizontalPodAutoscaler {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
2017-03-06 14:07:48 +00:00
} , events ) ,
} ,
"ConfigMap" : & ConfigMapDescriber {
fake . NewSimpleClientset ( & api . ConfigMap {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
2016-11-30 20:58:58 +00:00
} , events ) ,
} ,
2016-04-20 17:27:32 +00:00
}
for name , d := range m {
2018-05-14 07:11:48 +00:00
t . Run ( name , func ( t * testing . T ) {
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error for %q: %v" , name , err )
}
if ! strings . Contains ( out , "bar" ) {
t . Errorf ( "unexpected out for %q: %s" , name , out )
}
if ! strings . Contains ( out , "Events:" ) {
t . Errorf ( "events not found for %q when ShowEvents=true: %s" , name , out )
}
2016-04-20 17:27:32 +00:00
2018-05-14 07:11:48 +00:00
out , err = d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : false } )
if err != nil {
t . Errorf ( "unexpected error for %q: %s" , name , err )
}
if ! strings . Contains ( out , "bar" ) {
t . Errorf ( "unexpected out for %q: %s" , name , out )
}
if strings . Contains ( out , "Events:" ) {
t . Errorf ( "events found for %q when ShowEvents=false: %s" , name , out )
}
} )
2016-04-20 17:27:32 +00:00
}
}
2016-10-20 02:34:57 +00:00
func TestPrintLabelsMultiline ( t * testing . T ) {
var maxLenAnnotationStr string = "MaxLenAnnotation=Multicast addressing can be used in the link layer (Layer 2 in the OSI model), such as Ethernet multicast, and at the internet layer (Layer 3 for OSI) for Internet Protocol Version 4 "
testCases := [ ] struct {
annotations map [ string ] string
expectPrint string
} {
{
annotations : map [ string ] string { "col1" : "asd" , "COL2" : "zxc" } ,
expectPrint : "Annotations:\tCOL2=zxc\n\tcol1=asd\n" ,
} ,
{
annotations : map [ string ] string { "MaxLenAnnotation" : maxLenAnnotationStr [ 17 : ] } ,
expectPrint : "Annotations:\t" + maxLenAnnotationStr + "\n" ,
} ,
{
annotations : map [ string ] string { "MaxLenAnnotation" : maxLenAnnotationStr [ 17 : ] + "1" } ,
expectPrint : "Annotations:\t" + maxLenAnnotationStr + "...\n" ,
} ,
{
annotations : map [ string ] string { } ,
expectPrint : "Annotations:\t<none>\n" ,
} ,
}
for i , testCase := range testCases {
2018-05-14 07:11:48 +00:00
t . Run ( testCase . expectPrint , func ( t * testing . T ) {
out := new ( bytes . Buffer )
writer := NewPrefixWriter ( out )
printAnnotationsMultiline ( writer , "Annotations" , testCase . annotations )
output := out . String ( )
if output != testCase . expectPrint {
t . Errorf ( "Test case %d: expected to find %q in output: %q" , i , testCase . expectPrint , output )
}
} )
2016-10-20 02:34:57 +00:00
}
}
2017-04-07 00:14:16 +00:00
func TestDescribeUnstructuredContent ( t * testing . T ) {
testCases := [ ] struct {
expected string
unexpected string
} {
{
expected : ` API Version : v1
Dummy 2 : present
Items :
Item Bool : true
Item Int : 42
Kind : Test
Metadata :
Creation Timestamp : 2017 - 04 - 01 T00 : 00 : 00 Z
Name : MyName
Namespace : MyNamespace
Resource Version : 123
UID : 00000000 - 0000 - 0000 - 0000 - 000000000001
Status : ok
URL : http : //localhost
` ,
} ,
{
unexpected : "\nDummy 1:\tpresent\n" ,
} ,
{
unexpected : "Dummy 1" ,
} ,
{
unexpected : "Dummy 3" ,
} ,
{
unexpected : "Dummy3" ,
} ,
{
unexpected : "dummy3" ,
} ,
{
unexpected : "dummy 3" ,
} ,
}
out := new ( bytes . Buffer )
w := NewPrefixWriter ( out )
obj := & unstructured . Unstructured {
Object : map [ string ] interface { } {
"apiVersion" : "v1" ,
"kind" : "Test" ,
"dummy1" : "present" ,
"dummy2" : "present" ,
"metadata" : map [ string ] interface { } {
"name" : "MyName" ,
"namespace" : "MyNamespace" ,
"creationTimestamp" : "2017-04-01T00:00:00Z" ,
"resourceVersion" : 123 ,
"uid" : "00000000-0000-0000-0000-000000000001" ,
"dummy3" : "present" ,
} ,
"items" : [ ] interface { } {
map [ string ] interface { } {
"itemBool" : true ,
"itemInt" : 42 ,
} ,
} ,
"url" : "http://localhost" ,
"status" : "ok" ,
} ,
}
printUnstructuredContent ( w , LEVEL_0 , obj . UnstructuredContent ( ) , "" , ".dummy1" , ".metadata.dummy3" )
output := out . String ( )
for _ , test := range testCases {
if len ( test . expected ) > 0 {
if ! strings . Contains ( output , test . expected ) {
t . Errorf ( "Expected to find %q in: %q" , test . expected , output )
}
}
if len ( test . unexpected ) > 0 {
if strings . Contains ( output , test . unexpected ) {
t . Errorf ( "Didn't expect to find %q in: %q" , test . unexpected , output )
}
}
}
}
2017-05-23 03:16:39 +00:00
2017-05-15 06:27:14 +00:00
func TestDescribePodSecurityPolicy ( t * testing . T ) {
expected := [ ] string {
2017-08-31 23:08:14 +00:00
"Name:\\s*mypsp" ,
"Allow Privileged:\\s*false" ,
"Default Add Capabilities:\\s*<none>" ,
"Required Drop Capabilities:\\s*<none>" ,
"Allowed Capabilities:\\s*<none>" ,
"Allowed Volume Types:\\s*<none>" ,
"Allow Host Network:\\s*false" ,
"Allow Host Ports:\\s*<none>" ,
"Allow Host PID:\\s*false" ,
"Allow Host IPC:\\s*false" ,
"Read Only Root Filesystem:\\s*false" ,
2017-05-15 06:27:14 +00:00
"SELinux Context Strategy: RunAsAny" ,
2017-08-31 23:08:14 +00:00
"User:\\s*<none>" ,
"Role:\\s*<none>" ,
"Type:\\s*<none>" ,
"Level:\\s*<none>" ,
2017-05-15 06:27:14 +00:00
"Run As User Strategy: RunAsAny" ,
"FSGroup Strategy: RunAsAny" ,
"Supplemental Groups Strategy: RunAsAny" ,
}
2018-03-21 16:30:31 +00:00
fake := fake . NewSimpleClientset ( & policy . PodSecurityPolicy {
2017-05-15 06:27:14 +00:00
ObjectMeta : metav1 . ObjectMeta {
Name : "mypsp" ,
} ,
2018-03-21 16:30:31 +00:00
Spec : policy . PodSecurityPolicySpec {
SELinux : policy . SELinuxStrategyOptions {
Rule : policy . SELinuxStrategyRunAsAny ,
2017-05-15 06:27:14 +00:00
} ,
2018-03-21 16:30:31 +00:00
RunAsUser : policy . RunAsUserStrategyOptions {
Rule : policy . RunAsUserStrategyRunAsAny ,
2017-05-15 06:27:14 +00:00
} ,
2018-03-21 16:30:31 +00:00
FSGroup : policy . FSGroupStrategyOptions {
Rule : policy . FSGroupStrategyRunAsAny ,
2017-05-15 06:27:14 +00:00
} ,
2018-03-21 16:30:31 +00:00
SupplementalGroups : policy . SupplementalGroupsStrategyOptions {
Rule : policy . SupplementalGroupsStrategyRunAsAny ,
2017-05-15 06:27:14 +00:00
} ,
} ,
} )
c := & describeClient { T : t , Namespace : "" , Interface : fake }
d := PodSecurityPolicyDescriber { c }
out , err := d . Describe ( "" , "mypsp" , printers . DescriberSettings { } )
if err != nil {
t . Fatalf ( "unexpected error: %v" , err )
}
for _ , item := range expected {
if matched , _ := regexp . MatchString ( item , out ) ; ! matched {
t . Errorf ( "Expected to find %q in: %q" , item , out )
}
}
}
2017-05-23 03:16:39 +00:00
func TestDescribeResourceQuota ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & api . ResourceQuota {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
Status : api . ResourceQuotaStatus {
Hard : api . ResourceList {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "1" ) ,
api . ResourceName ( api . ResourceLimitsCPU ) : resource . MustParse ( "2" ) ,
api . ResourceName ( api . ResourceLimitsMemory ) : resource . MustParse ( "2G" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "1G" ) ,
api . ResourceName ( api . ResourceRequestsCPU ) : resource . MustParse ( "1" ) ,
api . ResourceName ( api . ResourceRequestsMemory ) : resource . MustParse ( "1G" ) ,
} ,
Used : api . ResourceList {
api . ResourceName ( api . ResourceCPU ) : resource . MustParse ( "0" ) ,
api . ResourceName ( api . ResourceLimitsCPU ) : resource . MustParse ( "0" ) ,
api . ResourceName ( api . ResourceLimitsMemory ) : resource . MustParse ( "0G" ) ,
api . ResourceName ( api . ResourceMemory ) : resource . MustParse ( "0G" ) ,
api . ResourceName ( api . ResourceRequestsCPU ) : resource . MustParse ( "0" ) ,
api . ResourceName ( api . ResourceRequestsMemory ) : resource . MustParse ( "0G" ) ,
} ,
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := ResourceQuotaDescriber { c }
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
expectedOut := [ ] string { "bar" , "foo" , "limits.cpu" , "2" , "limits.memory" , "2G" , "requests.cpu" , "1" , "requests.memory" , "1G" }
for _ , expected := range expectedOut {
if ! strings . Contains ( out , expected ) {
t . Errorf ( "expected to find %q in output: %q" , expected , out )
}
}
}
2017-05-08 01:42:11 +00:00
2017-06-05 04:12:21 +00:00
func TestDescribeNetworkPolicies ( t * testing . T ) {
expectedTime , err := time . Parse ( "2006-01-02 15:04:05 Z0700 MST" , "2017-06-04 21:45:56 -0700 PDT" )
if err != nil {
t . Errorf ( "unable to parse time %q error: %s" , "2017-06-04 21:45:56 -0700 PDT" , err )
}
expectedOut := ` Name : network - policy - 1
Namespace : default
Created on : 2017 - 06 - 04 21 : 45 : 56 - 0700 PDT
Labels : < none >
Annotations : < none >
Spec :
2017-11-06 07:22:50 +00:00
PodSelector : foo in ( bar1 , bar2 ) , foo2 notin ( bar1 , bar2 ) , id1 = app1 , id2 = app2
2017-06-05 04:12:21 +00:00
Allowing ingress traffic :
To Port : 80 / TCP
To Port : 82 / TCP
2018-03-26 07:08:07 +00:00
From :
NamespaceSelector : id = ns1 , id2 = ns2
PodSelector : id = pod1 , id2 = pod2
From :
PodSelector : id = app2 , id2 = app3
From :
NamespaceSelector : id = app2 , id2 = app3
From :
NamespaceSelector : foo in ( bar1 , bar2 ) , id = app2 , id2 = app3
From :
IPBlock :
2017-10-31 09:42:44 +00:00
CIDR : 192.168 .0 .0 / 16
Except : 192.168 .3 .0 / 24 , 192.168 .4 .0 / 24
2017-06-05 04:12:21 +00:00
-- -- -- -- --
To Port : < any > ( traffic allowed to all ports )
From : < any > ( traffic not restricted by source )
2017-10-31 11:39:25 +00:00
Allowing egress traffic :
2017-11-03 03:47:37 +00:00
To Port : 80 / TCP
To Port : 82 / TCP
2018-03-26 07:08:07 +00:00
To :
NamespaceSelector : id = ns1 , id2 = ns2
PodSelector : id = pod1 , id2 = pod2
To :
PodSelector : id = app2 , id2 = app3
To :
NamespaceSelector : id = app2 , id2 = app3
To :
NamespaceSelector : foo in ( bar1 , bar2 ) , id = app2 , id2 = app3
To :
IPBlock :
2017-10-31 11:39:25 +00:00
CIDR : 192.168 .0 .0 / 16
Except : 192.168 .3 .0 / 24 , 192.168 .4 .0 / 24
-- -- -- -- --
2017-11-03 03:47:37 +00:00
To Port : < any > ( traffic allowed to all ports )
2017-10-31 11:39:25 +00:00
To : < any > ( traffic not restricted by source )
2017-11-03 03:47:37 +00:00
Policy Types : Ingress , Egress
2017-06-05 04:12:21 +00:00
`
port80 := intstr . FromInt ( 80 )
port82 := intstr . FromInt ( 82 )
protoTCP := api . ProtocolTCP
versionedFake := fake . NewSimpleClientset ( & networking . NetworkPolicy {
ObjectMeta : metav1 . ObjectMeta {
Name : "network-policy-1" ,
Namespace : "default" ,
CreationTimestamp : metav1 . NewTime ( expectedTime ) ,
} ,
Spec : networking . NetworkPolicySpec {
PodSelector : metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id1" : "app1" ,
"id2" : "app2" ,
} ,
MatchExpressions : [ ] metav1 . LabelSelectorRequirement {
{ Key : "foo" , Operator : "In" , Values : [ ] string { "bar1" , "bar2" } } ,
{ Key : "foo2" , Operator : "NotIn" , Values : [ ] string { "bar1" , "bar2" } } ,
} ,
} ,
Ingress : [ ] networking . NetworkPolicyIngressRule {
{
Ports : [ ] networking . NetworkPolicyPort {
{ Port : & port80 } ,
{ Port : & port82 , Protocol : & protoTCP } ,
} ,
From : [ ] networking . NetworkPolicyPeer {
2018-03-26 07:08:07 +00:00
{
PodSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "pod1" ,
"id2" : "pod2" ,
} ,
} ,
NamespaceSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "ns1" ,
"id2" : "ns2" ,
} ,
} ,
} ,
2017-06-05 04:12:21 +00:00
{
PodSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "app2" ,
"id2" : "app3" ,
} ,
} ,
} ,
{
NamespaceSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "app2" ,
"id2" : "app3" ,
} ,
} ,
} ,
{
NamespaceSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "app2" ,
"id2" : "app3" ,
} ,
MatchExpressions : [ ] metav1 . LabelSelectorRequirement {
{ Key : "foo" , Operator : "In" , Values : [ ] string { "bar1" , "bar2" } } ,
} ,
} ,
} ,
2017-10-31 11:39:25 +00:00
{
IPBlock : & networking . IPBlock {
CIDR : "192.168.0.0/16" ,
Except : [ ] string { "192.168.3.0/24" , "192.168.4.0/24" } ,
} ,
} ,
} ,
} ,
{ } ,
} ,
Egress : [ ] networking . NetworkPolicyEgressRule {
{
Ports : [ ] networking . NetworkPolicyPort {
{ Port : & port80 } ,
{ Port : & port82 , Protocol : & protoTCP } ,
} ,
To : [ ] networking . NetworkPolicyPeer {
{
2018-03-26 07:08:07 +00:00
PodSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "pod1" ,
"id2" : "pod2" ,
} ,
} ,
NamespaceSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "ns1" ,
"id2" : "ns2" ,
} ,
} ,
} ,
{
2017-10-31 11:39:25 +00:00
PodSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "app2" ,
"id2" : "app3" ,
} ,
} ,
} ,
{
NamespaceSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "app2" ,
2017-06-05 04:12:21 +00:00
"id2" : "app3" ,
} ,
} ,
} ,
{
NamespaceSelector : & metav1 . LabelSelector {
MatchLabels : map [ string ] string {
"id" : "app2" ,
"id2" : "app3" ,
} ,
MatchExpressions : [ ] metav1 . LabelSelectorRequirement {
{ Key : "foo" , Operator : "In" , Values : [ ] string { "bar1" , "bar2" } } ,
} ,
} ,
} ,
2017-10-31 09:42:44 +00:00
{
IPBlock : & networking . IPBlock {
CIDR : "192.168.0.0/16" ,
Except : [ ] string { "192.168.3.0/24" , "192.168.4.0/24" } ,
} ,
} ,
2017-06-05 04:12:21 +00:00
} ,
} ,
{ } ,
} ,
2017-11-01 08:11:27 +00:00
PolicyTypes : [ ] networking . PolicyType { networking . PolicyTypeIngress , networking . PolicyTypeEgress } ,
2017-06-05 04:12:21 +00:00
} ,
} )
d := NetworkPolicyDescriber { versionedFake }
out , err := d . Describe ( "" , "network-policy-1" , printers . DescriberSettings { } )
if err != nil {
t . Errorf ( "unexpected error: %s" , err )
}
if out != expectedOut {
t . Errorf ( "want:\n%s\ngot:\n%s" , expectedOut , out )
}
}
2017-09-13 01:56:26 +00:00
func TestDescribeServiceAccount ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & api . ServiceAccount {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
Secrets : [ ] api . ObjectReference {
{
Name : "test-objectref" ,
} ,
} ,
ImagePullSecrets : [ ] api . LocalObjectReference {
{
Name : "test-local-ref" ,
} ,
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := ServiceAccountDescriber { c }
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
expectedOut := ` Name : bar
Namespace : foo
Labels : < none >
Annotations : < none >
Image pull secrets : test - local - ref ( not found )
Mountable secrets : test - objectref ( not found )
Tokens : < none >
Events : < none > ` + "\n"
if out != expectedOut {
t . Errorf ( "expected : %q\n but got output:\n %q" , expectedOut , out )
}
}
2018-02-06 12:14:46 +00:00
func TestDescribeNode ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & api . Node {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
Spec : api . NodeSpec {
Unschedulable : true ,
} ,
} )
c := & describeClient { T : t , Namespace : "foo" , Interface : fake }
d := NodeDescriber { c }
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
expectedOut := [ ] string { "Unschedulable" , "true" }
for _ , expected := range expectedOut {
if ! strings . Contains ( out , expected ) {
t . Errorf ( "expected to find %q in output: %q" , expected , out )
}
}
}
2018-05-15 04:42:13 +00:00
func TestDescribeStatefulSet ( t * testing . T ) {
fake := fake . NewSimpleClientset ( & apps . StatefulSet {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
} ,
Spec : apps . StatefulSetSpec {
Replicas : 1 ,
Selector : & metav1 . LabelSelector { } ,
Template : api . PodTemplateSpec {
Spec : api . PodSpec {
Containers : [ ] api . Container {
{ Image : "mytest-image:latest" } ,
} ,
} ,
} ,
UpdateStrategy : apps . StatefulSetUpdateStrategy {
Type : apps . RollingUpdateStatefulSetStrategyType ,
RollingUpdate : & apps . RollingUpdateStatefulSetStrategy {
Partition : 2 ,
} ,
} ,
} ,
} )
d := StatefulSetDescriber { fake }
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : true } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
expectedOutputs := [ ] string {
"bar" , "foo" , "Containers:" , "mytest-image:latest" , "Update Strategy" , "RollingUpdate" , "Partition" ,
}
for _ , o := range expectedOutputs {
if ! strings . Contains ( out , o ) {
t . Errorf ( "unexpected out: %s" , out )
break
}
}
}
2017-05-08 01:42:11 +00:00
// boolPtr returns a pointer to a bool
func boolPtr ( b bool ) * bool {
o := b
return & o
}
func TestControllerRef ( t * testing . T ) {
f := fake . NewSimpleClientset (
& api . ReplicationController {
ObjectMeta : metav1 . ObjectMeta {
Name : "bar" ,
Namespace : "foo" ,
UID : "123456" ,
} ,
TypeMeta : metav1 . TypeMeta {
Kind : "ReplicationController" ,
} ,
Spec : api . ReplicationControllerSpec {
Replicas : 1 ,
Selector : map [ string ] string { "abc" : "xyz" } ,
Template : & api . PodTemplateSpec {
Spec : api . PodSpec {
Containers : [ ] api . Container {
{ Image : "mytest-image:latest" } ,
} ,
} ,
} ,
} ,
} ,
& api . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "barpod" ,
Namespace : "foo" ,
Labels : map [ string ] string { "abc" : "xyz" } ,
OwnerReferences : [ ] metav1 . OwnerReference { { Name : "bar" , UID : "123456" , Controller : boolPtr ( true ) } } ,
} ,
TypeMeta : metav1 . TypeMeta {
Kind : "Pod" ,
} ,
Spec : api . PodSpec {
Containers : [ ] api . Container {
{ Image : "mytest-image:latest" } ,
} ,
} ,
Status : api . PodStatus {
Phase : api . PodRunning ,
} ,
} ,
& api . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "orphan" ,
Namespace : "foo" ,
Labels : map [ string ] string { "abc" : "xyz" } ,
} ,
TypeMeta : metav1 . TypeMeta {
Kind : "Pod" ,
} ,
Spec : api . PodSpec {
Containers : [ ] api . Container {
{ Image : "mytest-image:latest" } ,
} ,
} ,
Status : api . PodStatus {
Phase : api . PodRunning ,
} ,
} ,
& api . Pod {
ObjectMeta : metav1 . ObjectMeta {
Name : "buzpod" ,
Namespace : "foo" ,
Labels : map [ string ] string { "abc" : "xyz" } ,
OwnerReferences : [ ] metav1 . OwnerReference { { Name : "buz" , UID : "654321" , Controller : boolPtr ( true ) } } ,
} ,
TypeMeta : metav1 . TypeMeta {
Kind : "Pod" ,
} ,
Spec : api . PodSpec {
Containers : [ ] api . Container {
{ Image : "mytest-image:latest" } ,
} ,
} ,
Status : api . PodStatus {
Phase : api . PodRunning ,
} ,
} )
d := ReplicationControllerDescriber { f }
out , err := d . Describe ( "foo" , "bar" , printers . DescriberSettings { ShowEvents : false } )
if err != nil {
t . Errorf ( "unexpected error: %v" , err )
}
if ! strings . Contains ( out , "1 Running" ) {
t . Errorf ( "unexpected out: %s" , out )
}
}