github.com/john-lin/cni@v0.6.0-rc1.0.20170712150331-b69e640cc0e2/Documentation/spec-upgrades.md (about) 1 # How to upgrade to CNI Specification v0.3.1 2 3 The 0.3.0 specification contained a small error. The Result structure's `ip` field should have been renamed to `ips` to be consistent with the IPAM result structure definition; this rename was missed when updating the Result to accommodate multiple IP addresses and interfaces. All first-party CNI plugins (bridge, host-local, etc) were updated to use `ips` (and thus be inconsistent with the 0.3.0 specification) and most other plugins have not been updated to the 0.3.0 specification yet, so few (if any) users should be impacted by this change. 4 5 The 0.3.1 specification corrects the Result structure to use the `ips` field name as originally intended. This is the only change between 0.3.0 and 0.3.1. 6 7 # How to upgrade to CNI Specification v0.3.0 8 9 Version 0.3.0 of the [CNI Specification](../SPEC.md) provides rich information 10 about container network configuration, including details of network interfaces 11 and support for multiple IP addresses. 12 13 To support this new data, the specification changed in a couple significant 14 ways that will impact CNI users, plugin authors, and runtime authors. 15 16 This document provides guidance for how to upgrade: 17 18 - [For CNI Users](#for-cni-users) 19 - [For Plugin Authors](#for-plugin-authors) 20 - [For Runtime Authors](#for-runtime-authors) 21 22 **Note**: the CNI Spec is versioned independently from the GitHub releases 23 for this repo. For example, Release v0.4.0 supports Spec version v0.2.0, 24 and Release v0.5.0 supports Spec v0.3.0. 25 26 ---- 27 28 ## For CNI Users 29 If you maintain CNI configuration files for a container runtime that uses CNI, 30 ensure that the configuration files specify a `cniVersion` field and that the 31 version there is supported by your container runtime and CNI plugins. 32 Configuration files without a version field should be given version 0.2.0. 33 The CNI spec includes example configuration files for 34 [single plugins](https://github.com/containernetworking/cni/blob/master/SPEC.md#example-configurations) 35 and for [lists of chained plugins](https://github.com/containernetworking/cni/blob/master/SPEC.md#example-configurations). 36 37 Consult the documentation for your runtime and plugins to determine what 38 CNI spec versions they support. Test any plugin upgrades before deploying to 39 production. You may find [cnitool](https://github.com/containernetworking/cni/tree/master/cnitool) 40 useful. Specifically, your configuration version should be the lowest common 41 version supported by your plugins. 42 43 ## For Plugin Authors 44 This section provides guidance for upgrading plugins to CNI Spec Version 0.3.0. 45 46 ### General guidance for all plugins (language agnostic) 47 To provide the smoothest upgrade path, **existing plugins should support 48 multiple versions of the CNI spec**. In particular, plugins with existing 49 installed bases should add support for CNI spec version 0.3.0 while maintaining 50 compatibility with older versions. 51 52 To do this, two changes are required. First, a plugin should advertise which 53 CNI spec versions it supports. It does this by responding to the `VERSION` 54 command with the following JSON data: 55 56 ```json 57 { 58 "cniVersion": "0.3.0", 59 "supportedVersions": [ "0.1.0", "0.2.0", "0.3.0" ] 60 } 61 ``` 62 63 Second, for the `ADD` command, a plugin must respect the `cniVersion` field 64 provided in the [network configuration JSON](https://github.com/containernetworking/cni/blob/master/SPEC.md#network-configuration). 65 That field is a request for the plugin to return results of a particular format: 66 67 - If the `cniVersion` field is not present, then spec v0.2.0 should be assumed 68 and v0.2.0 format result JSON returned. 69 70 - If the plugin doesn't support the version, the plugin must error. 71 72 - Otherwise, the plugin must return a [CNI Result](https://github.com/containernetworking/cni/blob/master/SPEC.md#result) 73 in the format requested. 74 75 Result formats for older CNI spec versions are available in the 76 [git history for SPEC.md](https://github.com/containernetworking/cni/commits/master/SPEC.md). 77 78 For example, suppose a plugin, via its `VERSION` response, advertises CNI specification 79 support for v0.2.0 and v0.3.0. When it receives `cniVersion` key of `0.2.0`, 80 the plugin must return result JSON conforming to CNI spec version 0.2.0. 81 82 ### Specific guidance for plugins written in Go 83 Plugins written in Go may leverage the Go language packages in this repository 84 to ease the process of upgrading and supporting multiple versions. CNI 85 [Library and Plugins Release v0.5.0](https://github.com/containernetworking/cni/releases) 86 includes important changes to the Golang APIs. Plugins using these APIs will 87 require some changes now, but should more-easily handle spec changes and 88 new features going forward. 89 90 For plugin authors, the biggest change is that `types.Result` is now an 91 interface implemented by concrete struct types in the `types/current` and 92 `types/020` subpackages. 93 94 Internally, plugins should use the `types/current` structs, and convert 95 to or from specific versions when required. A typical plugin will only need 96 to do a single conversion. That is when it is about to complete and needs to 97 print the result JSON in the correct format to stdout. The library 98 function `types.PrintResult()` simplifies this by converting and printing in 99 a single call. 100 101 Additionally, the plugin should advertise which CNI Spec versions it supports 102 via the 3rd argument to `skel.PluginMain()`. 103 104 Here is some example code 105 106 ```go 107 import ( 108 "github.com/containernetworking/cni/pkg/skel" 109 "github.com/containernetworking/cni/pkg/types" 110 "github.com/containernetworking/cni/pkg/types/current" 111 "github.com/containernetworking/cni/pkg/version" 112 ) 113 114 func cmdAdd(args *skel.CmdArgs) error { 115 // determine spec version to use 116 var netConf struct { 117 types.NetConf 118 // other plugin-specific configuration goes here 119 } 120 err := json.Unmarshal(args.StdinData, &netConf) 121 cniVersion := netConf.CNIVersion 122 123 // plugin does its work... 124 // set up interfaces 125 // assign addresses, etc 126 127 // construct the result 128 result := ¤t.Result{ 129 Interfaces: []*current.Interface{ ... }, 130 IPs: []*current.IPs{ ... }, 131 ... 132 } 133 134 // print result to stdout, in the format defined by the requested cniVersion 135 return types.PrintResult(result, cniVersion) 136 } 137 138 func main() { 139 skel.PluginMain(cmdAdd, cmdDel, version.PluginSupports("0.1.0", "0.2.0", "0.3.0")) 140 } 141 ``` 142 143 Alternately, to use the result from a delegated IPAM plugin, the `result` 144 value might be formed like this: 145 146 ```go 147 ipamResult, err := ipam.ExecAdd(netConf.IPAM.Type, args.StdinData) 148 result, err := current.NewResultFromResult(ipamResult) 149 ``` 150 151 Other examples of spec v0.3.0-compatible plugins are the 152 [main plugins in this repo](https://github.com/containernetworking/cni/tree/master/plugins/main) 153 154 155 ## For Runtime Authors 156 157 This section provides guidance for upgrading container runtimes to support 158 CNI Spec Version 0.3.0. 159 160 ### General guidance for all runtimes (language agnostic) 161 162 #### Support multiple CNI spec versions 163 To provide the smoothest upgrade path and support the broadest range of CNI 164 plugins, **container runtimes should support multiple versions of the CNI spec**. 165 In particular, runtimes with existing installed bases should add support for CNI 166 spec version 0.3.0 while maintaining compatibility with older versions. 167 168 To support multiple versions of the CNI spec, runtimes should be able to 169 call both new and legacy plugins, and handle the results from either. 170 171 When calling a plugin, the runtime must request that the plugin respond in a 172 particular format by specifying the `cniVersion` field in the 173 [Network Configuration](https://github.com/containernetworking/cni/blob/master/SPEC.md#network-configuration) 174 JSON block. The plugin will then respond with 175 a [Result](https://github.com/containernetworking/cni/blob/master/SPEC.md#result) 176 in the format defined by that CNI spec version, and the runtime must parse 177 and handle this result. 178 179 #### Handle errors due to version incompatibility 180 Plugins may respond with error indicating that they don't support the requested 181 CNI version (see [Well-known Error Codes](https://github.com/containernetworking/cni/blob/master/SPEC.md#well-known-error-codes)), 182 e.g. 183 ```json 184 { 185 "cniVersion": "0.2.0", 186 "code": 1, 187 "msg": "CNI version not supported" 188 } 189 ``` 190 In that case, the runtime may retry with a lower CNI spec version, or take 191 some other action. 192 193 #### (optional) Discover plugin version support 194 Runtimes may discover which CNI spec versions are supported by a plugin, by 195 calling the plugin with the `VERSION` command. The `VERSION` command was 196 added in CNI spec v0.2.0, so older plugins may not respect it. In the absence 197 of a successful response to `VERSION`, assume that the plugin only supports 198 CNI spec v0.1.0. 199 200 #### Handle missing data in v0.3.0 results 201 The Result for the `ADD` command in CNI spec version 0.3.0 includes a new field 202 `interfaces`. An IP address in the `ip` field may describe which interface 203 it is assigned to, by placing a numeric index in the `interface` subfield. 204 205 However, some plugins which are v0.3.0 compatible may nonetheless omit the 206 `interfaces` field and/or set the `interface` index value to `-1`. Runtimes 207 should gracefully handle this situation, unless they have good reason to rely 208 on the existence of the interface data. In that case, provide the user an 209 error message that helps diagnose the issue. 210 211 ### Specific guidance for container runtimes written in Go 212 Container runtimes written in Go may leverage the Go language packages in this 213 repository to ease the process of upgrading and supporting multiple versions. 214 CNI [Library and Plugins Release v0.5.0](https://github.com/containernetworking/cni/releases) 215 includes important changes to the Golang APIs. Runtimes using these APIs will 216 require some changes now, but should more-easily handle spec changes and 217 new features going forward. 218 219 For runtimes, the biggest changes to the Go libraries are in the `types` package. 220 It has been refactored to make working with versioned results simpler. The top-level 221 `types.Result` is now an opaque interface instead of a struct, and APIs exposed by 222 other packages, such as the high-level `libcni` package, have been updated to use 223 this interface. Concrete types are now per-version subpackages. The `types/current` 224 subpackage contains the latest (spec v0.3.0) types. 225 226 When up-converting older result types to spec v0.3.0, fields new in 227 spec v0.3.0 (like `interfaces`) may be empty. Conversely, when 228 down-converting v0.3.0 results to an older version, any data in those fields 229 will be lost. 230 231 | From | 0.1 | 0.2 | 0.3 | 232 |--------|-----|-----|-----| 233 | To 0.1 | ✔ | ✔ | x | 234 | To 0.2 | ✔ | ✔ | x | 235 | To 0.3 | ✴ | ✴ | ✔ | 236 237 238 Key: 239 > ✔ : lossless conversion <br> 240 > ✴ : higher-version output may have empty fields <br> 241 > x : lower-version output is missing some data <br> 242 243 244 245 A container runtime should use `current.NewResultFromResult()` to convert the 246 opaque `types.Result` to a concrete `current.Result` struct. It may then 247 work with the fields exposed by that struct: 248 249 ```go 250 // runtime invokes the plugin to get the opaque types.Result 251 // this may conform to any CNI spec version 252 resultInterface, err := libcni.AddNetwork(netConf, runtimeConf) 253 254 // upconvert result to the current 0.3.0 spec 255 result, err := current.NewResultFromResult(resultInterface) 256 257 // use the result fields .... 258 for _, ip := range result.IPs { ... } 259 ```