github.com/john-lin/cni@v0.6.0-rc1.0.20170712150331-b69e640cc0e2/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  	"errors"
    20  	"fmt"
    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         struct {
    67  		Type string `json:"type,omitempty"`
    68  	} `json:"ipam,omitempty"`
    69  	DNS DNS `json:"dns"`
    70  }
    71  
    72  // NetConfList describes an ordered list of networks.
    73  type NetConfList struct {
    74  	CNIVersion string `json:"cniVersion,omitempty"`
    75  
    76  	Name    string     `json:"name,omitempty"`
    77  	Plugins []*NetConf `json:"plugins,omitempty"`
    78  }
    79  
    80  type ResultFactoryFunc func([]byte) (Result, error)
    81  
    82  // Result is an interface that provides the result of plugin execution
    83  type Result interface {
    84  	// The highest CNI specification result verison the result supports
    85  	// without having to convert
    86  	Version() string
    87  
    88  	// Returns the result converted into the requested CNI specification
    89  	// result version, or an error if conversion failed
    90  	GetAsVersion(version string) (Result, error)
    91  
    92  	// Prints the result in JSON format to stdout
    93  	Print() error
    94  
    95  	// Returns a JSON string representation of the result
    96  	String() string
    97  }
    98  
    99  func PrintResult(result Result, version string) error {
   100  	newResult, err := result.GetAsVersion(version)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	return newResult.Print()
   105  }
   106  
   107  // DNS contains values interesting for DNS resolvers
   108  type DNS struct {
   109  	Nameservers []string `json:"nameservers,omitempty"`
   110  	Domain      string   `json:"domain,omitempty"`
   111  	Search      []string `json:"search,omitempty"`
   112  	Options     []string `json:"options,omitempty"`
   113  }
   114  
   115  type Route struct {
   116  	Dst net.IPNet
   117  	GW  net.IP
   118  }
   119  
   120  func (r *Route) String() string {
   121  	return fmt.Sprintf("%+v", *r)
   122  }
   123  
   124  // Well known error codes
   125  // see https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes
   126  const (
   127  	ErrUnknown                uint = iota // 0
   128  	ErrIncompatibleCNIVersion             // 1
   129  	ErrUnsupportedField                   // 2
   130  )
   131  
   132  type Error struct {
   133  	Code    uint   `json:"code"`
   134  	Msg     string `json:"msg"`
   135  	Details string `json:"details,omitempty"`
   136  }
   137  
   138  func (e *Error) Error() string {
   139  	details := ""
   140  	if e.Details != "" {
   141  		details = fmt.Sprintf("; %v", e.Details)
   142  	}
   143  	return fmt.Sprintf("%v%v", e.Msg, details)
   144  }
   145  
   146  func (e *Error) Print() error {
   147  	return prettyPrint(e)
   148  }
   149  
   150  // net.IPNet is not JSON (un)marshallable so this duality is needed
   151  // for our custom IPNet type
   152  
   153  // JSON (un)marshallable types
   154  type route struct {
   155  	Dst IPNet  `json:"dst"`
   156  	GW  net.IP `json:"gw,omitempty"`
   157  }
   158  
   159  func (r *Route) UnmarshalJSON(data []byte) error {
   160  	rt := route{}
   161  	if err := json.Unmarshal(data, &rt); err != nil {
   162  		return err
   163  	}
   164  
   165  	r.Dst = net.IPNet(rt.Dst)
   166  	r.GW = rt.GW
   167  	return nil
   168  }
   169  
   170  func (r *Route) MarshalJSON() ([]byte, error) {
   171  	rt := route{
   172  		Dst: IPNet(r.Dst),
   173  		GW:  r.GW,
   174  	}
   175  
   176  	return json.Marshal(rt)
   177  }
   178  
   179  func prettyPrint(obj interface{}) error {
   180  	data, err := json.MarshalIndent(obj, "", "    ")
   181  	if err != nil {
   182  		return err
   183  	}
   184  	_, err = os.Stdout.Write(data)
   185  	return err
   186  }
   187  
   188  // NotImplementedError is used to indicate that a method is not implemented for the given platform
   189  var NotImplementedError = errors.New("Not Implemented")