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 }