github.com/baraj55/containernetworking-cni@v0.7.2-0.20200219164625-56ace59a9e7f/pkg/types/types.go (about)

     1  // Copyright 2015 CNI authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package types
    16  
    17  import (
    18  	"encoding/json"
    19  	"fmt"
    20  	"io"
    21  	"net"
    22  	"os"
    23  )
    24  
    25  // like net.IPNet but adds JSON marshalling and unmarshalling
    26  type IPNet net.IPNet
    27  
    28  // ParseCIDR takes a string like "10.2.3.1/24" and
    29  // return IPNet with "10.2.3.1" and /24 mask
    30  func ParseCIDR(s string) (*net.IPNet, error) {
    31  	ip, ipn, err := net.ParseCIDR(s)
    32  	if err != nil {
    33  		return nil, err
    34  	}
    35  
    36  	ipn.IP = ip
    37  	return ipn, nil
    38  }
    39  
    40  func (n IPNet) MarshalJSON() ([]byte, error) {
    41  	return json.Marshal((*net.IPNet)(&n).String())
    42  }
    43  
    44  func (n *IPNet) UnmarshalJSON(data []byte) error {
    45  	var s string
    46  	if err := json.Unmarshal(data, &s); err != nil {
    47  		return err
    48  	}
    49  
    50  	tmp, err := ParseCIDR(s)
    51  	if err != nil {
    52  		return err
    53  	}
    54  
    55  	*n = IPNet(*tmp)
    56  	return nil
    57  }
    58  
    59  // NetConf describes a network.
    60  type NetConf struct {
    61  	CNIVersion string `json:"cniVersion,omitempty"`
    62  
    63  	Name         string          `json:"name,omitempty"`
    64  	Type         string          `json:"type,omitempty"`
    65  	Capabilities map[string]bool `json:"capabilities,omitempty"`
    66  	IPAM         IPAM            `json:"ipam,omitempty"`
    67  	DNS          DNS             `json:"dns"`
    68  
    69  	RawPrevResult map[string]interface{} `json:"prevResult,omitempty"`
    70  	PrevResult    Result                 `json:"-"`
    71  }
    72  
    73  type IPAM struct {
    74  	Type string `json:"type,omitempty"`
    75  }
    76  
    77  // NetConfList describes an ordered list of networks.
    78  type NetConfList struct {
    79  	CNIVersion string `json:"cniVersion,omitempty"`
    80  
    81  	Name         string     `json:"name,omitempty"`
    82  	DisableCheck bool       `json:"disableCheck,omitempty"`
    83  	Plugins      []*NetConf `json:"plugins,omitempty"`
    84  }
    85  
    86  type ResultFactoryFunc func([]byte) (Result, error)
    87  
    88  // Result is an interface that provides the result of plugin execution
    89  type Result interface {
    90  	// The highest CNI specification result version the result supports
    91  	// without having to convert
    92  	Version() string
    93  
    94  	// Returns the result converted into the requested CNI specification
    95  	// result version, or an error if conversion failed
    96  	GetAsVersion(version string) (Result, error)
    97  
    98  	// Prints the result in JSON format to stdout
    99  	Print() error
   100  
   101  	// Prints the result in JSON format to provided writer
   102  	PrintTo(writer io.Writer) error
   103  }
   104  
   105  func PrintResult(result Result, version string) error {
   106  	newResult, err := result.GetAsVersion(version)
   107  	if err != nil {
   108  		return err
   109  	}
   110  	return newResult.Print()
   111  }
   112  
   113  // DNS contains values interesting for DNS resolvers
   114  type DNS struct {
   115  	Nameservers []string `json:"nameservers,omitempty"`
   116  	Domain      string   `json:"domain,omitempty"`
   117  	Search      []string `json:"search,omitempty"`
   118  	Options     []string `json:"options,omitempty"`
   119  }
   120  
   121  type Route struct {
   122  	Dst net.IPNet
   123  	GW  net.IP
   124  }
   125  
   126  func (r *Route) String() string {
   127  	return fmt.Sprintf("%+v", *r)
   128  }
   129  
   130  // Well known error codes
   131  // see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
   132  const (
   133  	ErrUnknown                     uint = iota // 0
   134  	ErrIncompatibleCNIVersion                  // 1
   135  	ErrUnsupportedField                        // 2
   136  	ErrUnknownContainer                        // 3
   137  	ErrInvalidEnvironmentVariables             // 4
   138  	ErrIOFailure                               // 5
   139  	ErrDecodingFailure                         // 6
   140  	ErrInvalidNetworkConfig                    // 7
   141  	ErrTryAgainLater               uint = 11
   142  	ErrInternal                    uint = 999
   143  )
   144  
   145  type Error struct {
   146  	Code    uint   `json:"code"`
   147  	Msg     string `json:"msg"`
   148  	Details string `json:"details,omitempty"`
   149  }
   150  
   151  func NewError(code uint, msg, details string) *Error {
   152  	return &Error{
   153  		Code:    code,
   154  		Msg:     msg,
   155  		Details: details,
   156  	}
   157  }
   158  
   159  func (e *Error) Error() string {
   160  	details := ""
   161  	if e.Details != "" {
   162  		details = fmt.Sprintf("; %v", e.Details)
   163  	}
   164  	return fmt.Sprintf("%v%v", e.Msg, details)
   165  }
   166  
   167  func (e *Error) Print() error {
   168  	return prettyPrint(e)
   169  }
   170  
   171  // net.IPNet is not JSON (un)marshallable so this duality is needed
   172  // for our custom IPNet type
   173  
   174  // JSON (un)marshallable types
   175  type route struct {
   176  	Dst IPNet  `json:"dst"`
   177  	GW  net.IP `json:"gw,omitempty"`
   178  }
   179  
   180  func (r *Route) UnmarshalJSON(data []byte) error {
   181  	rt := route{}
   182  	if err := json.Unmarshal(data, &rt); err != nil {
   183  		return err
   184  	}
   185  
   186  	r.Dst = net.IPNet(rt.Dst)
   187  	r.GW = rt.GW
   188  	return nil
   189  }
   190  
   191  func (r Route) MarshalJSON() ([]byte, error) {
   192  	rt := route{
   193  		Dst: IPNet(r.Dst),
   194  		GW:  r.GW,
   195  	}
   196  
   197  	return json.Marshal(rt)
   198  }
   199  
   200  func prettyPrint(obj interface{}) error {
   201  	data, err := json.MarshalIndent(obj, "", "    ")
   202  	if err != nil {
   203  		return err
   204  	}
   205  	_, err = os.Stdout.Write(data)
   206  	return err
   207  }