...

Source file src/k8s.io/kubectl/pkg/explain/model_printer.go

Documentation: k8s.io/kubectl/pkg/explain

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package explain
    18  
    19  import (
    20  	"k8s.io/apimachinery/pkg/runtime/schema"
    21  	"k8s.io/kube-openapi/pkg/util/proto"
    22  )
    23  
    24  const (
    25  	// fieldIndentLevel is the level of indentation for fields.
    26  	fieldIndentLevel = 3
    27  	// descriptionIndentLevel is the level of indentation for the
    28  	// description.
    29  	descriptionIndentLevel = 5
    30  )
    31  
    32  // modelPrinter prints a schema in Writer. Its "Builder" will decide if
    33  // it's recursive or not.
    34  type modelPrinter struct {
    35  	Name         string
    36  	Type         string
    37  	Descriptions []string
    38  	Writer       *Formatter
    39  	Builder      fieldsPrinterBuilder
    40  	GVK          schema.GroupVersionKind
    41  	Error        error
    42  }
    43  
    44  var _ proto.SchemaVisitor = &modelPrinter{}
    45  
    46  func (m *modelPrinter) PrintKindAndVersion() error {
    47  	if err := m.Writer.Write("KIND:     %s", m.GVK.Kind); err != nil {
    48  		return err
    49  	}
    50  	return m.Writer.Write("VERSION:  %s\n", m.GVK.GroupVersion())
    51  }
    52  
    53  // PrintDescription prints the description for a given schema. There
    54  // might be multiple description, since we collect descriptions when we
    55  // go through references, arrays and maps.
    56  func (m *modelPrinter) PrintDescription(schema proto.Schema) error {
    57  	if err := m.Writer.Write("DESCRIPTION:"); err != nil {
    58  		return err
    59  	}
    60  	empty := true
    61  	for i, desc := range append(m.Descriptions, schema.GetDescription()) {
    62  		if desc == "" {
    63  			continue
    64  		}
    65  		empty = false
    66  		if i != 0 {
    67  			if err := m.Writer.Write(""); err != nil {
    68  				return err
    69  			}
    70  		}
    71  		if err := m.Writer.Indent(descriptionIndentLevel).WriteWrapped("%s", desc); err != nil {
    72  			return err
    73  		}
    74  	}
    75  	if empty {
    76  		return m.Writer.Indent(descriptionIndentLevel).WriteWrapped("<empty>")
    77  	}
    78  	return nil
    79  }
    80  
    81  // VisitArray recurses inside the subtype, while collecting the type if
    82  // not done yet, and the description.
    83  func (m *modelPrinter) VisitArray(a *proto.Array) {
    84  	m.Descriptions = append(m.Descriptions, a.GetDescription())
    85  	if m.Type == "" {
    86  		m.Type = GetTypeName(a)
    87  	}
    88  	a.SubType.Accept(m)
    89  }
    90  
    91  // VisitKind prints a full resource with its fields.
    92  func (m *modelPrinter) VisitKind(k *proto.Kind) {
    93  	if err := m.PrintKindAndVersion(); err != nil {
    94  		m.Error = err
    95  		return
    96  	}
    97  
    98  	if m.Type == "" {
    99  		m.Type = GetTypeName(k)
   100  	}
   101  	if m.Name != "" {
   102  		m.Writer.Write("RESOURCE: %s <%s>\n", m.Name, m.Type)
   103  	}
   104  
   105  	if err := m.PrintDescription(k); err != nil {
   106  		m.Error = err
   107  		return
   108  	}
   109  	if err := m.Writer.Write("\nFIELDS:"); err != nil {
   110  		m.Error = err
   111  		return
   112  	}
   113  	m.Error = m.Builder.BuildFieldsPrinter(m.Writer.Indent(fieldIndentLevel)).PrintFields(k)
   114  }
   115  
   116  // VisitMap recurses inside the subtype, while collecting the type if
   117  // not done yet, and the description.
   118  func (m *modelPrinter) VisitMap(om *proto.Map) {
   119  	m.Descriptions = append(m.Descriptions, om.GetDescription())
   120  	if m.Type == "" {
   121  		m.Type = GetTypeName(om)
   122  	}
   123  	om.SubType.Accept(m)
   124  }
   125  
   126  // VisitPrimitive prints a field type and its description.
   127  func (m *modelPrinter) VisitPrimitive(p *proto.Primitive) {
   128  	if err := m.PrintKindAndVersion(); err != nil {
   129  		m.Error = err
   130  		return
   131  	}
   132  
   133  	if m.Type == "" {
   134  		m.Type = GetTypeName(p)
   135  	}
   136  	if err := m.Writer.Write("FIELD:    %s <%s>\n", m.Name, m.Type); err != nil {
   137  		m.Error = err
   138  		return
   139  	}
   140  	m.Error = m.PrintDescription(p)
   141  }
   142  
   143  func (m *modelPrinter) VisitArbitrary(a *proto.Arbitrary) {
   144  	if err := m.PrintKindAndVersion(); err != nil {
   145  		m.Error = err
   146  		return
   147  	}
   148  
   149  	m.Error = m.PrintDescription(a)
   150  }
   151  
   152  // VisitReference recurses inside the subtype, while collecting the description.
   153  func (m *modelPrinter) VisitReference(r proto.Reference) {
   154  	m.Descriptions = append(m.Descriptions, r.GetDescription())
   155  	r.SubSchema().Accept(m)
   156  }
   157  
   158  // PrintModel prints the description of a schema in writer.
   159  func PrintModel(name string, writer *Formatter, builder fieldsPrinterBuilder, schema proto.Schema, gvk schema.GroupVersionKind) error {
   160  	m := &modelPrinter{Name: name, Writer: writer, Builder: builder, GVK: gvk}
   161  	schema.Accept(m)
   162  	return m.Error
   163  }
   164  

View as plain text