mirror of https://github.com/k3s-io/k3s
Block Volume: cmdline printer update
parent
849d7f8595
commit
334a0f0620
|
@ -1136,6 +1136,9 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (
|
|||
}
|
||||
w.Write(LEVEL_0, "Reclaim Policy:\t%v\n", pv.Spec.PersistentVolumeReclaimPolicy)
|
||||
w.Write(LEVEL_0, "Access Modes:\t%s\n", helper.GetAccessModesAsString(pv.Spec.AccessModes))
|
||||
if pv.Spec.VolumeMode != nil {
|
||||
w.Write(LEVEL_0, "VolumeMode:\t%v\n", *pv.Spec.VolumeMode)
|
||||
}
|
||||
storage := pv.Spec.Capacity[api.ResourceStorage]
|
||||
w.Write(LEVEL_0, "Capacity:\t%s\n", storage.String())
|
||||
w.Write(LEVEL_0, "Message:\t%s\n", pv.Status.Message)
|
||||
|
@ -1235,6 +1238,9 @@ func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.E
|
|||
}
|
||||
w.Write(LEVEL_0, "Capacity:\t%s\n", capacity)
|
||||
w.Write(LEVEL_0, "Access Modes:\t%s\n", accessModes)
|
||||
if pvc.Spec.VolumeMode != nil {
|
||||
w.Write(LEVEL_0, "VolumeMode:\t%v\n", *pvc.Spec.VolumeMode)
|
||||
}
|
||||
if events != nil {
|
||||
DescribeEvents(events, w)
|
||||
}
|
||||
|
@ -1365,6 +1371,7 @@ func describeContainerProbe(container api.Container, w PrefixWriter) {
|
|||
}
|
||||
|
||||
func describeContainerVolumes(container api.Container, w PrefixWriter) {
|
||||
// Show volumeMounts
|
||||
none := ""
|
||||
if len(container.VolumeMounts) == 0 {
|
||||
none = "\t<none>"
|
||||
|
@ -1383,6 +1390,14 @@ func describeContainerVolumes(container api.Container, w PrefixWriter) {
|
|||
}
|
||||
w.Write(LEVEL_3, "%s from %s (%s)\n", mount.MountPath, mount.Name, strings.Join(flags, ","))
|
||||
}
|
||||
// Show volumeDevices if exists
|
||||
if len(container.VolumeDevices) > 0 {
|
||||
w.Write(LEVEL_2, "Devices:%s\n", none)
|
||||
sort.Sort(SortableVolumeDevices(container.VolumeDevices))
|
||||
for _, device := range container.VolumeDevices {
|
||||
w.Write(LEVEL_3, "%s from %s\n", device.DevicePath, device.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func describeContainerEnvVars(container api.Container, resolverFn EnvVarResolverFunc, w PrefixWriter) {
|
||||
|
@ -3803,6 +3818,20 @@ func (list SortableVolumeMounts) Less(i, j int) bool {
|
|||
return list[i].MountPath < list[j].MountPath
|
||||
}
|
||||
|
||||
type SortableVolumeDevices []api.VolumeDevice
|
||||
|
||||
func (list SortableVolumeDevices) Len() int {
|
||||
return len(list)
|
||||
}
|
||||
|
||||
func (list SortableVolumeDevices) Swap(i, j int) {
|
||||
list[i], list[j] = list[j], list[i]
|
||||
}
|
||||
|
||||
func (list SortableVolumeDevices) Less(i, j int) bool {
|
||||
return list[i].DevicePath < list[j].DevicePath
|
||||
}
|
||||
|
||||
// TODO: get rid of this and plumb the caller correctly
|
||||
func versionedExtensionsClientV1beta1(internalClient clientset.Interface) clientextensionsv1beta1.ExtensionsV1beta1Interface {
|
||||
if internalClient == nil {
|
||||
|
|
|
@ -634,6 +634,50 @@ func TestDescribeContainers(t *testing.T) {
|
|||
},
|
||||
expectedElements: []string{"cpu", "1k", "memory", "4G", "storage", "20G"},
|
||||
},
|
||||
// volumeMounts read/write
|
||||
{
|
||||
container: api.Container{
|
||||
Name: "test",
|
||||
Image: "image",
|
||||
VolumeMounts: []api.VolumeMount{
|
||||
{
|
||||
Name: "mounted-volume",
|
||||
MountPath: "/opt/",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedElements: []string{"mounted-volume", "/opt/", "(rw)"},
|
||||
},
|
||||
// volumeMounts readonly
|
||||
{
|
||||
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
|
||||
{
|
||||
container: api.Container{
|
||||
Name: "test",
|
||||
Image: "image",
|
||||
VolumeDevices: []api.VolumeDevice{
|
||||
{
|
||||
Name: "volume-device",
|
||||
DevicePath: "/dev/xvda",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedElements: []string{"Devices", "volume-device", "/dev/xvda"},
|
||||
},
|
||||
}
|
||||
|
||||
for i, testCase := range testCases {
|
||||
|
@ -815,99 +859,237 @@ func TestGetPodsTotalRequests(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPersistentVolumeDescriber(t *testing.T) {
|
||||
tests := map[string]*api.PersistentVolume{
|
||||
|
||||
"hostpath": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Type: new(api.HostPathType)},
|
||||
block := api.PersistentVolumeBlock
|
||||
file := api.PersistentVolumeFilesystem
|
||||
testCases := []struct {
|
||||
plugin string
|
||||
pv *api.PersistentVolume
|
||||
expectedElements []string
|
||||
unexpectedElements []string
|
||||
}{
|
||||
{
|
||||
plugin: "hostpath",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{Type: new(api.HostPathType)},
|
||||
},
|
||||
},
|
||||
},
|
||||
unexpectedElements: []string{"VolumeMode", "Filesystem"},
|
||||
},
|
||||
"gce": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{},
|
||||
{
|
||||
plugin: "gce",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
GCEPersistentDisk: &api.GCEPersistentDiskVolumeSource{},
|
||||
},
|
||||
VolumeMode: &file,
|
||||
},
|
||||
},
|
||||
expectedElements: []string{"VolumeMode", "Filesystem"},
|
||||
},
|
||||
"ebs": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{},
|
||||
{
|
||||
plugin: "ebs",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
AWSElasticBlockStore: &api.AWSElasticBlockStoreVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
unexpectedElements: []string{"VolumeMode", "Filesystem"},
|
||||
},
|
||||
"nfs": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
NFS: &api.NFSVolumeSource{},
|
||||
{
|
||||
plugin: "nfs",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
NFS: &api.NFSVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
unexpectedElements: []string{"VolumeMode", "Filesystem"},
|
||||
},
|
||||
"iscsi": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
ISCSI: &api.ISCSIPersistentVolumeSource{},
|
||||
{
|
||||
plugin: "iscsi",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
ISCSI: &api.ISCSIPersistentVolumeSource{},
|
||||
},
|
||||
VolumeMode: &block,
|
||||
},
|
||||
},
|
||||
expectedElements: []string{"VolumeMode", "Block"},
|
||||
},
|
||||
"gluster": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
Glusterfs: &api.GlusterfsVolumeSource{},
|
||||
{
|
||||
plugin: "gluster",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
Glusterfs: &api.GlusterfsVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
unexpectedElements: []string{"VolumeMode", "Filesystem"},
|
||||
},
|
||||
"rbd": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
RBD: &api.RBDPersistentVolumeSource{},
|
||||
{
|
||||
plugin: "rbd",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
RBD: &api.RBDPersistentVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
unexpectedElements: []string{"VolumeMode", "Filesystem"},
|
||||
},
|
||||
"quobyte": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
Quobyte: &api.QuobyteVolumeSource{},
|
||||
{
|
||||
plugin: "quobyte",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
Quobyte: &api.QuobyteVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
unexpectedElements: []string{"VolumeMode", "Filesystem"},
|
||||
},
|
||||
"cinder": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
Cinder: &api.CinderVolumeSource{},
|
||||
{
|
||||
plugin: "cinder",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
Cinder: &api.CinderVolumeSource{},
|
||||
},
|
||||
},
|
||||
},
|
||||
unexpectedElements: []string{"VolumeMode", "Filesystem"},
|
||||
},
|
||||
"fc": {
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
FC: &api.FCVolumeSource{},
|
||||
{
|
||||
plugin: "fc",
|
||||
pv: &api.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "bar"},
|
||||
Spec: api.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: api.PersistentVolumeSource{
|
||||
FC: &api.FCVolumeSource{},
|
||||
},
|
||||
VolumeMode: &block,
|
||||
},
|
||||
},
|
||||
expectedElements: []string{"VolumeMode", "Block"},
|
||||
},
|
||||
}
|
||||
|
||||
for name, pv := range tests {
|
||||
fake := fake.NewSimpleClientset(pv)
|
||||
for _, test := range testCases {
|
||||
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", name, err)
|
||||
t.Errorf("Unexpected error for test %s: %v", test.plugin, err)
|
||||
}
|
||||
if str == "" {
|
||||
t.Errorf("Unexpected empty string for test %s. Expected PV Describer output", name)
|
||||
t.Errorf("Unexpected empty string for test %s. Expected PV Describer output", test.plugin)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestPersistentVolumeClaimDescriber(t *testing.T) {
|
||||
block := api.PersistentVolumeBlock
|
||||
file := api.PersistentVolumeFilesystem
|
||||
goldClassName := "gold"
|
||||
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"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
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)
|
||||
}
|
||||
if str == "" {
|
||||
t.Errorf("Unexpected empty string for test %s. Expected PVC Describer output", test.name)
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue