├── .gitignore ├── Godeps ├── Godeps.json └── Readme ├── LICENSE ├── README.md ├── client └── k8s.go ├── conf ├── app.conf └── config ├── controllers ├── app.go ├── flavor.go ├── image.go ├── ingress.go ├── project.go └── service.go ├── main.go ├── models ├── app.go ├── ingress.go └── service.go ├── routers ├── commentsRouter_controllers.go └── router.go └── tests └── default_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | 16 | vendor 17 | swagger 18 | ice 19 | lastupdate.tmp 20 | 21 | # goland 22 | .idea/ 23 | 24 | -------------------------------------------------------------------------------- /Godeps/Godeps.json: -------------------------------------------------------------------------------- 1 | { 2 | "ImportPath": "github.com/yaoice/ice", 3 | "GoVersion": "go1.9", 4 | "GodepVersion": "v80", 5 | "Deps": [ 6 | { 7 | "ImportPath": "github.com/PuerkitoBio/purell", 8 | "Comment": "v1.0.0", 9 | "Rev": "8a290539e2e8629dbc4e6bad948158f790ec31f4" 10 | }, 11 | { 12 | "ImportPath": "github.com/PuerkitoBio/urlesc", 13 | "Rev": "5bd2802263f21d8788851d5305584c82a5c75d7e" 14 | }, 15 | { 16 | "ImportPath": "github.com/astaxie/beego", 17 | "Comment": "v1.9.2-2-gf166888", 18 | "Rev": "f16688817aa428d10361394015b40d096b680542" 19 | }, 20 | { 21 | "ImportPath": "github.com/astaxie/beego/config", 22 | "Comment": "v1.9.2-2-gf166888", 23 | "Rev": "f16688817aa428d10361394015b40d096b680542" 24 | }, 25 | { 26 | "ImportPath": "github.com/astaxie/beego/context", 27 | "Comment": "v1.9.2-2-gf166888", 28 | "Rev": "f16688817aa428d10361394015b40d096b680542" 29 | }, 30 | { 31 | "ImportPath": "github.com/astaxie/beego/context/param", 32 | "Comment": "v1.9.2-2-gf166888", 33 | "Rev": "f16688817aa428d10361394015b40d096b680542" 34 | }, 35 | { 36 | "ImportPath": "github.com/astaxie/beego/grace", 37 | "Comment": "v1.9.2-2-gf166888", 38 | "Rev": "f16688817aa428d10361394015b40d096b680542" 39 | }, 40 | { 41 | "ImportPath": "github.com/astaxie/beego/logs", 42 | "Comment": "v1.9.2-2-gf166888", 43 | "Rev": "f16688817aa428d10361394015b40d096b680542" 44 | }, 45 | { 46 | "ImportPath": "github.com/astaxie/beego/session", 47 | "Comment": "v1.9.2-2-gf166888", 48 | "Rev": "f16688817aa428d10361394015b40d096b680542" 49 | }, 50 | { 51 | "ImportPath": "github.com/astaxie/beego/toolbox", 52 | "Comment": "v1.9.2-2-gf166888", 53 | "Rev": "f16688817aa428d10361394015b40d096b680542" 54 | }, 55 | { 56 | "ImportPath": "github.com/astaxie/beego/utils", 57 | "Comment": "v1.9.2-2-gf166888", 58 | "Rev": "f16688817aa428d10361394015b40d096b680542" 59 | }, 60 | { 61 | "ImportPath": "github.com/emicklei/go-restful", 62 | "Comment": "2.2.0-4-gff4f55a", 63 | "Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46" 64 | }, 65 | { 66 | "ImportPath": "github.com/emicklei/go-restful/log", 67 | "Comment": "2.2.0-4-gff4f55a", 68 | "Rev": "ff4f55a206334ef123e4f79bbf348980da81ca46" 69 | }, 70 | { 71 | "ImportPath": "github.com/ghodss/yaml", 72 | "Rev": "73d445a93680fa1a78ae23a5839bad48f32ba1ee" 73 | }, 74 | { 75 | "ImportPath": "github.com/go-openapi/jsonpointer", 76 | "Rev": "46af16f9f7b149af66e5d1bd010e3574dc06de98" 77 | }, 78 | { 79 | "ImportPath": "github.com/go-openapi/jsonreference", 80 | "Rev": "13c6e3589ad90f49bd3e3bbe2c2cb3d7a4142272" 81 | }, 82 | { 83 | "ImportPath": "github.com/go-openapi/spec", 84 | "Rev": "7abd5745472fff5eb3685386d5fb8bf38683154d" 85 | }, 86 | { 87 | "ImportPath": "github.com/go-openapi/swag", 88 | "Rev": "f3f9494671f93fcff853e3c6e9e948b3eb71e590" 89 | }, 90 | { 91 | "ImportPath": "github.com/gogo/protobuf/proto", 92 | "Comment": "v0.4-3-gc0656edd", 93 | "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" 94 | }, 95 | { 96 | "ImportPath": "github.com/gogo/protobuf/sortkeys", 97 | "Comment": "v0.4-3-gc0656edd", 98 | "Rev": "c0656edd0d9eab7c66d1eb0c568f9039345796f7" 99 | }, 100 | { 101 | "ImportPath": "github.com/golang/glog", 102 | "Rev": "44145f04b68cf362d9c4df2182967c2275eaefed" 103 | }, 104 | { 105 | "ImportPath": "github.com/golang/protobuf/proto", 106 | "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" 107 | }, 108 | { 109 | "ImportPath": "github.com/golang/protobuf/ptypes", 110 | "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" 111 | }, 112 | { 113 | "ImportPath": "github.com/golang/protobuf/ptypes/any", 114 | "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" 115 | }, 116 | { 117 | "ImportPath": "github.com/golang/protobuf/ptypes/duration", 118 | "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" 119 | }, 120 | { 121 | "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", 122 | "Rev": "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" 123 | }, 124 | { 125 | "ImportPath": "github.com/google/btree", 126 | "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" 127 | }, 128 | { 129 | "ImportPath": "github.com/google/gofuzz", 130 | "Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c" 131 | }, 132 | { 133 | "ImportPath": "github.com/googleapis/gnostic/OpenAPIv2", 134 | "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" 135 | }, 136 | { 137 | "ImportPath": "github.com/googleapis/gnostic/compiler", 138 | "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" 139 | }, 140 | { 141 | "ImportPath": "github.com/googleapis/gnostic/extensions", 142 | "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" 143 | }, 144 | { 145 | "ImportPath": "github.com/gregjones/httpcache", 146 | "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" 147 | }, 148 | { 149 | "ImportPath": "github.com/gregjones/httpcache/diskcache", 150 | "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" 151 | }, 152 | { 153 | "ImportPath": "github.com/howeyc/gopass", 154 | "Rev": "bf9dde6d0d2c004a008c27aaee91170c786f6db8" 155 | }, 156 | { 157 | "ImportPath": "github.com/imdario/mergo", 158 | "Comment": "0.1.3-8-g6633656", 159 | "Rev": "6633656539c1639d9d78127b7d47c622b5d7b6dc" 160 | }, 161 | { 162 | "ImportPath": "github.com/json-iterator/go", 163 | "Comment": "1.0.0", 164 | "Rev": "36b14963da70d11297d313183d7e6388c8510e1e" 165 | }, 166 | { 167 | "ImportPath": "github.com/juju/ratelimit", 168 | "Comment": "1.0", 169 | "Rev": "5b9ff866471762aa2ab2dced63c9fb6f53921342" 170 | }, 171 | { 172 | "ImportPath": "github.com/mailru/easyjson/buffer", 173 | "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" 174 | }, 175 | { 176 | "ImportPath": "github.com/mailru/easyjson/jlexer", 177 | "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" 178 | }, 179 | { 180 | "ImportPath": "github.com/mailru/easyjson/jwriter", 181 | "Rev": "2f5df55504ebc322e4d52d34df6a1f5b503bf26d" 182 | }, 183 | { 184 | "ImportPath": "github.com/peterbourgon/diskv", 185 | "Comment": "v2.0.1", 186 | "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" 187 | }, 188 | { 189 | "ImportPath": "github.com/spf13/pflag", 190 | "Rev": "9ff6c6923cfffbcd502984b8e0c80539a94968b7" 191 | }, 192 | { 193 | "ImportPath": "golang.org/x/crypto/ssh/terminal", 194 | "Rev": "81e90905daefcd6fd217b62423c0908922eadb30" 195 | }, 196 | { 197 | "ImportPath": "golang.org/x/net/http2", 198 | "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f" 199 | }, 200 | { 201 | "ImportPath": "golang.org/x/net/http2/hpack", 202 | "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f" 203 | }, 204 | { 205 | "ImportPath": "golang.org/x/net/idna", 206 | "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f" 207 | }, 208 | { 209 | "ImportPath": "golang.org/x/net/lex/httplex", 210 | "Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f" 211 | }, 212 | { 213 | "ImportPath": "golang.org/x/sys/unix", 214 | "Rev": "95c6576299259db960f6c5b9b69ea52422860fce" 215 | }, 216 | { 217 | "ImportPath": "golang.org/x/sys/windows", 218 | "Rev": "95c6576299259db960f6c5b9b69ea52422860fce" 219 | }, 220 | { 221 | "ImportPath": "golang.org/x/text/cases", 222 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 223 | }, 224 | { 225 | "ImportPath": "golang.org/x/text/internal", 226 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 227 | }, 228 | { 229 | "ImportPath": "golang.org/x/text/internal/tag", 230 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 231 | }, 232 | { 233 | "ImportPath": "golang.org/x/text/language", 234 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 235 | }, 236 | { 237 | "ImportPath": "golang.org/x/text/runes", 238 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 239 | }, 240 | { 241 | "ImportPath": "golang.org/x/text/secure/bidirule", 242 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 243 | }, 244 | { 245 | "ImportPath": "golang.org/x/text/secure/precis", 246 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 247 | }, 248 | { 249 | "ImportPath": "golang.org/x/text/transform", 250 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 251 | }, 252 | { 253 | "ImportPath": "golang.org/x/text/unicode/bidi", 254 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 255 | }, 256 | { 257 | "ImportPath": "golang.org/x/text/unicode/norm", 258 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 259 | }, 260 | { 261 | "ImportPath": "golang.org/x/text/width", 262 | "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" 263 | }, 264 | { 265 | "ImportPath": "gopkg.in/inf.v0", 266 | "Comment": "v0.9.0", 267 | "Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" 268 | }, 269 | { 270 | "ImportPath": "gopkg.in/yaml.v2", 271 | "Rev": "53feefa2559fb8dfa8d81baad31be332c97d6c77" 272 | }, 273 | { 274 | "ImportPath": "k8s.io/api/admissionregistration/v1alpha1", 275 | "Comment": "kubernetes-1.9.3-beta.0", 276 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 277 | }, 278 | { 279 | "ImportPath": "k8s.io/api/admissionregistration/v1beta1", 280 | "Comment": "kubernetes-1.9.3-beta.0", 281 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 282 | }, 283 | { 284 | "ImportPath": "k8s.io/api/apps/v1", 285 | "Comment": "kubernetes-1.9.3-beta.0", 286 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 287 | }, 288 | { 289 | "ImportPath": "k8s.io/api/apps/v1beta1", 290 | "Comment": "kubernetes-1.9.3-beta.0", 291 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 292 | }, 293 | { 294 | "ImportPath": "k8s.io/api/apps/v1beta2", 295 | "Comment": "kubernetes-1.9.3-beta.0", 296 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 297 | }, 298 | { 299 | "ImportPath": "k8s.io/api/authentication/v1", 300 | "Comment": "kubernetes-1.9.3-beta.0", 301 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 302 | }, 303 | { 304 | "ImportPath": "k8s.io/api/authentication/v1beta1", 305 | "Comment": "kubernetes-1.9.3-beta.0", 306 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 307 | }, 308 | { 309 | "ImportPath": "k8s.io/api/authorization/v1", 310 | "Comment": "kubernetes-1.9.3-beta.0", 311 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 312 | }, 313 | { 314 | "ImportPath": "k8s.io/api/authorization/v1beta1", 315 | "Comment": "kubernetes-1.9.3-beta.0", 316 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 317 | }, 318 | { 319 | "ImportPath": "k8s.io/api/autoscaling/v1", 320 | "Comment": "kubernetes-1.9.3-beta.0", 321 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 322 | }, 323 | { 324 | "ImportPath": "k8s.io/api/autoscaling/v2beta1", 325 | "Comment": "kubernetes-1.9.3-beta.0", 326 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 327 | }, 328 | { 329 | "ImportPath": "k8s.io/api/batch/v1", 330 | "Comment": "kubernetes-1.9.3-beta.0", 331 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 332 | }, 333 | { 334 | "ImportPath": "k8s.io/api/batch/v1beta1", 335 | "Comment": "kubernetes-1.9.3-beta.0", 336 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 337 | }, 338 | { 339 | "ImportPath": "k8s.io/api/batch/v2alpha1", 340 | "Comment": "kubernetes-1.9.3-beta.0", 341 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 342 | }, 343 | { 344 | "ImportPath": "k8s.io/api/certificates/v1beta1", 345 | "Comment": "kubernetes-1.9.3-beta.0", 346 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 347 | }, 348 | { 349 | "ImportPath": "k8s.io/api/core/v1", 350 | "Comment": "kubernetes-1.9.3-beta.0", 351 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 352 | }, 353 | { 354 | "ImportPath": "k8s.io/api/events/v1beta1", 355 | "Comment": "kubernetes-1.9.3-beta.0", 356 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 357 | }, 358 | { 359 | "ImportPath": "k8s.io/api/extensions/v1beta1", 360 | "Comment": "kubernetes-1.9.3-beta.0", 361 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 362 | }, 363 | { 364 | "ImportPath": "k8s.io/api/networking/v1", 365 | "Comment": "kubernetes-1.9.3-beta.0", 366 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 367 | }, 368 | { 369 | "ImportPath": "k8s.io/api/policy/v1beta1", 370 | "Comment": "kubernetes-1.9.3-beta.0", 371 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 372 | }, 373 | { 374 | "ImportPath": "k8s.io/api/rbac/v1", 375 | "Comment": "kubernetes-1.9.3-beta.0", 376 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 377 | }, 378 | { 379 | "ImportPath": "k8s.io/api/rbac/v1alpha1", 380 | "Comment": "kubernetes-1.9.3-beta.0", 381 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 382 | }, 383 | { 384 | "ImportPath": "k8s.io/api/rbac/v1beta1", 385 | "Comment": "kubernetes-1.9.3-beta.0", 386 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 387 | }, 388 | { 389 | "ImportPath": "k8s.io/api/scheduling/v1alpha1", 390 | "Comment": "kubernetes-1.9.3-beta.0", 391 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 392 | }, 393 | { 394 | "ImportPath": "k8s.io/api/settings/v1alpha1", 395 | "Comment": "kubernetes-1.9.3-beta.0", 396 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 397 | }, 398 | { 399 | "ImportPath": "k8s.io/api/storage/v1", 400 | "Comment": "kubernetes-1.9.3-beta.0", 401 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 402 | }, 403 | { 404 | "ImportPath": "k8s.io/api/storage/v1alpha1", 405 | "Comment": "kubernetes-1.9.3-beta.0", 406 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 407 | }, 408 | { 409 | "ImportPath": "k8s.io/api/storage/v1beta1", 410 | "Comment": "kubernetes-1.9.3-beta.0", 411 | "Rev": "006a217681ae70cbacdd66a5e2fca1a61a8ff28e" 412 | }, 413 | { 414 | "ImportPath": "k8s.io/apimachinery/pkg/api/errors", 415 | "Comment": "kubernetes-1.9.3-beta.0", 416 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 417 | }, 418 | { 419 | "ImportPath": "k8s.io/apimachinery/pkg/api/meta", 420 | "Comment": "kubernetes-1.9.3-beta.0", 421 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 422 | }, 423 | { 424 | "ImportPath": "k8s.io/apimachinery/pkg/api/resource", 425 | "Comment": "kubernetes-1.9.3-beta.0", 426 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 427 | }, 428 | { 429 | "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", 430 | "Comment": "kubernetes-1.9.3-beta.0", 431 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 432 | }, 433 | { 434 | "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", 435 | "Comment": "kubernetes-1.9.3-beta.0", 436 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 437 | }, 438 | { 439 | "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1alpha1", 440 | "Comment": "kubernetes-1.9.3-beta.0", 441 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 442 | }, 443 | { 444 | "ImportPath": "k8s.io/apimachinery/pkg/conversion", 445 | "Comment": "kubernetes-1.9.3-beta.0", 446 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 447 | }, 448 | { 449 | "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", 450 | "Comment": "kubernetes-1.9.3-beta.0", 451 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 452 | }, 453 | { 454 | "ImportPath": "k8s.io/apimachinery/pkg/fields", 455 | "Comment": "kubernetes-1.9.3-beta.0", 456 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 457 | }, 458 | { 459 | "ImportPath": "k8s.io/apimachinery/pkg/labels", 460 | "Comment": "kubernetes-1.9.3-beta.0", 461 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 462 | }, 463 | { 464 | "ImportPath": "k8s.io/apimachinery/pkg/runtime", 465 | "Comment": "kubernetes-1.9.3-beta.0", 466 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 467 | }, 468 | { 469 | "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", 470 | "Comment": "kubernetes-1.9.3-beta.0", 471 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 472 | }, 473 | { 474 | "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", 475 | "Comment": "kubernetes-1.9.3-beta.0", 476 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 477 | }, 478 | { 479 | "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", 480 | "Comment": "kubernetes-1.9.3-beta.0", 481 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 482 | }, 483 | { 484 | "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", 485 | "Comment": "kubernetes-1.9.3-beta.0", 486 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 487 | }, 488 | { 489 | "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", 490 | "Comment": "kubernetes-1.9.3-beta.0", 491 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 492 | }, 493 | { 494 | "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming", 495 | "Comment": "kubernetes-1.9.3-beta.0", 496 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 497 | }, 498 | { 499 | "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", 500 | "Comment": "kubernetes-1.9.3-beta.0", 501 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 502 | }, 503 | { 504 | "ImportPath": "k8s.io/apimachinery/pkg/selection", 505 | "Comment": "kubernetes-1.9.3-beta.0", 506 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 507 | }, 508 | { 509 | "ImportPath": "k8s.io/apimachinery/pkg/types", 510 | "Comment": "kubernetes-1.9.3-beta.0", 511 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 512 | }, 513 | { 514 | "ImportPath": "k8s.io/apimachinery/pkg/util/clock", 515 | "Comment": "kubernetes-1.9.3-beta.0", 516 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 517 | }, 518 | { 519 | "ImportPath": "k8s.io/apimachinery/pkg/util/errors", 520 | "Comment": "kubernetes-1.9.3-beta.0", 521 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 522 | }, 523 | { 524 | "ImportPath": "k8s.io/apimachinery/pkg/util/framer", 525 | "Comment": "kubernetes-1.9.3-beta.0", 526 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 527 | }, 528 | { 529 | "ImportPath": "k8s.io/apimachinery/pkg/util/intstr", 530 | "Comment": "kubernetes-1.9.3-beta.0", 531 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 532 | }, 533 | { 534 | "ImportPath": "k8s.io/apimachinery/pkg/util/json", 535 | "Comment": "kubernetes-1.9.3-beta.0", 536 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 537 | }, 538 | { 539 | "ImportPath": "k8s.io/apimachinery/pkg/util/net", 540 | "Comment": "kubernetes-1.9.3-beta.0", 541 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 542 | }, 543 | { 544 | "ImportPath": "k8s.io/apimachinery/pkg/util/runtime", 545 | "Comment": "kubernetes-1.9.3-beta.0", 546 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 547 | }, 548 | { 549 | "ImportPath": "k8s.io/apimachinery/pkg/util/sets", 550 | "Comment": "kubernetes-1.9.3-beta.0", 551 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 552 | }, 553 | { 554 | "ImportPath": "k8s.io/apimachinery/pkg/util/validation", 555 | "Comment": "kubernetes-1.9.3-beta.0", 556 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 557 | }, 558 | { 559 | "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", 560 | "Comment": "kubernetes-1.9.3-beta.0", 561 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 562 | }, 563 | { 564 | "ImportPath": "k8s.io/apimachinery/pkg/util/wait", 565 | "Comment": "kubernetes-1.9.3-beta.0", 566 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 567 | }, 568 | { 569 | "ImportPath": "k8s.io/apimachinery/pkg/util/yaml", 570 | "Comment": "kubernetes-1.9.3-beta.0", 571 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 572 | }, 573 | { 574 | "ImportPath": "k8s.io/apimachinery/pkg/version", 575 | "Comment": "kubernetes-1.9.3-beta.0", 576 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 577 | }, 578 | { 579 | "ImportPath": "k8s.io/apimachinery/pkg/watch", 580 | "Comment": "kubernetes-1.9.3-beta.0", 581 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 582 | }, 583 | { 584 | "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", 585 | "Comment": "kubernetes-1.9.3-beta.0", 586 | "Rev": "68f9c3a1feb3140df59c67ced62d3a5df8e6c9c2" 587 | }, 588 | { 589 | "ImportPath": "k8s.io/client-go/discovery", 590 | "Comment": "kubernetes-1.9.4-beta.0", 591 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 592 | }, 593 | { 594 | "ImportPath": "k8s.io/client-go/kubernetes", 595 | "Comment": "kubernetes-1.9.4-beta.0", 596 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 597 | }, 598 | { 599 | "ImportPath": "k8s.io/client-go/kubernetes/scheme", 600 | "Comment": "kubernetes-1.9.4-beta.0", 601 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 602 | }, 603 | { 604 | "ImportPath": "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1", 605 | "Comment": "kubernetes-1.9.4-beta.0", 606 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 607 | }, 608 | { 609 | "ImportPath": "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1", 610 | "Comment": "kubernetes-1.9.4-beta.0", 611 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 612 | }, 613 | { 614 | "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1", 615 | "Comment": "kubernetes-1.9.4-beta.0", 616 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 617 | }, 618 | { 619 | "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1beta1", 620 | "Comment": "kubernetes-1.9.4-beta.0", 621 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 622 | }, 623 | { 624 | "ImportPath": "k8s.io/client-go/kubernetes/typed/apps/v1beta2", 625 | "Comment": "kubernetes-1.9.4-beta.0", 626 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 627 | }, 628 | { 629 | "ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1", 630 | "Comment": "kubernetes-1.9.4-beta.0", 631 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 632 | }, 633 | { 634 | "ImportPath": "k8s.io/client-go/kubernetes/typed/authentication/v1beta1", 635 | "Comment": "kubernetes-1.9.4-beta.0", 636 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 637 | }, 638 | { 639 | "ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1", 640 | "Comment": "kubernetes-1.9.4-beta.0", 641 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 642 | }, 643 | { 644 | "ImportPath": "k8s.io/client-go/kubernetes/typed/authorization/v1beta1", 645 | "Comment": "kubernetes-1.9.4-beta.0", 646 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 647 | }, 648 | { 649 | "ImportPath": "k8s.io/client-go/kubernetes/typed/autoscaling/v1", 650 | "Comment": "kubernetes-1.9.4-beta.0", 651 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 652 | }, 653 | { 654 | "ImportPath": "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1", 655 | "Comment": "kubernetes-1.9.4-beta.0", 656 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 657 | }, 658 | { 659 | "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v1", 660 | "Comment": "kubernetes-1.9.4-beta.0", 661 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 662 | }, 663 | { 664 | "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v1beta1", 665 | "Comment": "kubernetes-1.9.4-beta.0", 666 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 667 | }, 668 | { 669 | "ImportPath": "k8s.io/client-go/kubernetes/typed/batch/v2alpha1", 670 | "Comment": "kubernetes-1.9.4-beta.0", 671 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 672 | }, 673 | { 674 | "ImportPath": "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", 675 | "Comment": "kubernetes-1.9.4-beta.0", 676 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 677 | }, 678 | { 679 | "ImportPath": "k8s.io/client-go/kubernetes/typed/core/v1", 680 | "Comment": "kubernetes-1.9.4-beta.0", 681 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 682 | }, 683 | { 684 | "ImportPath": "k8s.io/client-go/kubernetes/typed/events/v1beta1", 685 | "Comment": "kubernetes-1.9.4-beta.0", 686 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 687 | }, 688 | { 689 | "ImportPath": "k8s.io/client-go/kubernetes/typed/extensions/v1beta1", 690 | "Comment": "kubernetes-1.9.4-beta.0", 691 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 692 | }, 693 | { 694 | "ImportPath": "k8s.io/client-go/kubernetes/typed/networking/v1", 695 | "Comment": "kubernetes-1.9.4-beta.0", 696 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 697 | }, 698 | { 699 | "ImportPath": "k8s.io/client-go/kubernetes/typed/policy/v1beta1", 700 | "Comment": "kubernetes-1.9.4-beta.0", 701 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 702 | }, 703 | { 704 | "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1", 705 | "Comment": "kubernetes-1.9.4-beta.0", 706 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 707 | }, 708 | { 709 | "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1", 710 | "Comment": "kubernetes-1.9.4-beta.0", 711 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 712 | }, 713 | { 714 | "ImportPath": "k8s.io/client-go/kubernetes/typed/rbac/v1beta1", 715 | "Comment": "kubernetes-1.9.4-beta.0", 716 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 717 | }, 718 | { 719 | "ImportPath": "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", 720 | "Comment": "kubernetes-1.9.4-beta.0", 721 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 722 | }, 723 | { 724 | "ImportPath": "k8s.io/client-go/kubernetes/typed/settings/v1alpha1", 725 | "Comment": "kubernetes-1.9.4-beta.0", 726 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 727 | }, 728 | { 729 | "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1", 730 | "Comment": "kubernetes-1.9.4-beta.0", 731 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 732 | }, 733 | { 734 | "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1alpha1", 735 | "Comment": "kubernetes-1.9.4-beta.0", 736 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 737 | }, 738 | { 739 | "ImportPath": "k8s.io/client-go/kubernetes/typed/storage/v1beta1", 740 | "Comment": "kubernetes-1.9.4-beta.0", 741 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 742 | }, 743 | { 744 | "ImportPath": "k8s.io/client-go/pkg/version", 745 | "Comment": "kubernetes-1.9.4-beta.0", 746 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 747 | }, 748 | { 749 | "ImportPath": "k8s.io/client-go/rest", 750 | "Comment": "kubernetes-1.9.4-beta.0", 751 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 752 | }, 753 | { 754 | "ImportPath": "k8s.io/client-go/rest/watch", 755 | "Comment": "kubernetes-1.9.4-beta.0", 756 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 757 | }, 758 | { 759 | "ImportPath": "k8s.io/client-go/tools/auth", 760 | "Comment": "kubernetes-1.9.4-beta.0", 761 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 762 | }, 763 | { 764 | "ImportPath": "k8s.io/client-go/tools/clientcmd", 765 | "Comment": "kubernetes-1.9.4-beta.0", 766 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 767 | }, 768 | { 769 | "ImportPath": "k8s.io/client-go/tools/clientcmd/api", 770 | "Comment": "kubernetes-1.9.4-beta.0", 771 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 772 | }, 773 | { 774 | "ImportPath": "k8s.io/client-go/tools/clientcmd/api/latest", 775 | "Comment": "kubernetes-1.9.4-beta.0", 776 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 777 | }, 778 | { 779 | "ImportPath": "k8s.io/client-go/tools/clientcmd/api/v1", 780 | "Comment": "kubernetes-1.9.4-beta.0", 781 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 782 | }, 783 | { 784 | "ImportPath": "k8s.io/client-go/tools/metrics", 785 | "Comment": "kubernetes-1.9.4-beta.0", 786 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 787 | }, 788 | { 789 | "ImportPath": "k8s.io/client-go/tools/reference", 790 | "Comment": "kubernetes-1.9.4-beta.0", 791 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 792 | }, 793 | { 794 | "ImportPath": "k8s.io/client-go/transport", 795 | "Comment": "kubernetes-1.9.4-beta.0", 796 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 797 | }, 798 | { 799 | "ImportPath": "k8s.io/client-go/util/cert", 800 | "Comment": "kubernetes-1.9.4-beta.0", 801 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 802 | }, 803 | { 804 | "ImportPath": "k8s.io/client-go/util/flowcontrol", 805 | "Comment": "kubernetes-1.9.4-beta.0", 806 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 807 | }, 808 | { 809 | "ImportPath": "k8s.io/client-go/util/homedir", 810 | "Comment": "kubernetes-1.9.4-beta.0", 811 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 812 | }, 813 | { 814 | "ImportPath": "k8s.io/client-go/util/integer", 815 | "Comment": "kubernetes-1.9.4-beta.0", 816 | "Rev": "9389c055a838d4f208b699b3c7c51b70f2368861" 817 | }, 818 | { 819 | "ImportPath": "k8s.io/kube-openapi/pkg/common", 820 | "Rev": "39a7bf85c140f972372c2a0d1ee40adbf0c8bfe1" 821 | } 822 | ] 823 | } 824 | -------------------------------------------------------------------------------- /Godeps/Readme: -------------------------------------------------------------------------------- 1 | This directory tree is generated automatically by godep. 2 | 3 | Please do not edit. 4 | 5 | See https://github.com/tools/godep for more information. 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # k8s api代理 2 | 3 | > 这是一个封装了原生k8s api的代理. 4 | 5 | ### 使用说明 6 | 7 | 1. 把k8s认证的.kube/config文件放到app/config位置 8 | 2. 安装godep: `go get github.com/tools/godep` 9 | 3. 安装go依赖: `godep restore` 10 | 4. 运行: `bee run -gendoc=true -downdoc=true` 11 | 5. 界面查看接口: `http://:8080/swagger/` 12 | -------------------------------------------------------------------------------- /client/k8s.go: -------------------------------------------------------------------------------- 1 | package client 2 | 3 | import ( 4 | "flag" 5 | "k8s.io/client-go/kubernetes" 6 | "k8s.io/client-go/tools/clientcmd" 7 | ) 8 | 9 | func NewK8sClient() *kubernetes.Clientset { 10 | var kubeconfig *string 11 | kubeconfig = flag.String("kubeconfig", "conf/config", "(optional) absolute path to the kubeconfig file") 12 | flag.Parse() 13 | 14 | config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig) 15 | if err != nil { 16 | panic(err) 17 | } 18 | clientset, err := kubernetes.NewForConfig(config) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | return clientset 24 | } 25 | 26 | var K8sDefaultClient = NewK8sClient() 27 | -------------------------------------------------------------------------------- /conf/app.conf: -------------------------------------------------------------------------------- 1 | appname = ice 2 | httpport = 8080 3 | runmode = dev 4 | autorender = false 5 | copyrequestbody = true 6 | EnableDocs = true 7 | -------------------------------------------------------------------------------- /conf/config: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | clusters: 3 | - cluster: 4 | certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUR1RENDQXFDZ0F3SUJBZ0lVSGlOamREQXhrRjhCaGFleWRIV0J2RjZ0eHRVd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1lqRUxNQWtHQTFVRUJoTUNRMDR4RWpBUUJnTlZCQWdUQ1VkMVlXNW5SRzl1WnpFTE1Ba0dBMVVFQnhNQwpVMW94RERBS0JnTlZCQW9UQTJzNGN6RVBNQTBHQTFVRUN4TUdVM2x6ZEdWdE1STXdFUVlEVlFRREV3cHJkV0psCmNtNWxkR1Z6TUI0WERURTRNRE13TXpFMk1qRXdNRm9YRFRJek1ETXdNakUyTWpFd01Gb3dZakVMTUFrR0ExVUUKQmhNQ1EwNHhFakFRQmdOVkJBZ1RDVWQxWVc1blJHOXVaekVMTUFrR0ExVUVCeE1DVTFveEREQUtCZ05WQkFvVApBMnM0Y3pFUE1BMEdBMVVFQ3hNR1UzbHpkR1Z0TVJNd0VRWURWUVFERXdwcmRXSmxjbTVsZEdWek1JSUJJakFOCkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXlsMEt0SjJWSmg0RVZ6V3MrU290UytNUlZhMXcKWkVjRWNmeDUzckc5dGM2WlhVZ0xESXNyT3BodWZSS204NFd0Nk9NS0I2NDFTa3UyZ0w0dzlJc3FhTVJIZlB1OAp6d0FucmJ2RnNvZk12YkZGM0NBbVRzRUZCNjlPWnZEYnhmS3JkWnNzSkhrTEozKzdtRHhBT1k2QmlPK1YwYkxXCkYwSi9UWC9CZ0R4NE9DM0JlR05OcjhmZElWcnpQRTBmUkVzS1JZM1VCWnB0aGVXNGY1bVlQK1JNSDFmckcvcmcKVG1EVzdEVTlxR1NaZEgrT2hQeVZOSGRhWWlsbGthQk52Qjl6Z0dVak5VK0IrRjJVMVo4YzB5SExjZXJtTVl4cQphWCt3NmxuSEpKZi9EQXVDcDdIQ2Vxb2hkZWUreElzZjAvSHk4SUtTcCtmRlZtck1uVWQxbldYcWVRSURBUUFCCm8yWXdaREFPQmdOVkhROEJBZjhFQkFNQ0FRWXdFZ1lEVlIwVEFRSC9CQWd3QmdFQi93SUJBakFkQmdOVkhRNEUKRmdRVXI5YU5LVVlPdE5uUmlUbklidU9xTXZ2WGp2Z3dId1lEVlIwakJCZ3dGb0FVcjlhTktVWU90Tm5SaVRuSQpidU9xTXZ2WGp2Z3dEUVlKS29aSWh2Y05BUUVMQlFBRGdnRUJBQVB5Y0lUVGtwbTlJeGFYSWJ2S2JUUzZEVlNmCmlIMDhxcHFuaGxFbEZoc2tIc3VpUFRhNnc2UEVhdHg1RjdSVnVNTmNBcHduNHZvT05NNWJGcFcxTE9NS0JTalEKNWxuVFppaHRxWmtqQXlyNjdHOGpVNFRyblhORXM2UHp0VzNZdFF5T3p5WGNQMFFVczZvYnpRL3RZOUlERm0rUwoyZWoyVno0UVNFVlhwdU5JMUpDbWtoNWhWWU90Y29TcWJLbGJmVFpSUDk0Z2F6ZW5QQWM0ZCt6OGtyWHRiSkV2CmtMZmh3bDBEZ09UMERCWmlXNURaMUhkUGlLOTN6V3RIQnQ4cFVobS9LdWV6dkZTbXlmSzV6M05QTlJ1WnlDTCsKazl3VkVHSjM1SVRVSmdZWGVLV0x4UWEvT2xjT0U1ZVlsODVGd2RZTHp6N2RUdlhiN0hqeVc3WXd4Y1E9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K 5 | server: https://172.16.28.58:8443 6 | name: kubernetes 7 | contexts: 8 | - context: 9 | cluster: kubernetes 10 | user: admin 11 | name: kubernetes 12 | current-context: kubernetes 13 | kind: Config 14 | preferences: {} 15 | users: 16 | - name: admin 17 | user: 18 | as-user-extra: {} 19 | client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUQxekNDQXIrZ0F3SUJBZ0lVZExubFpkZ3Zhd29BYnMrUk1KZ1ZlYUVDbVFVd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1lqRUxNQWtHQTFVRUJoTUNRMDR4RWpBUUJnTlZCQWdUQ1VkMVlXNW5SRzl1WnpFTE1Ba0dBMVVFQnhNQwpVMW94RERBS0JnTlZCQW9UQTJzNGN6RVBNQTBHQTFVRUN4TUdVM2x6ZEdWdE1STXdFUVlEVlFRREV3cHJkV0psCmNtNWxkR1Z6TUI0WERURTRNRE16TVRFek1qSXdNRm9YRFRJNE1ETXlPREV6TWpJd01Gb3dhREVMTUFrR0ExVUUKQmhNQ1EwNHhFakFRQmdOVkJBZ1RDVWQxWVc1blJHOXVaekVMTUFrR0ExVUVCeE1DVTFveEZ6QVZCZ05WQkFvVApEbk41YzNSbGJUcHRZWE4wWlhKek1ROHdEUVlEVlFRTEV3WlRlWE4wWlcweERqQU1CZ05WQkFNVEJXRmtiV2x1Ck1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBOUhHRm5mVFM3YzFMK2xkWllwQ0IKTnQ4VE1NZ3d2c1IzV1ZrSGxGa2V1TjEzQUI4TStvWnBqSk0wVGZZYW5JN3lxR2g2MU1MbTVEUmZaS2puV2FtZQpObG5waXczNW5pcWdIQUZscTgzcTNEMmwwWXg0ZjVvS3R6dlk5YzZ2ZmZsdGtQMkZuNERVSlZNcjI2SEpKQ2hZClo3Y2hkbG5tY0t3T2diRTgySzZ3bzJCMHhWZ3h6SDdXM2lYWmJZa29ITE5qOXgvSU5vSkt0U3RqUkl4VHBMOXMKQTFLM3UwVDd0MllsaFFHSWIvTGF6blJKUGN5WFh5QnAxNUdFcVk2OUVzU3orWi8xREVMKzZaYVV3Ry9SKzF1RQpuTjh2Q0V4QTF3TmJySSt1ay9jUnEvbWYvc2FXREk2NmdFeERmeSs3RVlYODFIa280RUNwMDdwVVZ1bUhmOGlvCkJ3SURBUUFCbzM4d2ZUQU9CZ05WSFE4QkFmOEVCQU1DQmFBd0hRWURWUjBsQkJZd0ZBWUlLd1lCQlFVSEF3RUcKQ0NzR0FRVUZCd01DTUF3R0ExVWRFd0VCL3dRQ01BQXdIUVlEVlIwT0JCWUVGTURIRDBFWk0rZTBiNTBWTnJPZgp0ZndrQ0hyaU1COEdBMVVkSXdRWU1CYUFGSy9XalNsR0RyVFowWWs1eUc3anFqTDcxNDc0TUEwR0NTcUdTSWIzCkRRRUJDd1VBQTRJQkFRQWdvUGJLUkJBM1JOZzczc3g5aGtOQVY2eUJBd3Q1em1lNzFiMExXZzExY2NqL3lpd08Kc2NjaFIvZlh0QStaaFUyNUtONWs5M2I3ZzNDb0FKYjEraG03c3FuZXpwTUhYSFl1cVVhTDhDKzFMelNreW9hVwpIbnpBaWV5d01QK0JJTi9oU2IvWmxTdzhwWHU3RmFoaWw3WDlWQmVXc3lOMW9jRmRHR0E3OVB4d3RUckRrQlQ0CnBjcm9ZUEQxMHJMVERXY1dQZk4wbXZCQzhQMGRqcjhhNmtZNUZ1RDVZOE1GWE5pOW5POENMcEpJSHhQaE9IOHoKejk5bEYvZk0vVUpCS2V0ZCtaVzhEc0Jwai9jTjRiUnZoK3laYkVydDFzaENDOEU5NWhsdVFoNHErL25PeGlyRwpDK0prdzBnbXJXaGpwQjJMcmg1RkVybXRMamFBR21GeHR4WlEKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= 20 | client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBOUhHRm5mVFM3YzFMK2xkWllwQ0JOdDhUTU1nd3ZzUjNXVmtIbEZrZXVOMTNBQjhNCitvWnBqSk0wVGZZYW5JN3lxR2g2MU1MbTVEUmZaS2puV2FtZU5sbnBpdzM1bmlxZ0hBRmxxODNxM0QybDBZeDQKZjVvS3R6dlk5YzZ2ZmZsdGtQMkZuNERVSlZNcjI2SEpKQ2hZWjdjaGRsbm1jS3dPZ2JFODJLNndvMkIweFZneAp6SDdXM2lYWmJZa29ITE5qOXgvSU5vSkt0U3RqUkl4VHBMOXNBMUszdTBUN3QyWWxoUUdJYi9MYXpuUkpQY3lYClh5QnAxNUdFcVk2OUVzU3orWi8xREVMKzZaYVV3Ry9SKzF1RW5OOHZDRXhBMXdOYnJJK3VrL2NScS9tZi9zYVcKREk2NmdFeERmeSs3RVlYODFIa280RUNwMDdwVVZ1bUhmOGlvQndJREFRQUJBb0lCQUNhRHRIL2MwVmN5bjZRRQpHMHRTWldtVjRGb3hVS3plRzhmeUpTV1VuU2lYakdaeWZnTURKcUpGbDFvcFNxd2NRZE9URXJkdk5oNEN1bjBMCnQ5Z0N4N0RjbmRXUkVDR0JxZFIveTlzMENLdEc4MWQvQUlWcWFnSFE1akJrcm5YMDFQU2hYV3B5Uy9yTmpmMS8KRWtnbUt6ZThQUU4reXJZNkJkY2RhKzdnSjJpMlBSZXdTMUlzTEtyQW5DYTVYV1Fnc2h0QnJVbnRlRHFiQldoLwpFNlF0bnZVS3doaDBlcm5OcVhOc1VzeTM4a3doeGNQaHlhY0FkcXI5N045WFQwdVprNXdiRTJRWEcyWHhrTXRaCkF6Z0xxcFZOYUJETXhCN0pXVmRRSmRidUcvUlpTVXc0QzEvbVYvTThQZEg5SzZpeVVNNXBhRnZnaHZjTGtqUm8KS05UNTBJRUNnWUVBL3ZlQ21BV0lrZDZJNHRFTm90dTdVZjhLbHo3bVh4Q1pvQTdsSFc4MEJMZTArMlBBTDM3SQorajRDMUJjVmdiNXMxaVFqaUo0VTR1ZXJYaS9PQXJGZEdNUjZYSFQ5VkxrT0FLeks0U3dsT2RlL0VjTkF6bXEyClQrTmtFcy9jd0NXako5MkhkOVlnNDVYeHFWSDBFRE9OL1cvTVQwcHd6dzNocVpGblF5ZWpVU2NDZ1lFQTlXOFkKYWhEMEJIZWZrYUJEU2paYkllTDNMZ0NENnd2RmVsVnNtYjNxN0VNWVJ6SUU4U2RtR2FYei9TalpaOVlwMEVhKwpNUmlPb2w3TmdyZ2YzUGVmRDNCN1BVZFV3RHB0SS9JVXZOSFJiR25LOGdjWUhoZXN5ZXdqc2pOZW4yakJWS1BxClk4ZWQ0OFNkdGxXZWZ3blowRVZWUkNoMVMwbmZ4ckFIdHhvbWZpRUNnWUVBa1RqSTJXM05hOGdrajR3akNDKy8KY2VTaVU2TXY4OVd3cXNuUkZnTFF6aDhVcGxzYWkvTGE1aTJMenVHWERsODMvb0IyL01tTmUvQVlXMzAvQ2FtYwpMUTg3NG8xLy9WR3ArQmh6TmUyL0JrTXNRU0hGTjh6d0tuQ0ovMjBGZnl2dzBqUUxoT1lodFg4aU5oN0h0TEtvCm5VR2dUVWxKRjZZQWNtU3ZQRURIZE9FQ2dZQm1TeloreHJBZHlJbnVWVUNXaHM4MjhYVWFiRWFQU2FtMkVqS2cKWllLcmxFOWpKUnJnTkE2ZTlBY2NaZEV2TVJqZVlRM1dRcWo0VGRFVUFZL3VOaHJLZ1pRcjl6WUFwSmxtbVBoQgp0cVcxck9aVU45YTZmQjJkVDFtVlpVbXo0U0pyRjZLU2tkbGgzRW5yZkFZQ1p1V3NvNmtsTGtPczdJNWpMbTBZCnlNSndZUUtCZ0Y0WndsRVZTQUwzTklTUEdZNnZnL2lFK3FYdVYwTU9uRVlqV05NTStnaGZtb3VpS2JLb0hwbTcKUkYvNklxUGNST01wZ1pNcVZHaUpOb3RCUEVER05oNzJuZFZEL0s4djdxS2xqa2VRdVIxR0p4V3NpQ3hBVm5YagphSExWQ2JXU0VtOVFacFN6WkYxaHJwK25vZk11TEwySUVrMDhFOHluTEt6amFnb0gxNmFUCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== 21 | -------------------------------------------------------------------------------- /controllers/app.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/astaxie/beego" 7 | "github.com/astaxie/beego/logs" 8 | "github.com/yaoice/ice/models" 9 | ) 10 | 11 | // Operations about app 12 | type AppsController struct { 13 | beego.Controller 14 | } 15 | 16 | // @Title Create 17 | // @Description create new app 18 | // @Param project path string true "The project you want to get" 19 | // @Param body body models.App true "The app content" 20 | // @Success 200 {app} models.App.AppName 21 | // @Failure 400 :body is empty 22 | // @router / [post] 23 | func (this *AppsController) Post() { 24 | var app models.App 25 | project := this.GetString(":project") 26 | json.Unmarshal(this.Ctx.Input.RequestBody, &app) 27 | result, err := models.CreateApp(project, &app) 28 | if err != nil { 29 | logs.Error("create app %s response err: %v", app.AppName, err) 30 | this.Ctx.Output.SetStatus(400) 31 | this.Data["json"] = err 32 | } else { 33 | this.Data["json"] = result 34 | } 35 | this.ServeJSON() 36 | } 37 | 38 | // @Title Get 39 | // @Description get app by appname 40 | // @Param project path string true "The project you want to get" 41 | // @Param appName path string true "The appname you want to get" 42 | // @Success 200 {app} models.App 43 | // @Failure 400 :appName is empty 44 | // @router /:appName [get] 45 | func (this *AppsController) Get() { 46 | project := this.GetString(":project") 47 | appName := this.GetString(":appName") 48 | app, err := models.GetApp(project, appName) 49 | if err != nil { 50 | logs.Error("get app %s response err: %v", appName, err) 51 | this.Ctx.Output.SetStatus(400) 52 | this.Data["json"] = err 53 | } else { 54 | this.Data["json"] = app 55 | } 56 | this.ServeJSON() 57 | } 58 | 59 | // @Title GetAll 60 | // @Description get all apps 61 | // @Param project path string true "The project you want to get" 62 | // @Success 200 {app} models.App 63 | // @Failure 400 :appName is empty 64 | // @router / [get] 65 | func (this *AppsController) GetAll() { 66 | project := this.GetString(":project") 67 | apps, err := models.GetAllApp(project) 68 | if err != nil { 69 | logs.Error("get all app response err: %v", err) 70 | this.Data["json"] = err 71 | } else { 72 | this.Data["json"] = apps 73 | } 74 | this.ServeJSON() 75 | } 76 | 77 | /* 78 | // @Title Update 79 | // @Description update app by appname 80 | // @Param project path string true "The project you want to get" 81 | // @Param appName path string true "The app you want to update" 82 | // @Param body body models.App true "The body" 83 | // @Success 200 {app} models.App 84 | // @Failure 400 :appName is empty 85 | // @router /:appName [put] 86 | func (this *AppsController) Put() { 87 | 88 | } 89 | */ 90 | 91 | // @Title Delete 92 | // @Description delete app by appname 93 | // @Param project path string true "The project you want to get" 94 | // @Param appName path string true "The app you want to delete" 95 | // @Success 200 {app} models.App 96 | // @Failure 400 :appName is empty 97 | // @router /:appName [delete] 98 | func (this *AppsController) Delete() { 99 | project := this.GetString(":project") 100 | appName := this.GetString(":appName") 101 | err := models.DeleteApp(project, appName) 102 | if err != nil { 103 | logs.Error("delete app %s response err: %v", appName, err) 104 | this.Ctx.Output.SetStatus(400) 105 | this.Data["json"] = err 106 | } else { 107 | s := fmt.Sprintf("delete app %s success!", appName) 108 | this.Data["json"] = s 109 | } 110 | this.ServeJSON() 111 | } 112 | -------------------------------------------------------------------------------- /controllers/flavor.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | ) 6 | 7 | // Operations about flavor 8 | type FlavorsController struct { 9 | beego.Controller 10 | } 11 | -------------------------------------------------------------------------------- /controllers/image.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | ) 6 | 7 | // Operations about image 8 | type ImagesController struct { 9 | beego.Controller 10 | } 11 | -------------------------------------------------------------------------------- /controllers/ingress.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/astaxie/beego" 7 | "github.com/astaxie/beego/logs" 8 | "github.com/yaoice/ice/models" 9 | ) 10 | 11 | // Operations about ingress 12 | type IngressesController struct { 13 | beego.Controller 14 | } 15 | 16 | // @Title Create 17 | // @Description create new ingress 18 | // @Param project path string true "The project you want to get" 19 | // @Param body body models.Ingress true "The ingress content" 20 | // @Success 200 {app} models.Ingress 21 | // @Failure 400 :body is empty 22 | // @router / [post] 23 | func (this *IngressesController) Post() { 24 | var ingress models.Ingress 25 | project := this.GetString(":project") 26 | json.Unmarshal(this.Ctx.Input.RequestBody, &ingress) 27 | result, err := models.CreateIngress(project, &ingress) 28 | if err != nil { 29 | logs.Error("create ingress %s response err: %v", ingress.AppName, err) 30 | this.Ctx.Output.SetStatus(400) 31 | this.Data["json"] = err 32 | } else { 33 | this.Data["json"] = result 34 | } 35 | this.ServeJSON() 36 | } 37 | 38 | // @Title Get 39 | // @Description get ingress by name 40 | // @Param project path string true "The project you want to get" 41 | // @Param ingressName path string true "The ingress you want to get" 42 | // @Success 200 {ingress} models.Ingress 43 | // @Failure 400 :ingressName is empty 44 | // @router /:ingressName [get] 45 | func (this *IngressesController) Get() { 46 | project := this.GetString(":project") 47 | ingressName := this.GetString(":ingressName") 48 | ingress, err := models.GetIngress(project, ingressName) 49 | if err != nil { 50 | logs.Error("get ingress %s response err: %v", ingressName, err) 51 | this.Ctx.Output.SetStatus(400) 52 | this.Data["json"] = err 53 | } else { 54 | this.Data["json"] = ingress 55 | } 56 | this.ServeJSON() 57 | } 58 | 59 | // @Title Delete 60 | // @Description delete ingress by name 61 | // @Param project path string true "The project you want to get" 62 | // @Param ingressName path string true "The ingress you want to delete" 63 | // @Success 200 {ingress} models.Ingress 64 | // @Failure 400 :ingressName is empty 65 | // @router /:ingressName [delete] 66 | func (this *IngressesController) Delete() { 67 | project := this.GetString(":project") 68 | ingressName := this.GetString(":ingressName") 69 | err := models.DeleteIngress(project, ingressName) 70 | if err != nil { 71 | logs.Error("delete ingress %s response err: %v", ingressName, err) 72 | this.Ctx.Output.SetStatus(400) 73 | this.Data["json"] = err 74 | } else { 75 | s := fmt.Sprintf("delete ingress %s success!", ingressName) 76 | this.Data["json"] = s 77 | } 78 | this.ServeJSON() 79 | } 80 | -------------------------------------------------------------------------------- /controllers/project.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | ) 6 | 7 | // Operations about project 8 | type ProjectsController struct { 9 | beego.Controller 10 | } 11 | -------------------------------------------------------------------------------- /controllers/service.go: -------------------------------------------------------------------------------- 1 | package controllers 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "github.com/astaxie/beego" 7 | "github.com/astaxie/beego/logs" 8 | "github.com/yaoice/ice/models" 9 | ) 10 | 11 | // Operations about service 12 | type ServicesController struct { 13 | beego.Controller 14 | } 15 | 16 | // @Title Create 17 | // @Description create new service 18 | // @Param project path string true "The project you want to get" 19 | // @Param body body models.Service true "The service content" 20 | // @Success 200 {service} models.Service 21 | // @Failure 400 :body is empty 22 | // @router / [post] 23 | func (this *ServicesController) Post() { 24 | var service models.Service 25 | project := this.GetString(":project") 26 | json.Unmarshal(this.Ctx.Input.RequestBody, &service) 27 | result, err := models.CreateService(project, &service) 28 | if err != nil { 29 | logs.Error("create service %s response err: %v", service.AppName, err) 30 | this.Ctx.Output.SetStatus(400) 31 | this.Data["json"] = err 32 | } else { 33 | this.Data["json"] = result 34 | } 35 | this.ServeJSON() 36 | } 37 | 38 | // @Title Get 39 | // @Description get service by name 40 | // @Param project path string true "The project you want to get" 41 | // @Param serviceName path string true "The service you want to get" 42 | // @Success 200 {service} models.Service 43 | // @Failure 400 :serviceName is empty 44 | // @router /:serviceName [get] 45 | func (this *ServicesController) Get() { 46 | project := this.GetString(":project") 47 | serviceName := this.GetString(":serviceName") 48 | service, err := models.GetService(project, serviceName) 49 | if err != nil { 50 | logs.Error("get service %s response err: %v", serviceName, err) 51 | this.Ctx.Output.SetStatus(400) 52 | this.Data["json"] = err 53 | } else { 54 | this.Data["json"] = service 55 | } 56 | this.ServeJSON() 57 | } 58 | 59 | // @Title Delete 60 | // @Description delete service by name 61 | // @Param project path string true "The project you want to get" 62 | // @Param serviceName path string true "The service you want to delete" 63 | // @Success 200 {service} models.Service 64 | // @Failure 400 :serviceName is empty 65 | // @router /:serviceName [delete] 66 | func (this *ServicesController) Delete() { 67 | project := this.GetString(":project") 68 | serviceName := this.GetString(":serviceName") 69 | err := models.DeleteService(project, serviceName) 70 | if err != nil { 71 | logs.Error("delete service %s response err: %v", serviceName, err) 72 | this.Ctx.Output.SetStatus(400) 73 | this.Data["json"] = err 74 | } else { 75 | s := fmt.Sprintf("delete service %s success!", serviceName) 76 | this.Data["json"] = s 77 | } 78 | this.ServeJSON() 79 | } 80 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "github.com/yaoice/ice/routers" 5 | 6 | "github.com/astaxie/beego" 7 | ) 8 | 9 | func main() { 10 | if beego.BConfig.RunMode == "dev" { 11 | beego.BConfig.WebConfig.DirectoryIndex = true 12 | beego.BConfig.WebConfig.StaticDir["/swagger"] = "swagger" 13 | } 14 | beego.Run() 15 | } 16 | -------------------------------------------------------------------------------- /models/app.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "github.com/yaoice/ice/client" 5 | appsv1beta1 "k8s.io/api/apps/v1beta1" 6 | v1beta1 "k8s.io/api/apps/v1beta1" 7 | apiv1 "k8s.io/api/core/v1" 8 | "k8s.io/apimachinery/pkg/api/resource" 9 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 10 | // "github.com/astaxie/beego/logs" 11 | ) 12 | 13 | var ( 14 | clientset = client.K8sDefaultClient 15 | Flavors map[string]*Flavor 16 | ) 17 | 18 | type Flavor struct { 19 | CPU int64 20 | Memory int64 21 | EphemeralStorage int64 22 | } 23 | 24 | type App struct { 25 | AppName string 26 | Replicas int32 27 | Image string 28 | ContainerPort int32 29 | FlavorRef string 30 | } 31 | 32 | func init() { 33 | Flavors = make(map[string]*Flavor) 34 | Flavors["0"] = &Flavor{1, 1 * 1024 * 1024 * 1024, 1 * 1024 * 1024 * 1024} 35 | Flavors["1"] = &Flavor{1, 1 * 1024 * 1024 * 1024, 10 * 1024 * 1024 * 1024} 36 | Flavors["2"] = &Flavor{2, 2 * 1024 * 1024 * 1024, 20 * 1024 * 1024 * 1024} 37 | Flavors["3"] = &Flavor{4, 4 * 1024 * 1024 * 1024, 40 * 1024 * 1024 * 1024} 38 | Flavors["4"] = &Flavor{8, 8 * 1024 * 1024 * 1024, 80 * 1024 * 1024 * 1024} 39 | } 40 | 41 | func int32Ptr(i int32) *int32 { return &i } 42 | func quantity(q *resource.Quantity) resource.Quantity { return *q } 43 | 44 | func CreateApp(project string, app *App) (result *v1beta1.Deployment, err error) { 45 | deploymentsClient := clientset.AppsV1beta1().Deployments(project) 46 | deployment := &appsv1beta1.Deployment{ 47 | ObjectMeta: metav1.ObjectMeta{ 48 | Name: app.AppName, 49 | }, 50 | Spec: appsv1beta1.DeploymentSpec{ 51 | Replicas: int32Ptr(app.Replicas), 52 | Template: apiv1.PodTemplateSpec{ 53 | ObjectMeta: metav1.ObjectMeta{ 54 | Labels: map[string]string{ 55 | "app": app.AppName, 56 | }, 57 | }, 58 | Spec: apiv1.PodSpec{ 59 | Containers: []apiv1.Container{ 60 | { 61 | Name: app.AppName, 62 | Image: app.Image, 63 | Ports: []apiv1.ContainerPort{ 64 | { 65 | Name: app.AppName, 66 | Protocol: apiv1.ProtocolTCP, 67 | ContainerPort: app.ContainerPort, 68 | }, 69 | }, 70 | Resources: apiv1.ResourceRequirements{ 71 | Limits: apiv1.ResourceList{ 72 | "cpu": quantity(resource.NewQuantity( 73 | Flavors[app.FlavorRef].CPU, 74 | resource.DecimalSI, 75 | )), 76 | "memory": quantity(resource.NewQuantity( 77 | Flavors[app.FlavorRef].Memory, 78 | resource.DecimalSI, 79 | )), 80 | "ephemeral-storage": quantity(resource.NewQuantity( 81 | Flavors[app.FlavorRef].EphemeralStorage, 82 | resource.DecimalSI, 83 | )), 84 | }, 85 | }, 86 | }, 87 | }, 88 | }, 89 | }, 90 | }, 91 | } 92 | result, err = deploymentsClient.Create(deployment) 93 | return result, err 94 | } 95 | 96 | func GetApp(project string, appName string) (app *v1beta1.Deployment, err error) { 97 | deploymentsClient := clientset.AppsV1beta1().Deployments(project) 98 | app, err = deploymentsClient.Get(appName, metav1.GetOptions{}) 99 | return app, err 100 | } 101 | 102 | func GetAllApp(project string) (list *v1beta1.DeploymentList, err error) { 103 | deploymentsClient := clientset.AppsV1beta1().Deployments(project) 104 | list, err = deploymentsClient.List(metav1.ListOptions{}) 105 | return list, err 106 | } 107 | 108 | func DeleteApp(project string, appName string) (err error) { 109 | deploymentsClient := clientset.AppsV1beta1().Deployments(project) 110 | deletePolicy := metav1.DeletePropagationForeground 111 | err = deploymentsClient.Delete(appName, &metav1.DeleteOptions{ 112 | PropagationPolicy: &deletePolicy, 113 | }) 114 | return err 115 | } 116 | -------------------------------------------------------------------------------- /models/ingress.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "github.com/astaxie/beego/logs" 6 | v1beta1 "k8s.io/api/extensions/v1beta1" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | "k8s.io/client-go/kubernetes/scheme" 9 | ) 10 | 11 | type Ingress struct { 12 | AppName string 13 | Host string 14 | ServicePort int32 15 | Path string 16 | } 17 | 18 | var raw_ingressjson = ` 19 | { 20 | "apiVersion": "extensions/v1beta1", 21 | "kind": "Ingress", 22 | "metadata": { 23 | "name": "%s", 24 | "namespace": "%s" 25 | }, 26 | "spec": { 27 | "rules": [{ 28 | "host": "%s", 29 | "http": { 30 | "paths": [{ 31 | "backend": { 32 | "serviceName": "%s", 33 | "servicePort": %d 34 | }, 35 | "path": "%s" 36 | }] 37 | } 38 | }] 39 | } 40 | } 41 | ` 42 | 43 | func CreateIngress(project string, i *Ingress) (result *v1beta1.Ingress, err error) { 44 | ingressClient := clientset.ExtensionsV1beta1().Ingresses(project) 45 | 46 | ingressjson := fmt.Sprintf(raw_ingressjson, i.AppName, 47 | project, i.Host, i.AppName, i.ServicePort, i.Path) 48 | 49 | // fmt.Printf("%s", ingressjson) 50 | decode := scheme.Codecs.UniversalDeserializer().Decode 51 | obj, _, e := decode([]byte(ingressjson), nil, nil) 52 | if err != nil { 53 | logs.Error("ingress json decode err: %v", e) 54 | } 55 | 56 | ingress := obj.(*v1beta1.Ingress) 57 | result, err = ingressClient.Create(ingress) 58 | return result, err 59 | } 60 | 61 | func GetIngress(project string, ingressName string) (result *v1beta1.Ingress, err error) { 62 | ingressClient := clientset.ExtensionsV1beta1().Ingresses(project) 63 | result, err = ingressClient.Get(ingressName, metav1.GetOptions{}) 64 | return result, err 65 | } 66 | 67 | func DeleteIngress(project string, ingressName string) (err error) { 68 | ingressClient := clientset.ExtensionsV1beta1().Ingresses(project) 69 | deletePolicy := metav1.DeletePropagationForeground 70 | err = ingressClient.Delete(ingressName, &metav1.DeleteOptions{ 71 | PropagationPolicy: &deletePolicy, 72 | }) 73 | return err 74 | } 75 | -------------------------------------------------------------------------------- /models/service.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "github.com/astaxie/beego/logs" 6 | v1 "k8s.io/api/core/v1" 7 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 8 | "k8s.io/client-go/kubernetes/scheme" 9 | ) 10 | 11 | type Service struct { 12 | AppName string 13 | // Protocol string 14 | Port int32 15 | TargetPort int32 16 | // ServiceType string 17 | } 18 | 19 | var raw_servicejson = ` 20 | { 21 | "kind": "Service", 22 | "apiVersion": "v1", 23 | "metadata": { 24 | "name": "%s", 25 | "creationTimestamp": null 26 | }, 27 | "spec": { 28 | "ports": [{ 29 | "protocol": "TCP", 30 | "port": %d, 31 | "targetPort": %d 32 | }], 33 | "selector": { 34 | "app": "%s" 35 | } 36 | }, 37 | "status": { 38 | "loadBalancer": {} 39 | } 40 | } 41 | ` 42 | 43 | func CreateService(project string, s *Service) (result *v1.Service, err error) { 44 | serviceClient := clientset.CoreV1().Services(project) 45 | 46 | servicejson := fmt.Sprintf(raw_servicejson, s.AppName, s.Port, s.TargetPort, s.AppName) 47 | 48 | // fmt.Printf("%s", servicejson) 49 | decode := scheme.Codecs.UniversalDeserializer().Decode 50 | obj, _, e := decode([]byte(servicejson), nil, nil) 51 | if err != nil { 52 | logs.Error("service json decode err: %v", e) 53 | } 54 | 55 | service := obj.(*v1.Service) 56 | result, err = serviceClient.Create(service) 57 | return result, err 58 | } 59 | 60 | func GetService(project string, serviceName string) (result *v1.Service, err error) { 61 | serviceClient := clientset.CoreV1().Services(project) 62 | result, err = serviceClient.Get(serviceName, metav1.GetOptions{}) 63 | return result, err 64 | } 65 | 66 | func DeleteService(project string, serviceName string) (err error) { 67 | serviceClient := clientset.CoreV1().Services(project) 68 | deletePolicy := metav1.DeletePropagationForeground 69 | err = serviceClient.Delete(serviceName, &metav1.DeleteOptions{ 70 | PropagationPolicy: &deletePolicy, 71 | }) 72 | return err 73 | } 74 | -------------------------------------------------------------------------------- /routers/commentsRouter_controllers.go: -------------------------------------------------------------------------------- 1 | package routers 2 | 3 | import ( 4 | "github.com/astaxie/beego" 5 | "github.com/astaxie/beego/context/param" 6 | ) 7 | 8 | func init() { 9 | 10 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:AppsController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:AppsController"], 11 | beego.ControllerComments{ 12 | Method: "Post", 13 | Router: `/`, 14 | AllowHTTPMethods: []string{"post"}, 15 | MethodParams: param.Make(), 16 | Params: nil}) 17 | 18 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:AppsController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:AppsController"], 19 | beego.ControllerComments{ 20 | Method: "GetAll", 21 | Router: `/`, 22 | AllowHTTPMethods: []string{"get"}, 23 | MethodParams: param.Make(), 24 | Params: nil}) 25 | 26 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:AppsController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:AppsController"], 27 | beego.ControllerComments{ 28 | Method: "Get", 29 | Router: `/:appName`, 30 | AllowHTTPMethods: []string{"get"}, 31 | MethodParams: param.Make(), 32 | Params: nil}) 33 | 34 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:AppsController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:AppsController"], 35 | beego.ControllerComments{ 36 | Method: "Delete", 37 | Router: `/:appName`, 38 | AllowHTTPMethods: []string{"delete"}, 39 | MethodParams: param.Make(), 40 | Params: nil}) 41 | 42 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:IngressesController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:IngressesController"], 43 | beego.ControllerComments{ 44 | Method: "Post", 45 | Router: `/`, 46 | AllowHTTPMethods: []string{"post"}, 47 | MethodParams: param.Make(), 48 | Params: nil}) 49 | 50 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:IngressesController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:IngressesController"], 51 | beego.ControllerComments{ 52 | Method: "Get", 53 | Router: `/:ingressName`, 54 | AllowHTTPMethods: []string{"get"}, 55 | MethodParams: param.Make(), 56 | Params: nil}) 57 | 58 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:IngressesController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:IngressesController"], 59 | beego.ControllerComments{ 60 | Method: "Delete", 61 | Router: `/:ingressName`, 62 | AllowHTTPMethods: []string{"delete"}, 63 | MethodParams: param.Make(), 64 | Params: nil}) 65 | 66 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:ServicesController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:ServicesController"], 67 | beego.ControllerComments{ 68 | Method: "Post", 69 | Router: `/`, 70 | AllowHTTPMethods: []string{"post"}, 71 | MethodParams: param.Make(), 72 | Params: nil}) 73 | 74 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:ServicesController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:ServicesController"], 75 | beego.ControllerComments{ 76 | Method: "Get", 77 | Router: `/:serviceName`, 78 | AllowHTTPMethods: []string{"get"}, 79 | MethodParams: param.Make(), 80 | Params: nil}) 81 | 82 | beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:ServicesController"] = append(beego.GlobalControllerRouter["github.com/yaoice/ice/controllers:ServicesController"], 83 | beego.ControllerComments{ 84 | Method: "Delete", 85 | Router: `/:serviceName`, 86 | AllowHTTPMethods: []string{"delete"}, 87 | MethodParams: param.Make(), 88 | Params: nil}) 89 | 90 | } 91 | -------------------------------------------------------------------------------- /routers/router.go: -------------------------------------------------------------------------------- 1 | // @APIVersion 1.0.0 2 | // @Title Ice API 3 | // @Description Ice is an k8s api proxy 4 | // @Contact yao3690093@gmail.com 5 | // @License Apache 2.0 6 | // @LicenseUrl http://www.apache.org/licenses/LICENSE-2.0.html 7 | package routers 8 | 9 | import ( 10 | "github.com/yaoice/ice/controllers" 11 | 12 | "github.com/astaxie/beego" 13 | ) 14 | 15 | func init() { 16 | ns := beego.NewNamespace("/apis/v1", 17 | beego.NSNamespace("/projects", 18 | beego.NSInclude( 19 | &controllers.ProjectsController{}, 20 | ), 21 | ), 22 | beego.NSNamespace("/projects/:project/apps", 23 | beego.NSInclude( 24 | &controllers.AppsController{}, 25 | ), 26 | ), 27 | beego.NSNamespace("/projects/:project/ingresses", 28 | beego.NSInclude( 29 | &controllers.IngressesController{}, 30 | ), 31 | ), 32 | beego.NSNamespace("/projects/:project/services", 33 | beego.NSInclude( 34 | &controllers.ServicesController{}, 35 | ), 36 | ), 37 | beego.NSNamespace("/flavors", 38 | beego.NSInclude( 39 | &controllers.FlavorsController{}, 40 | ), 41 | ), 42 | beego.NSNamespace("/images", 43 | beego.NSInclude( 44 | &controllers.ImagesController{}, 45 | ), 46 | ), 47 | ) 48 | beego.AddNamespace(ns) 49 | } 50 | -------------------------------------------------------------------------------- /tests/default_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | _ "github.com/yaoice/ice/routers" 5 | "net/http" 6 | "net/http/httptest" 7 | "path/filepath" 8 | "runtime" 9 | "testing" 10 | 11 | "github.com/astaxie/beego" 12 | . "github.com/smartystreets/goconvey/convey" 13 | ) 14 | 15 | func init() { 16 | _, file, _, _ := runtime.Caller(1) 17 | apppath, _ := filepath.Abs(filepath.Dir(filepath.Join(file, ".."+string(filepath.Separator)))) 18 | beego.TestBeegoInit(apppath) 19 | } 20 | 21 | // TestGet is a sample to run an endpoint test 22 | func TestGet(t *testing.T) { 23 | r, _ := http.NewRequest("GET", "/v1/object", nil) 24 | w := httptest.NewRecorder() 25 | beego.BeeApp.Handlers.ServeHTTP(w, r) 26 | 27 | beego.Trace("testing", "TestGet", "Code[%d]\n%s", w.Code, w.Body.String()) 28 | 29 | Convey("Subject: Test Station Endpoint\n", t, func() { 30 | Convey("Status Code Should Be 200", func() { 31 | So(w.Code, ShouldEqual, 200) 32 | }) 33 | Convey("The Result Should Not Be Empty", func() { 34 | So(w.Body.Len(), ShouldBeGreaterThan, 0) 35 | }) 36 | }) 37 | } 38 | --------------------------------------------------------------------------------