mapping data to etcd
This commit is contained in:
74
Gopkg.lock
generated
74
Gopkg.lock
generated
@@ -23,47 +23,46 @@
|
||||
version = "v3.3.7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/docker/distribution"
|
||||
packages = [
|
||||
"digestset",
|
||||
"digest",
|
||||
"reference"
|
||||
]
|
||||
revision = "749f6afb4572201e3c37325d0ffedb6f32be8950"
|
||||
revision = "48294d928ced5dd9b378f7fd7c6f5da3ff3f2c89"
|
||||
version = "v2.6.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/docker/docker"
|
||||
packages = [
|
||||
"api",
|
||||
"api/types",
|
||||
"api/types/blkiodev",
|
||||
"api/types/container",
|
||||
"api/types/events",
|
||||
"api/types/filters",
|
||||
"api/types/image",
|
||||
"api/types/mount",
|
||||
"api/types/network",
|
||||
"api/types/reference",
|
||||
"api/types/registry",
|
||||
"api/types/strslice",
|
||||
"api/types/swarm",
|
||||
"api/types/swarm/runtime",
|
||||
"api/types/time",
|
||||
"api/types/versions",
|
||||
"api/types/volume",
|
||||
"client"
|
||||
"client",
|
||||
"pkg/tlsconfig"
|
||||
]
|
||||
revision = "692df4699c3dcbe4645e9b90cc40091b1f2519d4"
|
||||
revision = "092cba3727bb9b4a2f0e922cd6c0f93ea270e363"
|
||||
version = "v1.13.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/docker/go-connections"
|
||||
packages = [
|
||||
"nat",
|
||||
"sockets",
|
||||
"tlsconfig"
|
||||
]
|
||||
revision = "7395e3f8aa162843a74ed6d48e79627d9792ac55"
|
||||
revision = "3ede32e2033de7505e6500d6c868c2b9ed9f169d"
|
||||
version = "v0.3.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/docker/go-units"
|
||||
@@ -95,6 +94,12 @@
|
||||
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
packages = ["."]
|
||||
revision = "d523deb1b23d913de5bdada721a6071e71283618"
|
||||
version = "v1.4.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/gogo/protobuf"
|
||||
packages = [
|
||||
@@ -158,6 +163,18 @@
|
||||
revision = "9316a62528ac99aaecb4e47eadd6dc8aa6533d58"
|
||||
version = "v0.3.5"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/jinzhu/gorm"
|
||||
packages = ["."]
|
||||
revision = "6ed508ec6a4ecb3531899a69cbc746ccf65a4166"
|
||||
version = "v1.9.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/jinzhu/inflection"
|
||||
packages = ["."]
|
||||
revision = "04140366298a54a039076d798123ffa108fff46c"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/json-iterator/go"
|
||||
packages = ["."]
|
||||
@@ -176,21 +193,6 @@
|
||||
revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f"
|
||||
version = "1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/opencontainers/go-digest"
|
||||
packages = ["."]
|
||||
revision = "279bed98673dd5bef374d3b6e4b09e2af76183bf"
|
||||
version = "v1.0.0-rc1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/opencontainers/image-spec"
|
||||
packages = [
|
||||
"specs-go",
|
||||
"specs-go/v1"
|
||||
]
|
||||
revision = "d60099175f88c47cd379c4738d158884749ed235"
|
||||
version = "v1.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
@@ -207,7 +209,7 @@
|
||||
branch = "master"
|
||||
name = "golang.org/x/crypto"
|
||||
packages = ["ssh/terminal"]
|
||||
revision = "8ac0e0d97ce45cd83d1d7243c060cb8461dda5e9"
|
||||
revision = "a8fb68e7206f8c78be19b432c58eb52a6aa34462"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -233,7 +235,7 @@
|
||||
"unix",
|
||||
"windows"
|
||||
]
|
||||
revision = "8ee9f3e146b708d082f4bab861e5759d1edf8c00"
|
||||
revision = "8014b7b116a67fea23fbb82cd834c9ad656ea44b"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/text"
|
||||
@@ -262,6 +264,12 @@
|
||||
packages = ["rate"]
|
||||
revision = "fbb02b2291d28baffd63558aa44b4b56f178d650"
|
||||
|
||||
[[projects]]
|
||||
name = "google.golang.org/appengine"
|
||||
packages = ["cloudsql"]
|
||||
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "google.golang.org/genproto"
|
||||
@@ -319,6 +327,7 @@
|
||||
version = "v2.2.1"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/api"
|
||||
packages = [
|
||||
"admissionregistration/v1alpha1",
|
||||
@@ -350,10 +359,10 @@
|
||||
"storage/v1alpha1",
|
||||
"storage/v1beta1"
|
||||
]
|
||||
revision = "73d903622b7391f3312dcbac6483fed484e185f8"
|
||||
version = "kubernetes-1.10.0"
|
||||
revision = "783dfbe86ff74ef4a6e1243688e1585ac243f8e7"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apimachinery"
|
||||
packages = [
|
||||
"pkg/api/errors",
|
||||
@@ -397,8 +406,7 @@
|
||||
"third_party/forked/golang/netutil",
|
||||
"third_party/forked/golang/reflect"
|
||||
]
|
||||
revision = "302974c03f7e50f16561ba237db776ab93594ef6"
|
||||
version = "kubernetes-1.10.0"
|
||||
revision = "5a8013207d0d28c7fe98193e5b6cdbf92e98a000"
|
||||
|
||||
[[projects]]
|
||||
name = "k8s.io/client-go"
|
||||
@@ -468,6 +476,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "3a835656d614522efea125721424042ef0f7159446907bedccef8fd249a69e0d"
|
||||
inputs-digest = "748f1a35c23f248b894b1413f6c6821ddb832a05e6bad53e6f4a84791057a376"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
||||
31
Gopkg.toml
31
Gopkg.toml
@@ -31,16 +31,24 @@
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/docker/docker"
|
||||
branch = "master"
|
||||
version = "1.13.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/emicklei/go-restful"
|
||||
version = "2.7.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/go-sql-driver/mysql"
|
||||
version = "1.4.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "github.com/golang/glog"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/jinzhu/gorm"
|
||||
version = "1.9.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/spf13/pflag"
|
||||
version = "1.0.1"
|
||||
@@ -54,12 +62,12 @@
|
||||
version = "2.2.1"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "k8s.io/api"
|
||||
version = "kubernetes-1.10.0"
|
||||
|
||||
[[constraint]]
|
||||
branch = "master"
|
||||
name = "k8s.io/apimachinery"
|
||||
version = "kubernetes-1.10.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "k8s.io/client-go"
|
||||
@@ -72,20 +80,3 @@
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
||||
# To use reference package:
|
||||
# vendor/github.com/docker/docker/client/container_commit.go:17: undefined: reference.ParseNormalizedNamed
|
||||
# vendor/github.com/docker/docker/client/container_commit.go:25: undefined: reference.TagNameOnly
|
||||
# vendor/github.com/docker/docker/client/container_commit.go:30: undefined: reference.FamiliarNam
|
||||
[[override]]
|
||||
name = "github.com/docker/distribution"
|
||||
branch = "master"
|
||||
|
||||
# To use reference package:
|
||||
# vendor/github.com/docker/docker/registry/registry.go:30: cannot call non-function tlsconfig.ServerDefault (type tls.Config)
|
||||
# vendor/github.com/docker/docker/registry/registry.go:66: undefined: tlsconfig.SystemCertPool
|
||||
# vendor/github.com/docker/docker/registry/registry.go:168: cannot call non-function tlsconfig.ServerDefault (type tls.Config)
|
||||
# vendor/github.com/docker/docker/registry/service_v2.go:11: cannot call non-function tlsconfig.ServerDefault (type tls.Config)
|
||||
[[override]]
|
||||
name = "github.com/docker/go-connections"
|
||||
branch = "master"
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/pods"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/quota"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/registries"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/resources"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/routes"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/storage"
|
||||
"kubesphere.io/kubesphere/pkg/apis/v1alpha/terminal"
|
||||
@@ -52,6 +53,7 @@ func init() {
|
||||
terminal.Register(ws, "/namespaces/{namespace}/pod/{pod}/shell/{container}")
|
||||
workloadstatus.Register(ws, "/status")
|
||||
quota.Register(ws, "/quota")
|
||||
resources.Register(ws, "/resources")
|
||||
|
||||
// add webservice to default container
|
||||
restful.Add(ws)
|
||||
|
||||
46
pkg/apis/v1alpha/resources/resources.go
Normal file
46
pkg/apis/v1alpha/resources/resources.go
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
)
|
||||
|
||||
func Register(ws *restful.WebService, subPath string) {
|
||||
|
||||
ws.Route(ws.GET(subPath + "/{resource}").To(listResource).Produces(restful.MIME_JSON))
|
||||
|
||||
}
|
||||
|
||||
func listResource(req *restful.Request, resp *restful.Response) {
|
||||
|
||||
resource := req.PathParameter("resource")
|
||||
conditions := req.QueryParameter("conditions")
|
||||
paging := req.QueryParameter("paging")
|
||||
|
||||
res, err := models.ListResource(resource, conditions, paging)
|
||||
if err != nil {
|
||||
resp.WriteHeaderAndEntity(http.StatusInternalServerError, constants.MessageResponse{Message: err.Error()})
|
||||
return
|
||||
}
|
||||
resp.WriteEntity(res)
|
||||
}
|
||||
@@ -15,10 +15,10 @@
|
||||
package terminal
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
|
||||
"net/http"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/models"
|
||||
)
|
||||
|
||||
|
||||
@@ -20,19 +20,18 @@ import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
"github.com/emicklei/go-restful"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
_ "kubesphere.io/kubesphere/pkg/apis/v1alpha"
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/jobs/cronjobs"
|
||||
"kubesphere.io/kubesphere/pkg/models/jobs/resources"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
"kubesphere.io/kubesphere/pkg/options"
|
||||
)
|
||||
|
||||
@@ -81,8 +80,8 @@ func (server *kubeSphereServer) run() {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
go resources.Run()
|
||||
go cronjobs.Run()
|
||||
|
||||
go controllers.Run()
|
||||
|
||||
if len(server.certFile) > 0 && len(server.keyFile) > 0 {
|
||||
servingCert, err := tls.LoadX509KeyPair(server.certFile, server.keyFile)
|
||||
|
||||
61
pkg/client/dbclient.go
Normal file
61
pkg/client/dbclient.go
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/jinzhu/gorm"
|
||||
//_ "github.com/jinzhu/gorm/dialects/mysql"
|
||||
"fmt"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/options"
|
||||
)
|
||||
|
||||
var dbClient *gorm.DB
|
||||
|
||||
const database = "kubesphere"
|
||||
|
||||
func NewDBClient() *gorm.DB {
|
||||
if dbClient != nil {
|
||||
return dbClient
|
||||
}
|
||||
|
||||
user := options.ServerOptions.GetMysqlUser()
|
||||
passwd := options.ServerOptions.GetMysqlPassword()
|
||||
addr := options.ServerOptions.GetMysqlAddr()
|
||||
conn := fmt.Sprintf("%s:%s@tcp(%s)/mysql?charset=utf8mb4&parseTime=True&loc=Local", user, passwd, addr)
|
||||
db, err := gorm.Open("mysql", conn)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
panic(err)
|
||||
}
|
||||
|
||||
db.Exec(fmt.Sprintf("create database if not exists %s;", database))
|
||||
|
||||
conn = fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local", user, passwd, addr, database)
|
||||
db, err = gorm.Open("mysql", conn)
|
||||
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
panic(err)
|
||||
}
|
||||
dbClient = db
|
||||
return dbClient
|
||||
}
|
||||
@@ -28,10 +28,6 @@ type PageableResponse struct {
|
||||
const (
|
||||
APIVERSION = "v1alpha1"
|
||||
KIND = "kubesphere"
|
||||
Root = "/kubesphere"
|
||||
UpdateCircle = 60
|
||||
QuotaKey = "resource-quota"
|
||||
WorkloadStatusKey = "workload-status"
|
||||
NameSpace = "kubesphere"
|
||||
DATA_HOME = "/etc/kubesphere"
|
||||
INGRESS_CONTROLLER_FOLDER = DATA_HOME + "/ingress-controller"
|
||||
|
||||
140
pkg/models/controllers/clusterRoles.go
Normal file
140
pkg/models/controllers/clusterRoles.go
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/rbac/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
func (ctl *ClusterRoleCtl) generateObjec(item v1.ClusterRole) *ClusterRole {
|
||||
name := item.Name
|
||||
if strings.HasPrefix(name, "system:") {
|
||||
return nil
|
||||
}
|
||||
|
||||
createTime := item.CreationTimestamp.Time
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
|
||||
object := &ClusterRole{Name: name, CreateTime: createTime, AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleCtl) listAndWatch() {
|
||||
defer func() {
|
||||
close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&ClusterRole{}) {
|
||||
db.DropTable(&ClusterRole{})
|
||||
|
||||
}
|
||||
|
||||
db = db.CreateTable(&ClusterRole{})
|
||||
|
||||
k8sClient := ctl.K8sClient
|
||||
|
||||
clusterRoleList, err := k8sClient.RbacV1().ClusterRoles().List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range clusterRoleList.Items {
|
||||
obj := ctl.generateObjec(item)
|
||||
if obj != nil {
|
||||
db.Create(obj)
|
||||
}
|
||||
}
|
||||
|
||||
clusterRoleWatcher, err := k8sClient.RbacV1().ClusterRoles().Watch(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-clusterRoleWatcher.ResultChan():
|
||||
var role ClusterRole
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1.ClusterRole)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, "\"\"").Find(&role)
|
||||
db.Delete(role)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObjec(*object)
|
||||
if obj != nil {
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleCtl) CountWithConditions(conditions string) int {
|
||||
var object ClusterRole
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var object ClusterRole
|
||||
var list []ClusterRole
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
db := ctl.DB
|
||||
|
||||
listWithConditions(db, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *ClusterRoleCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
db.Model(&ClusterRole{}).Count(&count)
|
||||
return count
|
||||
}
|
||||
161
pkg/models/controllers/daemonsets.go
Normal file
161
pkg/models/controllers/daemonsets.go
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func (ctl *DaemonsetCtl) generateObject(item v1beta2.DaemonSet) *Daemonset {
|
||||
var app string
|
||||
var status string
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.CurrentNumberScheduled
|
||||
desirePodNum := item.Status.DesiredNumberScheduled
|
||||
createTime := item.CreationTimestamp.Time
|
||||
release := item.ObjectMeta.Labels["release"]
|
||||
nodeSelector := item.Spec.Template.Spec.NodeSelector
|
||||
nodeSelectorStr, _ := json.Marshal(nodeSelector)
|
||||
|
||||
chart := item.ObjectMeta.Labels["chart"]
|
||||
|
||||
if len(release) > 0 && len(chart) > 0 {
|
||||
app = release + "/" + chart
|
||||
} else {
|
||||
app = "-"
|
||||
}
|
||||
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
if availablePodNum >= desirePodNum {
|
||||
status = running
|
||||
} else {
|
||||
status = updating
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
|
||||
object := &Daemonset{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, CreateTime: createTime, Status: status, NodeSelector: string(nodeSelectorStr), AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *DaemonsetCtl) listAndWatch() {
|
||||
defer func() {
|
||||
|
||||
close(ctl.aliveChan)
|
||||
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Daemonset{}) {
|
||||
db.DropTable(&Daemonset{})
|
||||
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Daemonset{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
deoloyList, err := k8sClient.AppsV1beta2().DaemonSets("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range deoloyList.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.AppsV1beta2().DaemonSets("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var ss Daemonset
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1beta2.DaemonSet)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&ss)
|
||||
db.Delete(ss)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(*object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *DaemonsetCtl) CountWithConditions(conditions string) int {
|
||||
var object Daemonset
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *DaemonsetCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Daemonset
|
||||
var object Daemonset
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *DaemonsetCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
if len(namespace) == 0 {
|
||||
db.Model(&Daemonset{}).Count(&count)
|
||||
} else {
|
||||
db.Model(&Daemonset{}).Where("namespace = ?", namespace).Count(&count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
161
pkg/models/controllers/deployments.go
Normal file
161
pkg/models/controllers/deployments.go
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func (ctl *DeploymentCtl) generateObject(item v1beta2.Deployment) *Deployment {
|
||||
var app string
|
||||
var status string
|
||||
var updateTime time.Time
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.AvailableReplicas
|
||||
desirePodNum := *item.Spec.Replicas
|
||||
release := item.ObjectMeta.Labels["release"]
|
||||
chart := item.ObjectMeta.Labels["chart"]
|
||||
|
||||
if len(release) > 0 && len(chart) > 0 {
|
||||
app = release + "/" + chart
|
||||
} else {
|
||||
app = "-"
|
||||
}
|
||||
|
||||
for _, conditon := range item.Status.Conditions {
|
||||
if conditon.Type == "Progressing" {
|
||||
updateTime = conditon.LastUpdateTime.Time
|
||||
}
|
||||
}
|
||||
if updateTime.IsZero() {
|
||||
updateTime = time.Now()
|
||||
}
|
||||
|
||||
if item.Annotations["state"] == "stop" {
|
||||
status = stopping
|
||||
} else {
|
||||
if availablePodNum >= desirePodNum {
|
||||
status = running
|
||||
} else {
|
||||
status = updating
|
||||
}
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
|
||||
return &Deployment{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, UpdateTime: updateTime, Status: status, AnnotationStr: string(annotation)}
|
||||
}
|
||||
|
||||
func (ctl *DeploymentCtl) listAndWatch() {
|
||||
defer func() {
|
||||
close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
if db.HasTable(&Deployment{}) {
|
||||
db.DropTable(&Deployment{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Deployment{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
deoloyList, err := k8sClient.AppsV1beta2().Deployments("").List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range deoloyList.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.AppsV1beta2().Deployments("").Watch(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var deploy Deployment
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1beta2.Deployment)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&deploy)
|
||||
db.Delete(deploy)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(*object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *DeploymentCtl) CountWithConditions(conditions string) int {
|
||||
var object Deployment
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *DeploymentCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Deployment
|
||||
var object Deployment
|
||||
var total int
|
||||
|
||||
order := "updateTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *DeploymentCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
if len(namespace) == 0 {
|
||||
db.Model(&Deployment{}).Count(&count)
|
||||
} else {
|
||||
db.Model(&Deployment{}).Where("namespace = ?", namespace).Count(&count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
148
pkg/models/controllers/ingresses.go
Normal file
148
pkg/models/controllers/ingresses.go
Normal file
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/extensions/v1beta1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func (ctl *IngressCtl) generateObject(item v1beta1.Ingress) *Ingress {
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
ip := "-"
|
||||
tls := "-"
|
||||
createTime := item.CreationTimestamp.Time
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
var ipList []string
|
||||
for _, lb := range item.Status.LoadBalancer.Ingress {
|
||||
if len(lb.IP) > 0 {
|
||||
ipList = append(ipList, lb.IP)
|
||||
}
|
||||
}
|
||||
if len(ipList) > 0 {
|
||||
ip = strings.Join(ipList, ",")
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
object := &Ingress{Namespace: namespace, Name: name, TlsTermination: tls, Ip: ip, CreateTime: createTime, AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *IngressCtl) listAndWatch() {
|
||||
defer func() {
|
||||
defer close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Ingress{}) {
|
||||
db.DropTable(&Ingress{})
|
||||
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Ingress{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
list, err := k8sClient.ExtensionsV1beta1().Ingresses("").List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.ExtensionsV1beta1().Ingresses("").Watch(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var ing Ingress
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1beta1.Ingress)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&ing)
|
||||
db.Delete(ing)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(*object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *IngressCtl) CountWithConditions(conditions string) int {
|
||||
var object Ingress
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *IngressCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Ingress
|
||||
var object Ingress
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *IngressCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
if len(namespace) == 0 {
|
||||
db.Model(&Ingress{}).Count(&count)
|
||||
} else {
|
||||
db.Model(&Ingress{}).Where("namespace = ?", namespace).Count(&count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
310
pkg/models/controllers/namespaces.go
Normal file
310
pkg/models/controllers/namespaces.go
Normal file
@@ -0,0 +1,310 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
rbac "k8s.io/api/rbac/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/options"
|
||||
)
|
||||
|
||||
const (
|
||||
provider = "kubernetes"
|
||||
admin = "admin"
|
||||
normal = "normal"
|
||||
view = "view"
|
||||
kubectlNamespace = "kubesphere"
|
||||
kubectlConfigKey = "config"
|
||||
)
|
||||
|
||||
var adminRules = []rbac.PolicyRule{rbac.PolicyRule{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}
|
||||
var normalRules = []rbac.PolicyRule{rbac.PolicyRule{Verbs: []string{"*"}, APIGroups: []string{"", "apps", "extensions"}, Resources: []string{"*"}}}
|
||||
var viewRules = []rbac.PolicyRule{rbac.PolicyRule{Verbs: []string{"list", "get"}, APIGroups: []string{"", "apps", "extensions"}, Resources: []string{"*"}}}
|
||||
|
||||
type runTime struct {
|
||||
RuntimeId string `json:"runtime_id"`
|
||||
RuntimeUrl string `json:"runtime_url"`
|
||||
Name string `json:"name"`
|
||||
Provider string `json:"provider"`
|
||||
Zone string `json:"zone"`
|
||||
RuntimeCredential string `json:"runtime_credential"`
|
||||
}
|
||||
|
||||
type DeleteRunTime struct {
|
||||
RuntimeId []string `json:"runtime_id"`
|
||||
}
|
||||
|
||||
func makeHttpRequest(method, url, data string) ([]byte, error) {
|
||||
req, err := http.NewRequest(method, url, strings.NewReader(data))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
httpClient := &http.Client{}
|
||||
resp, err := httpClient.Do(req)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
glog.Error(string(body))
|
||||
defer resp.Body.Close()
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) getKubeConfig(user string) (string, error) {
|
||||
k8sClient := client.NewK8sClient()
|
||||
configmap, err := k8sClient.CoreV1().ConfigMaps(kubectlNamespace).Get(user, metaV1.GetOptions{})
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return "", err
|
||||
}
|
||||
return configmap.Data[kubectlConfigKey], nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) deleteOpRuntime(item v1.Namespace) {
|
||||
|
||||
runtimeId := item.Annotations["openpitrix_runtime"]
|
||||
if len(runtimeId) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
url := options.ServerOptions.GetOpAddress() + "/v1/runtimes"
|
||||
|
||||
var deleteRuntime = DeleteRunTime{RuntimeId: []string{runtimeId}}
|
||||
|
||||
body, err := json.Marshal(deleteRuntime)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
// todo: if delete failed, what's to be done?
|
||||
makeHttpRequest("DELETE", url, string(body))
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) createOpRuntime(namespace, user string) ([]byte, error) {
|
||||
zone := namespace
|
||||
name := namespace
|
||||
kubeConfig, err := ctl.getKubeConfig(user)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
url := options.ServerOptions.GetOpAddress() + "/v1/runtimes"
|
||||
|
||||
option := runTime{Name: name, Provider: provider, RuntimeCredential: kubeConfig, Zone: zone}
|
||||
body, err := json.Marshal(option)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return makeHttpRequest("POST", url, string(body))
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) createDefaultRole(ns string) error {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
}()
|
||||
|
||||
adminRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: admin, Namespace: ns}, Rules: adminRules}
|
||||
normalRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: normal, Namespace: ns}, Rules: normalRules}
|
||||
viewRole := &rbac.Role{ObjectMeta: metaV1.ObjectMeta{Name: view, Namespace: ns}, Rules: viewRules}
|
||||
|
||||
role, _ := ctl.K8sClient.RbacV1().Roles(ns).Get(admin, metaV1.GetOptions{})
|
||||
|
||||
if role.Name != admin {
|
||||
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(adminRole)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
role, _ = ctl.K8sClient.RbacV1().Roles(ns).Get(normal, metaV1.GetOptions{})
|
||||
|
||||
if role.Name != normal {
|
||||
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(normalRole)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
role, _ = ctl.K8sClient.RbacV1().Roles(ns).Get(view, metaV1.GetOptions{})
|
||||
|
||||
if role.Name != view {
|
||||
_, err := ctl.K8sClient.RbacV1().Roles(ns).Create(viewRole)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) createRoleAndRuntime(item v1.Namespace) {
|
||||
user := item.Annotations["creator"]
|
||||
ns := item.Name
|
||||
if len(user) > 0 && len(item.Annotations["openpitrix_runtime"]) == 0 {
|
||||
err := ctl.createDefaultRole(ns)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
resp, err := ctl.createOpRuntime(ns, user)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var runtime runTime
|
||||
err = json.Unmarshal(resp, &runtime)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
item.Annotations["openpitrix_runtime"] = runtime.RuntimeId
|
||||
ctl.K8sClient.CoreV1().Namespaces().Update(&item)
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) generateObject(item v1.Namespace) *Namespace {
|
||||
|
||||
name := item.Name
|
||||
createTime := item.CreationTimestamp.Time
|
||||
status := fmt.Sprintf("%v", item.Status.Phase)
|
||||
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
object := &Namespace{Name: name, CreateTime: createTime, Status: status, AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) listAndWatch() {
|
||||
defer func() {
|
||||
defer close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Namespace{}) {
|
||||
db.DropTable(&Namespace{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Namespace{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
list, err := k8sClient.CoreV1().Namespaces().List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
db.Create(obj)
|
||||
|
||||
ctl.createRoleAndRuntime(item)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.CoreV1().Namespaces().Watch(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var ns Namespace
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1.Namespace)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=?", object.Name).Find(&ns)
|
||||
db.Delete(ns)
|
||||
|
||||
ctl.deleteOpRuntime(*object)
|
||||
break
|
||||
}
|
||||
|
||||
ctl.createRoleAndRuntime(*object)
|
||||
|
||||
obj := ctl.generateObject(*object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) CountWithConditions(conditions string) int {
|
||||
var object Namespace
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Namespace
|
||||
var object Namespace
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *NamespaceCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
db.Model(&Namespace{}).Count(&count)
|
||||
return count
|
||||
}
|
||||
161
pkg/models/controllers/pods.go
Normal file
161
pkg/models/controllers/pods.go
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func (ctl *PodCtl) generateObject(item v1.Pod) *Pod {
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
podIp := item.Status.PodIP
|
||||
nodeName := item.Spec.NodeName
|
||||
nodeIp := item.Status.HostIP
|
||||
status := string(item.Status.Phase)
|
||||
createTime := item.CreationTimestamp.Time
|
||||
containerStatus := item.Status.ContainerStatuses
|
||||
containerSpecs := item.Spec.Containers
|
||||
var containers []Container
|
||||
|
||||
for _, containerSpec := range containerSpecs {
|
||||
var container Container
|
||||
container.Name = containerSpec.Name
|
||||
container.Image = containerSpec.Image
|
||||
container.Ports = containerSpec.Ports
|
||||
for _, status := range containerStatus {
|
||||
if container.Name == status.Name {
|
||||
container.Ready = status.Ready
|
||||
}
|
||||
}
|
||||
|
||||
containers = append(containers, container)
|
||||
}
|
||||
|
||||
containerStr, _ := json.Marshal(containers)
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
|
||||
object := &Pod{Namespace: namespace, Name: name, Node: nodeName, PodIp: podIp, Status: status, NodeIp: nodeIp,
|
||||
CreateTime: createTime, ContainerStr: string(containerStr), AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *PodCtl) listAndWatch() {
|
||||
defer func() {
|
||||
defer close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Pod{}) {
|
||||
db.DropTable(&Pod{})
|
||||
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Pod{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
list, err := k8sClient.CoreV1().Pods("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.CoreV1().Pods("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var po Pod
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1.Pod)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&po)
|
||||
db.Delete(po)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(*object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *PodCtl) CountWithConditions(conditions string) int {
|
||||
var object Pod
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *PodCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Pod
|
||||
var object Pod
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
var containers []Container
|
||||
json.Unmarshal([]byte(item.ContainerStr), &containers)
|
||||
list[index].Containers = containers
|
||||
list[index].ContainerStr = ""
|
||||
|
||||
annotation := make(Annotation)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *PodCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
if len(namespace) == 0 {
|
||||
db.Model(&Pod{}).Count(&count)
|
||||
} else {
|
||||
db.Model(&Pod{}).Where("namespace = ?", namespace).Count(&count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
162
pkg/models/controllers/pvcs.go
Normal file
162
pkg/models/controllers/pvcs.go
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
const creator = "creator"
|
||||
|
||||
func (ctl *PvcCtl) generateObject(item *v1.PersistentVolumeClaim) *Pvc {
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
status := fmt.Sprintf("%s", item.Status.Phase)
|
||||
createTime := item.CreationTimestamp.Time
|
||||
capacity := "-"
|
||||
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
if storage, exist := item.Status.Capacity["storage"]; exist {
|
||||
capacity = storage.String()
|
||||
}
|
||||
|
||||
storageClass := "-"
|
||||
if item.Spec.StorageClassName != nil {
|
||||
storageClass = *item.Spec.StorageClassName
|
||||
}
|
||||
|
||||
accessModeStr := "-"
|
||||
|
||||
var accessModeList []string
|
||||
for _, accessMode := range item.Status.AccessModes {
|
||||
accessModeList = append(accessModeList, string(accessMode))
|
||||
}
|
||||
|
||||
accessModeStr = strings.Join(accessModeList, ",")
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
|
||||
object := &Pvc{Namespace: namespace, Name: name, Status: status, Capacity: capacity,
|
||||
AccessMode: accessModeStr, StorageClassName: storageClass, CreateTime: createTime, AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *PvcCtl) listAndWatch() {
|
||||
defer func() {
|
||||
defer close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Pvc{}) {
|
||||
db.DropTable(&Pvc{})
|
||||
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Pvc{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
pvcList, err := k8sClient.CoreV1().PersistentVolumeClaims("").List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range pvcList.Items {
|
||||
obj := ctl.generateObject(&item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.CoreV1().PersistentVolumeClaims("").Watch(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var pvc Pvc
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1.PersistentVolumeClaim)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&pvc)
|
||||
db.Delete(pvc)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *PvcCtl) CountWithConditions(conditions string) int {
|
||||
var object Pvc
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *PvcCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Pvc
|
||||
var object Pvc
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *PvcCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
if len(namespace) == 0 {
|
||||
db.Model(&Pvc{}).Count(&count)
|
||||
} else {
|
||||
db.Model(&Pvc{}).Where("namespace = ?", namespace).Count(&count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
142
pkg/models/controllers/roles.go
Normal file
142
pkg/models/controllers/roles.go
Normal file
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/rbac/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func (ctl *RoleCtl) generateObject(item v1.Role) *Role {
|
||||
name := item.Name
|
||||
if strings.HasPrefix(name, "system:") {
|
||||
return nil
|
||||
}
|
||||
namespace := item.Namespace
|
||||
createTime := item.CreationTimestamp.Time
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
|
||||
object := &Role{Namespace: namespace, Name: name, CreateTime: createTime, AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *RoleCtl) listAndWatch() {
|
||||
defer func() {
|
||||
close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Role{}) {
|
||||
db.DropTable(&Role{})
|
||||
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Role{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
roleList, err := k8sClient.RbacV1().Roles("").List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range roleList.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
if obj != nil {
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
roleWatcher, err := k8sClient.RbacV1().Roles("").Watch(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-roleWatcher.ResultChan():
|
||||
var role Role
|
||||
object := event.Object.(*v1.Role)
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&role)
|
||||
db.Delete(role)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(*object)
|
||||
if obj != nil {
|
||||
db.Save(obj)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *RoleCtl) CountWithConditions(conditions string) int {
|
||||
var object Role
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *RoleCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Role
|
||||
var object Role
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *RoleCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
db.Model(&Role{}).Where("namespace = ?", namespace).Count(&count)
|
||||
return count
|
||||
}
|
||||
100
pkg/models/controllers/run.go
Normal file
100
pkg/models/controllers/run.go
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/jinzhu/gorm"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
type resourceControllers struct {
|
||||
controllers map[string]Controller
|
||||
db *gorm.DB
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
var stopChan chan struct{}
|
||||
|
||||
func (rec *resourceControllers) runContoller(name string) {
|
||||
var ctl Controller
|
||||
attr := CommonAttribute{DB: rec.db, K8sClient: rec.k8sClient, stopChan: stopChan, aliveChan: make(chan struct{})}
|
||||
switch name {
|
||||
case Deployments:
|
||||
ctl = &DeploymentCtl{attr}
|
||||
case Statefulsets:
|
||||
ctl = &StatefulsetCtl{attr}
|
||||
case Daemonsets:
|
||||
ctl = &DaemonsetCtl{attr}
|
||||
case Ingresses:
|
||||
ctl = &IngressCtl{attr}
|
||||
case PersistentVolumeClaim:
|
||||
ctl = &PvcCtl{attr}
|
||||
case Roles:
|
||||
ctl = &RoleCtl{attr}
|
||||
case ClusterRoles:
|
||||
ctl = &ClusterRoleCtl{attr}
|
||||
case Services:
|
||||
ctl = &ServiceCtl{attr}
|
||||
case Pods:
|
||||
ctl = &PodCtl{attr}
|
||||
case Namespaces:
|
||||
ctl = &NamespaceCtl{attr}
|
||||
case StorageClasses:
|
||||
ctl = &StorageClassCtl{attr}
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
rec.controllers[name] = ctl
|
||||
go ctl.listAndWatch()
|
||||
|
||||
}
|
||||
|
||||
func Run() {
|
||||
db := client.NewDBClient()
|
||||
|
||||
stopChan := make(chan struct{})
|
||||
defer db.Commit()
|
||||
defer db.Close()
|
||||
defer close(stopChan)
|
||||
|
||||
rec := resourceControllers{k8sClient: client.NewK8sClient(), db: db, controllers: make(map[string]Controller)}
|
||||
|
||||
for _, item := range []string{Deployments, Statefulsets, Daemonsets, PersistentVolumeClaim, Pods, Services,
|
||||
Ingresses, Roles, ClusterRoles, Namespaces, StorageClasses} {
|
||||
rec.runContoller(item)
|
||||
}
|
||||
|
||||
for {
|
||||
for ctlName, controller := range rec.controllers {
|
||||
select {
|
||||
case _, isClose := <-controller.chanAlive():
|
||||
if !isClose {
|
||||
glog.Errorf("controller %s have stopped, restart it", ctlName)
|
||||
rec.runContoller(ctlName)
|
||||
}
|
||||
default:
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
218
pkg/models/controllers/services.go
Normal file
218
pkg/models/controllers/services.go
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
const (
|
||||
headlessSelector = "Headless(Selector)"
|
||||
headlessExternal = "Headless(ExternalName)"
|
||||
virtualIp = "Virtual IP"
|
||||
)
|
||||
|
||||
func (ctl *ServiceCtl) loadBalancerStatusStringer(item v1.Service) string {
|
||||
ingress := item.Status.LoadBalancer.Ingress
|
||||
result := sets.NewString()
|
||||
for i := range ingress {
|
||||
if ingress[i].IP != "" {
|
||||
result.Insert(ingress[i].IP)
|
||||
} else if ingress[i].Hostname != "" {
|
||||
result.Insert(ingress[i].Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
r := strings.Join(result.List(), ",")
|
||||
return r
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) getExternalIp(item v1.Service) string {
|
||||
switch item.Spec.Type {
|
||||
case "ClusterIP", "NodePort":
|
||||
if len(item.Spec.ExternalIPs) > 0 {
|
||||
return strings.Join(item.Spec.ExternalIPs, ",")
|
||||
}
|
||||
case "ExternalName":
|
||||
return item.Spec.ExternalName
|
||||
|
||||
case "LoadBalancer":
|
||||
lbIps := ctl.loadBalancerStatusStringer(item)
|
||||
if len(item.Spec.ExternalIPs) > 0 {
|
||||
results := []string{}
|
||||
if len(lbIps) > 0 {
|
||||
results = append(results, strings.Split(lbIps, ",")...)
|
||||
}
|
||||
results = append(results, item.Spec.ExternalIPs...)
|
||||
return strings.Join(results, ",")
|
||||
}
|
||||
if len(lbIps) > 0 {
|
||||
return lbIps
|
||||
}
|
||||
return "<pending>"
|
||||
}
|
||||
return "-"
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) generateObject(item v1.Service) *Service {
|
||||
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
createTime := item.CreationTimestamp.Time
|
||||
externalIp := ctl.getExternalIp(item)
|
||||
serviceType := virtualIp
|
||||
vip := item.Spec.ClusterIP
|
||||
ports := ""
|
||||
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
if item.Spec.ClusterIP == "None" {
|
||||
serviceType = headlessSelector
|
||||
vip = "-"
|
||||
}
|
||||
|
||||
if len(item.Spec.ExternalName) > 0 {
|
||||
serviceType = headlessExternal
|
||||
vip = "-"
|
||||
}
|
||||
|
||||
if len(item.Spec.ExternalIPs) > 0 {
|
||||
externalIp = strings.Join(item.Spec.ExternalIPs, ",")
|
||||
}
|
||||
|
||||
for _, portItem := range item.Spec.Ports {
|
||||
port := portItem.Port
|
||||
targetPort := portItem.TargetPort.String()
|
||||
protocol := portItem.Protocol
|
||||
ports += fmt.Sprintf("%d:%s/%s,", port, targetPort, protocol)
|
||||
}
|
||||
if len(ports) == 0 {
|
||||
ports = "-"
|
||||
} else {
|
||||
ports = ports[0 : len(ports)-1]
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
object := &Service{Namespace: namespace, Name: name, ServiceType: serviceType, ExternalIp: externalIp,
|
||||
VirtualIp: vip, CreateTime: createTime, Ports: ports, AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) listAndWatch() {
|
||||
defer func() {
|
||||
defer close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&Service{}) {
|
||||
db.DropTable(&Service{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Service{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
svcList, err := k8sClient.CoreV1().Services("").List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range svcList.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.CoreV1().Services("").Watch(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var svc Service
|
||||
object := event.Object.(*v1.Service)
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&svc)
|
||||
db.Delete(svc)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(*object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) CountWithConditions(conditions string) int {
|
||||
var object Service
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Service
|
||||
var object Service
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *ServiceCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
if len(namespace) == 0 {
|
||||
db.Model(&Service{}).Count(&count)
|
||||
} else {
|
||||
db.Model(&Service{}).Where("namespace = ?", namespace).Count(&count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
156
pkg/models/controllers/statefulsets.go
Normal file
156
pkg/models/controllers/statefulsets.go
Normal file
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func (ctl *StatefulsetCtl) generateObject(item v1beta2.StatefulSet) *Statefulset {
|
||||
var app string
|
||||
var status string
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.ReadyReplicas
|
||||
desirePodNum := *item.Spec.Replicas
|
||||
createTime := item.CreationTimestamp.Time
|
||||
release := item.ObjectMeta.Labels["release"]
|
||||
chart := item.ObjectMeta.Labels["chart"]
|
||||
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
if len(release) > 0 && len(chart) > 0 {
|
||||
app = release + "/" + chart
|
||||
} else {
|
||||
app = "-"
|
||||
}
|
||||
|
||||
if item.Annotations["state"] == "stop" {
|
||||
status = stopping
|
||||
} else {
|
||||
if availablePodNum >= desirePodNum {
|
||||
status = running
|
||||
} else {
|
||||
status = updating
|
||||
}
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
|
||||
statefulSetObject := &Statefulset{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, CreateTime: createTime, Status: status, AnnotationStr: string(annotation)}
|
||||
|
||||
return statefulSetObject
|
||||
}
|
||||
|
||||
func (ctl *StatefulsetCtl) listAndWatch() {
|
||||
defer func() {
|
||||
defer close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
if db.HasTable(&Statefulset{}) {
|
||||
db.DropTable(&Statefulset{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&Statefulset{})
|
||||
k8sClient := client.NewK8sClient()
|
||||
deoloyList, err := k8sClient.AppsV1beta2().StatefulSets("").List(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
for _, item := range deoloyList.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.AppsV1beta2().StatefulSets("").Watch(metaV1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var tmp Statefulset
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1beta2.StatefulSet)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=? And namespace=?", object.Name, object.Namespace).Find(&tmp)
|
||||
db.Delete(tmp)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(*object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *StatefulsetCtl) CountWithConditions(conditions string) int {
|
||||
var object Statefulset
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *StatefulsetCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []Statefulset
|
||||
var object Statefulset
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, item := range list {
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(item.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
}
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *StatefulsetCtl) Count(namespace string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
if len(namespace) == 0 {
|
||||
db.Model(&Statefulset{}).Count(&count)
|
||||
} else {
|
||||
db.Model(&Statefulset{}).Where("namespace = ?", namespace).Count(&count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
141
pkg/models/controllers/storageclasses.go
Normal file
141
pkg/models/controllers/storageclasses.go
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/storage/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
)
|
||||
|
||||
func (ctl *StorageClassCtl) generateObject(item v1beta1.StorageClass) *StorageClass {
|
||||
|
||||
name := item.Name
|
||||
createTime := item.CreationTimestamp.Time
|
||||
isDefault := false
|
||||
if item.Annotations["storageclass.beta.kubernetes.io/is-default-class"] == "true" {
|
||||
isDefault = true
|
||||
}
|
||||
|
||||
if createTime.IsZero() {
|
||||
createTime = time.Now()
|
||||
}
|
||||
|
||||
annotation, _ := json.Marshal(item.Annotations)
|
||||
object := &StorageClass{Name: name, CreateTime: createTime, IsDefault: isDefault, AnnotationStr: string(annotation)}
|
||||
|
||||
return object
|
||||
}
|
||||
|
||||
func (ctl *StorageClassCtl) listAndWatch() {
|
||||
defer func() {
|
||||
defer close(ctl.aliveChan)
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
db := ctl.DB
|
||||
|
||||
if db.HasTable(&StorageClass{}) {
|
||||
db.DropTable(&StorageClass{})
|
||||
}
|
||||
|
||||
db = db.CreateTable(&StorageClass{})
|
||||
|
||||
k8sClient := client.NewK8sClient()
|
||||
list, err := k8sClient.StorageV1beta1().StorageClasses().List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, item := range list.Items {
|
||||
obj := ctl.generateObject(item)
|
||||
db.Create(obj)
|
||||
}
|
||||
|
||||
watcher, err := k8sClient.StorageV1beta1().StorageClasses().Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctl.stopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
var sc StorageClass
|
||||
if event.Object == nil {
|
||||
break
|
||||
}
|
||||
object := event.Object.(*v1beta1.StorageClass)
|
||||
if event.Type == watch.Deleted {
|
||||
db.Where("name=?", object.Name).Find(&sc)
|
||||
db.Delete(sc)
|
||||
break
|
||||
}
|
||||
obj := ctl.generateObject(*object)
|
||||
db.Save(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (ctl *StorageClassCtl) CountWithConditions(conditions string) int {
|
||||
var object StorageClass
|
||||
|
||||
return countWithConditions(ctl.DB, conditions, &object)
|
||||
}
|
||||
|
||||
func (ctl *StorageClassCtl) ListWithConditions(conditions string, paging *Paging) (int, interface{}, error) {
|
||||
var list []StorageClass
|
||||
var object StorageClass
|
||||
var total int
|
||||
|
||||
order := "createTime desc"
|
||||
|
||||
listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order)
|
||||
|
||||
for index, storageClass := range list {
|
||||
name := storageClass.Name
|
||||
annotation := make(map[string]string)
|
||||
json.Unmarshal([]byte(storageClass.AnnotationStr), &annotation)
|
||||
list[index].Annotation = annotation
|
||||
list[index].AnnotationStr = ""
|
||||
pvcCtl := PvcCtl{CommonAttribute{K8sClient: ctl.K8sClient, DB: ctl.DB}}
|
||||
|
||||
list[index].Count = pvcCtl.CountWithConditions(fmt.Sprintf("storage_class=\"%s\"", name))
|
||||
}
|
||||
|
||||
return total, list, nil
|
||||
}
|
||||
|
||||
func (ctl *StorageClassCtl) Count(name string) int {
|
||||
var count int
|
||||
db := ctl.DB
|
||||
db.Model(&StorageClass{}).Count(&count)
|
||||
return count
|
||||
}
|
||||
361
pkg/models/controllers/types.go
Normal file
361
pkg/models/controllers/types.go
Normal file
@@ -0,0 +1,361 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
const (
|
||||
stopping = "stopped"
|
||||
running = "running"
|
||||
updating = "updating"
|
||||
tablePods = "pods"
|
||||
tableDeployments = "deployments"
|
||||
tableDaemonsets = "daemonsets"
|
||||
tableStatefulsets = "statefulsets"
|
||||
tableNamespaces = "namespaces"
|
||||
tableIngresses = "ingresses"
|
||||
tablePersistentVolumeClaim = "pvcs"
|
||||
tableRoles = "roles"
|
||||
tableClusterRoles = "cluster_roles"
|
||||
tableServices = "services"
|
||||
tableStorageClasses = "storage_classes"
|
||||
|
||||
Pods = "pods"
|
||||
Deployments = "deployments"
|
||||
Daemonsets = "daemonsets"
|
||||
Statefulsets = "statefulsets"
|
||||
Namespaces = "namespaces"
|
||||
Ingresses = "ingresses"
|
||||
PersistentVolumeClaim = "persistent-volume-claims"
|
||||
Roles = "roles"
|
||||
ClusterRoles = "cluster-roles"
|
||||
Services = "services"
|
||||
StorageClasses = "storage-classes"
|
||||
)
|
||||
|
||||
var ResourceTable = map[string]string{Deployments: tableDeployments, Statefulsets: tableStatefulsets, Daemonsets: tableDaemonsets,
|
||||
Pods: tablePods, Namespaces: tableNamespaces, Ingresses: tableIngresses, PersistentVolumeClaim: tablePersistentVolumeClaim, Roles: tableRoles,
|
||||
Services: tableServices, StorageClasses: tableStorageClasses, ClusterRoles: tableClusterRoles}
|
||||
|
||||
type Annotation map[string]string
|
||||
|
||||
//
|
||||
//func (annotation *Annotation)Scan(val interface{}) error{
|
||||
// switch val := val.(type){
|
||||
// case string:
|
||||
// return json.Unmarshal([]byte(val), annotation)
|
||||
// case []byte:
|
||||
// return json.Unmarshal(val, annotation)
|
||||
// default:
|
||||
// return errors.New("not support")
|
||||
// }
|
||||
// return nil
|
||||
//}
|
||||
//
|
||||
//func (annotation *Annotation)Value() (driver.Value, error){
|
||||
// bytes, err := json.Marshal(annotation)
|
||||
// return string(bytes), err
|
||||
//}
|
||||
|
||||
type Deployment struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
App string `json:"app,omitempty"`
|
||||
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
UpdateTime time.Time `gorm:"column:updateTime" json:"updateTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Deployment) TableName() string {
|
||||
return tableDeployments
|
||||
}
|
||||
|
||||
type Statefulset struct {
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace,omitempty"`
|
||||
App string `json:"app,omitempty"`
|
||||
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Statefulset) TableName() string {
|
||||
return tableStatefulsets
|
||||
}
|
||||
|
||||
type Daemonset struct {
|
||||
Name string `gorm:"primary_key" json:"name,omitempty"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace,omitempty"`
|
||||
App string `json:"app,omitempty"`
|
||||
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Status string `json:"status"`
|
||||
NodeSelector string `json:"nodeSelector, omitempty"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Daemonset) TableName() string {
|
||||
return tableDaemonsets
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
ServiceType string `json:"type,omitempty"`
|
||||
|
||||
VirtualIp string `json:"virtualIp,omitempty"`
|
||||
ExternalIp string `json:"externalIp,omitempty"`
|
||||
|
||||
Ports string `json:"ports,omitempty"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Service) TableName() string {
|
||||
return tableServices
|
||||
}
|
||||
|
||||
type Pvc struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Capacity string `json:"capacity,omitempty"`
|
||||
AccessMode string `json:"accessMode,omitempty"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
StorageClassName string `gorm:"column:storage_class" json:"storage_class,omitempty"`
|
||||
}
|
||||
|
||||
func (Pvc) TableName() string {
|
||||
return tablePersistentVolumeClaim
|
||||
}
|
||||
|
||||
type Ingress struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Ip string `json:"ip,omitempty"`
|
||||
TlsTermination string `json:"tlsTermination,omitempty"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Ingress) TableName() string {
|
||||
return tableIngresses
|
||||
}
|
||||
|
||||
type Pod struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Node string `json:"node,omitempty"`
|
||||
NodeIp string `json:"nodeIp,omitempty"`
|
||||
PodIp string `json:"podIp,omitempty"`
|
||||
ContainerStr string `gorm:"type:text" json:",omitempty"`
|
||||
Containers []Container `json:"containers,omitempty"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
type Container struct {
|
||||
Name string `json:"name"`
|
||||
Ready bool `json:"ready,omitempty"`
|
||||
Image string `json:"image"`
|
||||
Ports []v1.ContainerPort `json:"ports"`
|
||||
}
|
||||
|
||||
func (Pod) TableName() string {
|
||||
return tablePods
|
||||
}
|
||||
|
||||
type Role struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Namespace string `gorm:"primary_key" json:"namespace"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Role) TableName() string {
|
||||
return tableRoles
|
||||
}
|
||||
|
||||
type ClusterRole struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (ClusterRole) TableName() string {
|
||||
return tableClusterRoles
|
||||
}
|
||||
|
||||
type Namespace struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Creator string `json:"creator,omitempty"`
|
||||
Status string `json:"status"`
|
||||
|
||||
Descrition string `json:"description,omitempty"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
func (Namespace) TableName() string {
|
||||
return tableNamespaces
|
||||
}
|
||||
|
||||
type StorageClass struct {
|
||||
Name string `gorm:"primary_key" json:"name"`
|
||||
Creator string `json:"creator,omitempty"`
|
||||
AnnotationStr string `gorm:"type:text" json:"annotationStr,omitempty"`
|
||||
Annotation Annotation `gorm:"-" json:"annotation"`
|
||||
CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"`
|
||||
IsDefault bool `json:"default"`
|
||||
Count int `json:"count"`
|
||||
}
|
||||
|
||||
func (StorageClass) TableName() string {
|
||||
return tableStorageClasses
|
||||
}
|
||||
|
||||
type Paging struct {
|
||||
Limit, Offset int
|
||||
}
|
||||
|
||||
type Controller interface {
|
||||
listAndWatch()
|
||||
chanStop() chan struct{}
|
||||
chanAlive() chan struct{}
|
||||
Count(conditions string) int
|
||||
ListWithConditions(condition string, paging *Paging) (int, interface{}, error)
|
||||
}
|
||||
|
||||
type CommonAttribute struct {
|
||||
K8sClient *kubernetes.Clientset
|
||||
DB *gorm.DB
|
||||
stopChan chan struct{}
|
||||
aliveChan chan struct{}
|
||||
}
|
||||
|
||||
func (ca *CommonAttribute) chanStop() chan struct{} {
|
||||
|
||||
return ca.stopChan
|
||||
}
|
||||
|
||||
func (ca *CommonAttribute) chanAlive() chan struct{} {
|
||||
|
||||
return ca.aliveChan
|
||||
}
|
||||
|
||||
type DeploymentCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type StatefulsetCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type DaemonsetCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type ServiceCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type PvcCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type PodCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type IngressCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type NamespaceCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type StorageClassCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type RoleCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
type ClusterRoleCtl struct {
|
||||
CommonAttribute
|
||||
}
|
||||
|
||||
func listWithConditions(db *gorm.DB, total *int, object, list interface{}, conditions string, paging *Paging, order string) {
|
||||
if len(conditions) == 0 {
|
||||
db.Model(object).Count(total)
|
||||
} else {
|
||||
db.Model(object).Where(conditions).Count(total)
|
||||
}
|
||||
|
||||
if paging != nil {
|
||||
if len(conditions) > 0 {
|
||||
db.Where(conditions).Order(order).Limit(paging.Limit).Offset(paging.Offset).Find(list)
|
||||
} else {
|
||||
db.Order(order).Limit(paging.Limit).Offset(paging.Offset).Find(list)
|
||||
}
|
||||
|
||||
} else {
|
||||
if len(conditions) > 0 {
|
||||
db.Where(conditions).Order(order).Find(list)
|
||||
} else {
|
||||
db.Order(order).Find(list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func countWithConditions(db *gorm.DB, conditions string, object interface{}) int {
|
||||
var count int
|
||||
if len(conditions) == 0 {
|
||||
db.Model(object).Count(&count)
|
||||
} else {
|
||||
db.Model(object).Where(conditions).Count(&count)
|
||||
}
|
||||
return count
|
||||
}
|
||||
@@ -1,231 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cronjobs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/jobs/resources"
|
||||
)
|
||||
|
||||
const (
|
||||
pods = "count/pods"
|
||||
daemonsets = "count/daemonsets.apps"
|
||||
deployments = "count/deployments.apps"
|
||||
ingress = "count/ingresses.extensions"
|
||||
roles = "count/roles.rbac.authorization.k8s.io"
|
||||
services = "count/services"
|
||||
statefulsets = "count/statefulsets.apps"
|
||||
persistentvolumeclaims = "persistentvolumeclaims"
|
||||
)
|
||||
|
||||
type resourceUsage struct {
|
||||
NameSpace string
|
||||
Data v1.ResourceQuotaStatus
|
||||
UpdateTimeStamp int64
|
||||
}
|
||||
|
||||
type resourceQuotaWorker struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
resChan chan dataType
|
||||
stopChan chan struct{}
|
||||
}
|
||||
|
||||
func (ru resourceUsage) namespace() string {
|
||||
return ru.NameSpace
|
||||
}
|
||||
|
||||
type workloadList map[string][]resources.WorkLoadObject
|
||||
|
||||
type otherResourceList map[string][]resources.OtherResourceObject
|
||||
|
||||
type workload struct {
|
||||
ResourceType string `json:"type"`
|
||||
ResourceList workloadList `json:"lists"`
|
||||
UpdateTimeStamp int64 `json:"updateTimestamp"`
|
||||
}
|
||||
|
||||
type otherResource struct {
|
||||
ResourceType string `json:"type"`
|
||||
ResourceList otherResourceList `json:"lists"`
|
||||
UpdateTimeStamp int64 `json:"updateTimestamp"`
|
||||
}
|
||||
|
||||
var workLoads = []string{"deployments", "daemonsets", "statefulsets"}
|
||||
|
||||
var resourceMap = map[string]string{daemonsets: "daemonsets", deployments: "deployments", ingress: "ingresses",
|
||||
roles: "roles", services: "services", statefulsets: "statefulsets", persistentvolumeclaims: "persistent-volume-claim", pods: "pods"}
|
||||
|
||||
func contain(items []string, item string) bool {
|
||||
for _, v := range items {
|
||||
if v == item {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (rw *resourceQuotaWorker) getResourceusage(namespace, resourceName string) (int, error) {
|
||||
|
||||
etcdcli, err := client.NewEtcdClient()
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
defer etcdcli.Close()
|
||||
key := constants.Root + "/" + resourceName
|
||||
value, err := etcdcli.Get(key)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
if contain(workLoads, resourceName) {
|
||||
resourceStatus := workload{ResourceList: make(workloadList)}
|
||||
|
||||
err := json.Unmarshal(value, &resourceStatus)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
return len(resourceStatus.ResourceList[namespace]), nil
|
||||
} else {
|
||||
resourceStatus := otherResource{ResourceList: make(otherResourceList)}
|
||||
|
||||
err := json.Unmarshal(value, &resourceStatus)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return len(resourceStatus.ResourceList[namespace]), nil
|
||||
}
|
||||
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (rw *resourceQuotaWorker) updateNamespaceQuota(tmpResourceList, resourceList v1.ResourceList) {
|
||||
if tmpResourceList == nil {
|
||||
tmpResourceList = resourceList
|
||||
}
|
||||
for resource, usage := range resourceList {
|
||||
tmpUsage, exist := tmpResourceList[resource]
|
||||
if !exist {
|
||||
tmpResourceList[resource] = usage
|
||||
}
|
||||
if tmpUsage.Cmp(usage) == 1 {
|
||||
tmpResourceList[resource] = usage
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (rw *resourceQuotaWorker) getNamespaceResourceUsageByQuota(namespace string) (*v1.ResourceQuotaStatus, error) {
|
||||
quotaList, err := rw.k8sClient.CoreV1().ResourceQuotas(namespace).List(meta_v1.ListOptions{})
|
||||
if err != nil || len(quotaList.Items) == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
quotaStatus := v1.ResourceQuotaStatus{Hard: make(v1.ResourceList), Used: make(v1.ResourceList)}
|
||||
|
||||
for _, quota := range quotaList.Items {
|
||||
rw.updateNamespaceQuota(quotaStatus.Hard, quota.Status.Hard)
|
||||
rw.updateNamespaceQuota(quotaStatus.Used, quota.Status.Used)
|
||||
}
|
||||
|
||||
return "aStatus, nil
|
||||
}
|
||||
|
||||
func (rw *resourceQuotaWorker) getNamespaceQuota(namespace string) (v1.ResourceQuotaStatus, error) {
|
||||
quota, err := rw.getNamespaceResourceUsageByQuota(namespace)
|
||||
if err != nil {
|
||||
return v1.ResourceQuotaStatus{}, err
|
||||
}
|
||||
|
||||
if quota == nil {
|
||||
quota = new(v1.ResourceQuotaStatus)
|
||||
quota.Used = make(v1.ResourceList)
|
||||
}
|
||||
|
||||
for k, v := range resourceMap {
|
||||
if _, exist := quota.Used[v1.ResourceName(k)]; !exist {
|
||||
used, err := rw.getResourceusage(namespace, v)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
var quantity resource.Quantity
|
||||
quantity.Set(int64(used))
|
||||
quota.Used[v1.ResourceName(k)] = quantity
|
||||
}
|
||||
}
|
||||
|
||||
return *quota, nil
|
||||
}
|
||||
|
||||
func (rw *resourceQuotaWorker) workOnce() {
|
||||
clusterQuota := new(v1.ResourceQuotaStatus)
|
||||
clusterQuota.Used = make(v1.ResourceList)
|
||||
namespaces, err := rw.k8sClient.CoreV1().Namespaces().List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, ns := range namespaces.Items {
|
||||
namespace := ns.Name
|
||||
nsquota, err := rw.getNamespaceQuota(namespace)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
res := resourceUsage{NameSpace: namespace, Data: nsquota, UpdateTimeStamp: time.Now().Unix()}
|
||||
rw.resChan <- res
|
||||
|
||||
for k, v := range nsquota.Used {
|
||||
tmp := clusterQuota.Used[k]
|
||||
tmp.Add(v)
|
||||
clusterQuota.Used[k] = tmp
|
||||
}
|
||||
}
|
||||
|
||||
var quantity resource.Quantity
|
||||
quantity.Set(int64(len(namespaces.Items)))
|
||||
|
||||
clusterQuota.Used["count/namespaces"] = quantity
|
||||
res := resourceUsage{NameSpace: "\"\"", Data: *clusterQuota, UpdateTimeStamp: time.Now().Unix()}
|
||||
rw.resChan <- res
|
||||
|
||||
}
|
||||
|
||||
func (rw *resourceQuotaWorker) chanStop() chan struct{} {
|
||||
return rw.stopChan
|
||||
}
|
||||
|
||||
func (rw *resourceQuotaWorker) chanRes() chan dataType {
|
||||
return rw.resChan
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cronjobs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
var etcdClient *client.EtcdClient
|
||||
|
||||
var stopChan = make(chan struct{})
|
||||
|
||||
type dataType interface {
|
||||
namespace() string
|
||||
}
|
||||
|
||||
type Worker interface {
|
||||
workOnce()
|
||||
chanRes() chan dataType
|
||||
chanStop() chan struct{}
|
||||
}
|
||||
|
||||
func registerWorker(workers map[string]Worker, name string) {
|
||||
|
||||
glog.Infof("Register cronjob: %s", name)
|
||||
k8sClient := client.NewK8sClient()
|
||||
switch name {
|
||||
case constants.WorkloadStatusKey:
|
||||
worker := workloadWorker{k8sClient: k8sClient, stopChan: stopChan, resChan: make(chan dataType, 10)}
|
||||
workers[constants.WorkloadStatusKey] = &worker
|
||||
case constants.QuotaKey:
|
||||
worker := resourceQuotaWorker{k8sClient: k8sClient, stopChan: stopChan, resChan: make(chan dataType, 10)}
|
||||
workers[constants.QuotaKey] = &worker
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func run(worker Worker) {
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
close(worker.chanRes())
|
||||
}
|
||||
}()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-worker.chanStop():
|
||||
return
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
worker.workOnce()
|
||||
time.Sleep(time.Duration(constants.UpdateCircle) * time.Second)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func startWorks(workers map[string]Worker) {
|
||||
for wokername, woker := range workers {
|
||||
glog.Infof("cronjob %s start to work", wokername)
|
||||
go run(woker)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func receiveResourceStatus(workers map[string]Worker) {
|
||||
defer func() {
|
||||
close(stopChan)
|
||||
}()
|
||||
|
||||
for {
|
||||
for name, worker := range workers {
|
||||
select {
|
||||
case res, ok := <-worker.chanRes():
|
||||
if !ok {
|
||||
glog.Errorf("cronjob:%s have stopped", name)
|
||||
registerWorker(workers, name)
|
||||
run(workers[name])
|
||||
} else {
|
||||
value, err := json.Marshal(res)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
continue
|
||||
}
|
||||
key := constants.Root + "/" + name + "/" + res.namespace()
|
||||
err = etcdClient.Put(key, string(value))
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Run() {
|
||||
glog.Info("Begin to run cronjob")
|
||||
var err error
|
||||
etcdClient, err = client.NewEtcdClient()
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
defer etcdClient.Close()
|
||||
workers := make(map[string]Worker)
|
||||
workerList := []string{constants.QuotaKey, constants.WorkloadStatusKey}
|
||||
for _, name := range workerList {
|
||||
registerWorker(workers, name)
|
||||
}
|
||||
startWorks(workers)
|
||||
receiveResourceStatus(workers)
|
||||
}
|
||||
@@ -1,104 +0,0 @@
|
||||
package cronjobs
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
var workLoadList = []string{"deployments", "daemonsets", "statefulsets"}
|
||||
|
||||
type workLoadStatus struct {
|
||||
NameSpace string
|
||||
Data map[string]int
|
||||
UpdateTimeStamp int64
|
||||
}
|
||||
|
||||
func (ws workLoadStatus) namespace() string {
|
||||
return ws.NameSpace
|
||||
}
|
||||
|
||||
type workloadWorker struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
resChan chan dataType
|
||||
stopChan chan struct{}
|
||||
}
|
||||
|
||||
func (ww *workloadWorker) GetNamespacesResourceStatus(namespace string) (map[string]int, error) {
|
||||
|
||||
cli, err := client.NewEtcdClient()
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
defer cli.Close()
|
||||
|
||||
res := make(map[string]int)
|
||||
|
||||
for _, resourceName := range workLoadList {
|
||||
key := constants.Root + "/" + resourceName
|
||||
value, err := cli.Get(key)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
resourceStatus := workload{ResourceList: make(workloadList)}
|
||||
|
||||
err = json.Unmarshal(value, &resourceStatus)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
notReady := 0
|
||||
for _, v := range resourceStatus.ResourceList[namespace] {
|
||||
if !v.Ready {
|
||||
notReady++
|
||||
}
|
||||
}
|
||||
res[resourceName] = notReady
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (ww workloadWorker) workOnce() {
|
||||
namespaces, err := ww.k8sClient.CoreV1().Namespaces().List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
resourceStatus := make(map[string]int)
|
||||
for _, item := range namespaces.Items {
|
||||
namespace := item.Name
|
||||
namespacesResourceStatus, err := ww.GetNamespacesResourceStatus(namespace)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
|
||||
var ws = workLoadStatus{UpdateTimeStamp: time.Now().Unix(), Data: namespacesResourceStatus, NameSpace: namespace}
|
||||
ww.resChan <- ws
|
||||
|
||||
for k, v := range namespacesResourceStatus {
|
||||
resourceStatus[k] = v + resourceStatus[k]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var ws = workLoadStatus{UpdateTimeStamp: time.Now().Unix(), Data: resourceStatus, NameSpace: "\"\""}
|
||||
ww.resChan <- ws
|
||||
}
|
||||
|
||||
func (ww workloadWorker) chanRes() chan dataType {
|
||||
return ww.resChan
|
||||
}
|
||||
|
||||
func (ww workloadWorker) chanStop() chan struct{} {
|
||||
return ww.stopChan
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type daemonset struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (ds *daemonset) list() (interface{}, error) {
|
||||
daemonsetList, err := ds.k8sClient.AppsV1beta2().DaemonSets("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return daemonsetList.Items, nil
|
||||
}
|
||||
|
||||
func (ds *daemonset) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := ds.k8sClient.AppsV1beta2().DaemonSets("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (ds *daemonset) generateObject(item v1beta2.DaemonSet) WorkLoadObject {
|
||||
var app string
|
||||
var ready bool
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.CurrentNumberScheduled
|
||||
desirePodNum := item.Status.DesiredNumberScheduled
|
||||
createTime := item.CreationTimestamp
|
||||
release := item.ObjectMeta.Labels["release"]
|
||||
nodeSelector := item.Spec.Template.Spec.NodeSelector
|
||||
chart := item.ObjectMeta.Labels["chart"]
|
||||
|
||||
if len(release) > 0 && len(chart) > 0 {
|
||||
app = release + "/" + chart
|
||||
} else {
|
||||
app = "-"
|
||||
}
|
||||
|
||||
if availablePodNum >= desirePodNum {
|
||||
ready = true
|
||||
} else {
|
||||
ready = false
|
||||
}
|
||||
|
||||
workloadObject := WorkLoadObject{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, CreateTime: createTime, Ready: ready, NodeSelector: nodeSelector}
|
||||
|
||||
return workloadObject
|
||||
|
||||
}
|
||||
|
||||
func (ds *daemonset) updateWithObject(status *ResourceStatus, item v1beta2.DaemonSet) {
|
||||
namespace := item.Namespace
|
||||
dsObject := ds.generateObject(item)
|
||||
|
||||
status.ResourceList.update(namespace, dsObject)
|
||||
}
|
||||
|
||||
func (ds *daemonset) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1beta2.DaemonSet)
|
||||
|
||||
for _, item := range items {
|
||||
ds.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (ds *daemonset) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1beta2.DaemonSet)
|
||||
namespace := object.Namespace
|
||||
daemonsetObject := ds.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, daemonsetObject)
|
||||
return
|
||||
}
|
||||
|
||||
ds.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type deployment struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (deploy *deployment) list() (interface{}, error) {
|
||||
deoloyList, err := deploy.k8sClient.AppsV1beta2().Deployments("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return deoloyList.Items, nil
|
||||
}
|
||||
|
||||
func (deploy *deployment) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := deploy.k8sClient.AppsV1beta2().Deployments("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (deploy *deployment) generateObject(item v1beta2.Deployment) WorkLoadObject {
|
||||
var app string
|
||||
var ready bool
|
||||
var updateTime meta_v1.Time
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.AvailableReplicas
|
||||
desirePodNum := *item.Spec.Replicas
|
||||
release := item.ObjectMeta.Labels["release"]
|
||||
chart := item.ObjectMeta.Labels["chart"]
|
||||
|
||||
if len(release) > 0 && len(chart) > 0 {
|
||||
app = release + "/" + chart
|
||||
} else {
|
||||
app = "-"
|
||||
}
|
||||
|
||||
for _, conditon := range item.Status.Conditions {
|
||||
if conditon.Type == "Progressing" {
|
||||
updateTime = conditon.LastUpdateTime
|
||||
}
|
||||
}
|
||||
|
||||
if availablePodNum >= desirePodNum {
|
||||
ready = true
|
||||
} else {
|
||||
ready = false
|
||||
}
|
||||
|
||||
deployObject := WorkLoadObject{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, UpdateTime: updateTime, Ready: ready}
|
||||
|
||||
return deployObject
|
||||
|
||||
}
|
||||
|
||||
func (deploy *deployment) updateWithObject(status *ResourceStatus, item v1beta2.Deployment) {
|
||||
namespace := item.Namespace
|
||||
|
||||
deployObject := deploy.generateObject(item)
|
||||
status.ResourceList.update(namespace, deployObject)
|
||||
}
|
||||
|
||||
func (deploy *deployment) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1beta2.Deployment)
|
||||
|
||||
for _, item := range items {
|
||||
deploy.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (deploy *deployment) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1beta2.Deployment)
|
||||
namespace := object.Namespace
|
||||
deployObject := deploy.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, deployObject)
|
||||
return
|
||||
}
|
||||
|
||||
deploy.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/extensions/v1beta1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type ingress struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (ing *ingress) list() (interface{}, error) {
|
||||
list, err := ing.k8sClient.ExtensionsV1beta1().Ingresses("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list.Items, nil
|
||||
}
|
||||
|
||||
func (ing *ingress) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := ing.k8sClient.ExtensionsV1beta1().Ingresses("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (ing *ingress) generateObject(item v1beta1.Ingress) OtherResourceObject {
|
||||
name := item.Name
|
||||
ns := item.Namespace
|
||||
|
||||
object := OtherResourceObject{Namespace: ns, Name: name}
|
||||
|
||||
return object
|
||||
|
||||
}
|
||||
|
||||
func (ing *ingress) updateWithObject(status *ResourceStatus, item v1beta1.Ingress) {
|
||||
namespace := item.Namespace
|
||||
|
||||
object := ing.generateObject(item)
|
||||
status.ResourceList.update(namespace, object)
|
||||
}
|
||||
|
||||
func (ing *ingress) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1beta1.Ingress)
|
||||
|
||||
for _, item := range items {
|
||||
ing.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (ing *ingress) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1beta1.Ingress)
|
||||
namespace := object.Namespace
|
||||
tmpObject := ing.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, tmpObject)
|
||||
return
|
||||
}
|
||||
|
||||
ing.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type namespace struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (ns *namespace) list() (interface{}, error) {
|
||||
nsList, err := ns.k8sClient.CoreV1().Namespaces().List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nsList.Items, nil
|
||||
}
|
||||
|
||||
func (ns *namespace) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := ns.k8sClient.CoreV1().Namespaces().Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (ns *namespace) generateObject(item v1.Namespace) OtherResourceObject {
|
||||
name := item.Name
|
||||
nsp := item.Namespace
|
||||
|
||||
object := OtherResourceObject{Namespace: nsp, Name: name}
|
||||
|
||||
return object
|
||||
|
||||
}
|
||||
|
||||
func (ns *namespace) updateWithObject(status *ResourceStatus, item v1.Namespace) {
|
||||
namespace := item.Namespace
|
||||
|
||||
object := ns.generateObject(item)
|
||||
status.ResourceList.update(namespace, object)
|
||||
}
|
||||
|
||||
func (ns *namespace) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1.Namespace)
|
||||
|
||||
for _, item := range items {
|
||||
ns.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (ns *namespace) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1.Namespace)
|
||||
namespace := object.Namespace
|
||||
tmpObject := ns.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, tmpObject)
|
||||
return
|
||||
}
|
||||
|
||||
ns.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type pod struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (po *pod) list() (interface{}, error) {
|
||||
list, err := po.k8sClient.CoreV1().Pods("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list.Items, nil
|
||||
}
|
||||
|
||||
func (po *pod) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := po.k8sClient.CoreV1().Pods("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (po *pod) generateObject(item v1.Pod) OtherResourceObject {
|
||||
name := item.Name
|
||||
ns := item.Namespace
|
||||
|
||||
Object := OtherResourceObject{Namespace: ns, Name: name}
|
||||
|
||||
return Object
|
||||
|
||||
}
|
||||
|
||||
func (po *pod) updateWithObject(status *ResourceStatus, item v1.Pod) {
|
||||
namespace := item.Namespace
|
||||
|
||||
object := po.generateObject(item)
|
||||
status.ResourceList.update(namespace, object)
|
||||
}
|
||||
|
||||
func (po *pod) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1.Pod)
|
||||
|
||||
for _, item := range items {
|
||||
po.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (po *pod) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1.Pod)
|
||||
namespace := object.Namespace
|
||||
tmpObject := po.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, tmpObject)
|
||||
return
|
||||
}
|
||||
|
||||
po.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type persistmentVolume struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (pvc *persistmentVolume) list() (interface{}, error) {
|
||||
list, err := pvc.k8sClient.CoreV1().PersistentVolumeClaims("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list.Items, nil
|
||||
}
|
||||
|
||||
func (pvc *persistmentVolume) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := pvc.k8sClient.CoreV1().PersistentVolumeClaims("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (pvc *persistmentVolume) generateObject(item v1.PersistentVolumeClaim) OtherResourceObject {
|
||||
name := item.Name
|
||||
ns := item.Namespace
|
||||
|
||||
object := OtherResourceObject{Namespace: ns, Name: name}
|
||||
|
||||
return object
|
||||
|
||||
}
|
||||
|
||||
func (pvc *persistmentVolume) updateWithObject(status *ResourceStatus, item v1.PersistentVolumeClaim) {
|
||||
namespace := item.Namespace
|
||||
|
||||
object := pvc.generateObject(item)
|
||||
status.ResourceList.update(namespace, object)
|
||||
}
|
||||
|
||||
func (pvc *persistmentVolume) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1.PersistentVolumeClaim)
|
||||
|
||||
for _, item := range items {
|
||||
pvc.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (pvc *persistmentVolume) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1.PersistentVolumeClaim)
|
||||
namespace := object.Namespace
|
||||
tmpObject := pvc.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, tmpObject)
|
||||
return
|
||||
}
|
||||
|
||||
pvc.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/rbac/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type role struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (r *role) list() (interface{}, error) {
|
||||
list, err := r.k8sClient.RbacV1().Roles("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list.Items, nil
|
||||
}
|
||||
|
||||
func (r *role) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := r.k8sClient.RbacV1().Roles("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (r *role) generateObject(item v1.Role) OtherResourceObject {
|
||||
name := item.Name
|
||||
ns := item.Namespace
|
||||
|
||||
object := OtherResourceObject{Namespace: ns, Name: name}
|
||||
|
||||
return object
|
||||
|
||||
}
|
||||
|
||||
func (r *role) updateWithObject(status *ResourceStatus, item v1.Role) {
|
||||
namespace := item.Namespace
|
||||
|
||||
object := r.generateObject(item)
|
||||
status.ResourceList.update(namespace, object)
|
||||
}
|
||||
|
||||
func (r *role) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1.Role)
|
||||
|
||||
for _, item := range items {
|
||||
r.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (r *role) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1.Role)
|
||||
namespace := object.Namespace
|
||||
tmpObject := r.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, tmpObject)
|
||||
return
|
||||
}
|
||||
|
||||
r.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
var etcdClient *client.EtcdClient
|
||||
|
||||
var stopChan = make(chan struct{})
|
||||
|
||||
const (
|
||||
pods = "pods"
|
||||
deployments = "deployments"
|
||||
daemonsets = "daemonsets"
|
||||
statefulsets = "statefulsets"
|
||||
namespaces = "namespaces"
|
||||
ingresses = "ingresses"
|
||||
persistentVolumeClaim = "persistent-volume-claim"
|
||||
roles = "roles"
|
||||
services = "services"
|
||||
)
|
||||
|
||||
func registerResource(resourceChans map[string]ResourceChan, resourceType string) {
|
||||
resourceChan := ResourceChan{Type: resourceType, StatusChan: make(chan *ResourceStatus), StopChan: stopChan}
|
||||
resourceChans[resourceType] = resourceChan
|
||||
}
|
||||
|
||||
func updateStatus(resource Resource, resourceChan ResourceChan) {
|
||||
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
glog.Error(err)
|
||||
close(resourceChan.StatusChan)
|
||||
}
|
||||
}()
|
||||
|
||||
var clusterStatus ResourceStatus
|
||||
clusterStatus.UpdateTimeStamp = time.Now().Unix()
|
||||
clusterStatus.ResourceType = resourceChan.Type
|
||||
|
||||
items, err := resource.list()
|
||||
if err != nil {
|
||||
glog.Errorln(err)
|
||||
return
|
||||
}
|
||||
resource.updateWithObjects(&clusterStatus, items)
|
||||
|
||||
watcher, err := resource.getWatcher()
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return
|
||||
}
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-resourceChan.StopChan:
|
||||
return
|
||||
case event := <-watcher.ResultChan():
|
||||
resource.updateWithEvent(&clusterStatus, event)
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if time.Now().Unix()-clusterStatus.UpdateTimeStamp > constants.UpdateCircle {
|
||||
clusterStatus.UpdateTimeStamp = time.Now().Unix()
|
||||
resourceChan.StatusChan <- &clusterStatus
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func updateResourceStatus(resourceChan ResourceChan) {
|
||||
glog.Infof("updateResourceStatus:%s", resourceChan.Type)
|
||||
client := client.NewK8sClient()
|
||||
switch resourceChan.Type {
|
||||
case deployments:
|
||||
deploy := deployment{k8sClient: client}
|
||||
go updateStatus(&deploy, resourceChan)
|
||||
case daemonsets:
|
||||
ds := daemonset{k8sClient: client}
|
||||
go updateStatus(&ds, resourceChan)
|
||||
case statefulsets:
|
||||
ss := statefulset{k8sClient: client}
|
||||
go updateStatus(&ss, resourceChan)
|
||||
case namespaces:
|
||||
ns := namespace{k8sClient: client}
|
||||
go updateStatus(&ns, resourceChan)
|
||||
case ingresses:
|
||||
ing := ingress{k8sClient: client}
|
||||
go updateStatus(&ing, resourceChan)
|
||||
case persistentVolumeClaim:
|
||||
pvc := persistmentVolume{k8sClient: client}
|
||||
go updateStatus(&pvc, resourceChan)
|
||||
case roles:
|
||||
r := role{k8sClient: client}
|
||||
go updateStatus(&r, resourceChan)
|
||||
case services:
|
||||
svc := service{k8sClient: client}
|
||||
go updateStatus(&svc, resourceChan)
|
||||
case pods:
|
||||
po := pod{k8sClient: client}
|
||||
go updateStatus(&po, resourceChan)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func updateAllResourceStatus(resourceChans map[string]ResourceChan) {
|
||||
for _, resourceChan := range resourceChans {
|
||||
updateResourceStatus(resourceChan)
|
||||
}
|
||||
}
|
||||
|
||||
func receiveResourceStatus(resourceChans map[string]ResourceChan) {
|
||||
defer func() {
|
||||
close(stopChan)
|
||||
}()
|
||||
|
||||
for {
|
||||
for _, resourceChan := range resourceChans {
|
||||
select {
|
||||
case res, ok := <-resourceChan.StatusChan:
|
||||
if !ok {
|
||||
glog.Errorf("job:calculate %s' status have stopped", resourceChan.Type)
|
||||
registerResource(resourceChans, resourceChan.Type)
|
||||
updateResourceStatus(resourceChans[resourceChan.Type])
|
||||
} else {
|
||||
value, _ := json.Marshal(res)
|
||||
key := constants.Root + "/" + res.ResourceType
|
||||
etcdClient.Put(key, string(value))
|
||||
}
|
||||
default:
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func Run() {
|
||||
glog.Info("Begin to submit resource status")
|
||||
var err error
|
||||
etcdClient, err = client.NewEtcdClient()
|
||||
defer etcdClient.Close()
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
}
|
||||
resourceChans := make(map[string]ResourceChan)
|
||||
resourceList := []string{statefulsets, deployments, daemonsets, namespaces, ingresses, services, roles, persistentVolumeClaim, pods}
|
||||
for _, resource := range resourceList {
|
||||
registerResource(resourceChans, resource)
|
||||
}
|
||||
updateAllResourceStatus(resourceChans)
|
||||
receiveResourceStatus(resourceChans)
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type service struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (svc *service) list() (interface{}, error) {
|
||||
list, err := svc.k8sClient.CoreV1().Services("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list.Items, nil
|
||||
}
|
||||
|
||||
func (svc *service) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := svc.k8sClient.CoreV1().Services("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (svc *service) generateObject(item v1.Service) OtherResourceObject {
|
||||
name := item.Name
|
||||
ns := item.Namespace
|
||||
|
||||
object := OtherResourceObject{Namespace: ns, Name: name}
|
||||
|
||||
return object
|
||||
|
||||
}
|
||||
|
||||
func (svc *service) updateWithObject(status *ResourceStatus, item v1.Service) {
|
||||
namespace := item.Namespace
|
||||
|
||||
object := svc.generateObject(item)
|
||||
status.ResourceList.update(namespace, object)
|
||||
}
|
||||
|
||||
func (svc *service) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1.Service)
|
||||
|
||||
for _, item := range items {
|
||||
svc.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (svc *service) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1.Service)
|
||||
namespace := object.Namespace
|
||||
tmpObject := svc.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, tmpObject)
|
||||
return
|
||||
}
|
||||
|
||||
svc.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"k8s.io/api/apps/v1beta2"
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
type statefulset struct {
|
||||
k8sClient *kubernetes.Clientset
|
||||
}
|
||||
|
||||
func (ss *statefulset) list() (interface{}, error) {
|
||||
daemonsetList, err := ss.k8sClient.AppsV1beta2().StatefulSets("").List(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return daemonsetList.Items, nil
|
||||
}
|
||||
|
||||
func (ss *statefulset) getWatcher() (watch.Interface, error) {
|
||||
watcher, err := ss.k8sClient.AppsV1beta2().StatefulSets("").Watch(meta_v1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return watcher, nil
|
||||
}
|
||||
|
||||
func (ss *statefulset) generateObject(item v1beta2.StatefulSet) WorkLoadObject {
|
||||
var app string
|
||||
var ready bool
|
||||
name := item.Name
|
||||
namespace := item.Namespace
|
||||
availablePodNum := item.Status.ReadyReplicas
|
||||
desirePodNum := *item.Spec.Replicas
|
||||
createTime := item.CreationTimestamp
|
||||
release := item.ObjectMeta.Labels["release"]
|
||||
chart := item.ObjectMeta.Labels["chart"]
|
||||
|
||||
if len(release) > 0 && len(chart) > 0 {
|
||||
app = release + "/" + chart
|
||||
} else {
|
||||
app = "-"
|
||||
}
|
||||
if availablePodNum >= desirePodNum {
|
||||
ready = true
|
||||
} else {
|
||||
ready = false
|
||||
}
|
||||
|
||||
statefulSetObject := WorkLoadObject{Namespace: namespace, Name: name, Available: availablePodNum, Desire: desirePodNum,
|
||||
App: app, CreateTime: createTime, Ready: ready}
|
||||
|
||||
return statefulSetObject
|
||||
|
||||
}
|
||||
|
||||
func (ss *statefulset) updateWithObject(status *ResourceStatus, item v1beta2.StatefulSet) {
|
||||
namespace := item.Namespace
|
||||
ssObject := ss.generateObject(item)
|
||||
|
||||
status.ResourceList.update(namespace, ssObject)
|
||||
|
||||
}
|
||||
|
||||
func (ss *statefulset) updateWithObjects(status *ResourceStatus, objects interface{}) {
|
||||
if status.ResourceList == nil {
|
||||
status.ResourceList = make(Resources)
|
||||
}
|
||||
|
||||
items := objects.([]v1beta2.StatefulSet)
|
||||
|
||||
for _, item := range items {
|
||||
ss.updateWithObject(status, item)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (ss *statefulset) updateWithEvent(status *ResourceStatus, event watch.Event) {
|
||||
object := event.Object.(*v1beta2.StatefulSet)
|
||||
namespace := object.Namespace
|
||||
ssObject := ss.generateObject(*object)
|
||||
|
||||
if event.Type == watch.Deleted {
|
||||
status.ResourceList.del(namespace, ssObject)
|
||||
return
|
||||
}
|
||||
|
||||
ss.updateWithObject(status, *object)
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
)
|
||||
|
||||
type resource interface {
|
||||
equal(object resource) bool
|
||||
}
|
||||
|
||||
type resourcetList interface {
|
||||
update(key string, value resource)
|
||||
del(key string, value resource)
|
||||
}
|
||||
|
||||
type ResourceStatus struct {
|
||||
ResourceType string `json:"type"`
|
||||
ResourceList resourcetList `json:"lists"`
|
||||
UpdateTimeStamp int64 `json:"updateTimestamp"`
|
||||
}
|
||||
|
||||
type ResourceChan struct {
|
||||
Type string
|
||||
StatusChan chan *ResourceStatus
|
||||
StopChan chan struct{}
|
||||
}
|
||||
|
||||
type Resource interface {
|
||||
list() (interface{}, error)
|
||||
getWatcher() (watch.Interface, error)
|
||||
updateWithObjects(workload *ResourceStatus, objects interface{})
|
||||
updateWithEvent(workload *ResourceStatus, event watch.Event)
|
||||
}
|
||||
|
||||
type WorkLoadObject struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
App string `json:"app"`
|
||||
Available int32 `json:"available"`
|
||||
Desire int32 `json:"desire"`
|
||||
Ready bool `json:"ready"`
|
||||
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
|
||||
UpdateTime meta_v1.Time `json:"updateTime,omitempty"`
|
||||
CreateTime meta_v1.Time `json:"createTime,omitempty"`
|
||||
}
|
||||
|
||||
type OtherResourceObject struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace"`
|
||||
}
|
||||
|
||||
type Resources map[string][]resource
|
||||
|
||||
func (resources Resources) update(namespace string, object resource) {
|
||||
for index, tmpObject := range resources[namespace] {
|
||||
if tmpObject.equal(object) {
|
||||
resources[namespace][index] = object
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
resources[namespace] = append(resources[namespace], object)
|
||||
}
|
||||
|
||||
func (resources Resources) del(namespace string, object resource) {
|
||||
for index, tmpObject := range resources[namespace] {
|
||||
if tmpObject.equal(object) {
|
||||
resources[namespace] = append(resources[namespace][:index], resources[namespace][index+1:]...)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (workLoadObject WorkLoadObject) equal(object resource) bool {
|
||||
tmp := object.(WorkLoadObject)
|
||||
if workLoadObject.Name == tmp.Name && workLoadObject.Namespace == tmp.Namespace {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (otherResourceObject OtherResourceObject) equal(object resource) bool {
|
||||
tmp := object.(OtherResourceObject)
|
||||
if otherResourceObject.Name == tmp.Name && otherResourceObject.Namespace == tmp.Namespace {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -17,50 +17,115 @@ limitations under the License.
|
||||
package models
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
)
|
||||
|
||||
const (
|
||||
podsKey = "count/pods"
|
||||
daemonsetsKey = "count/daemonsets.apps"
|
||||
deploymentsKey = "count/deployments.apps"
|
||||
ingressKey = "count/ingresses.extensions"
|
||||
rolesKey = "count/roles.rbac.authorization.k8s.io"
|
||||
clusterRolesKey = "count/cluster-role"
|
||||
servicesKey = "count/services"
|
||||
statefulsetsKey = "count/statefulsets.apps"
|
||||
persistentvolumeclaimsKey = "persistentvolumeclaims"
|
||||
storageClassesKey = "count/storageClass"
|
||||
namespaceKey = "count/namespace"
|
||||
)
|
||||
|
||||
var resourceMap = map[string]string{daemonsetsKey: controllers.Daemonsets, deploymentsKey: controllers.Deployments,
|
||||
ingressKey: controllers.Ingresses, rolesKey: controllers.Roles, servicesKey: controllers.Services,
|
||||
statefulsetsKey: controllers.Statefulsets, persistentvolumeclaimsKey: controllers.PersistentVolumeClaim, podsKey: controllers.Pods,
|
||||
namespaceKey: controllers.Namespaces, storageClassesKey: controllers.StorageClasses, clusterRolesKey: controllers.ClusterRoles}
|
||||
|
||||
type resourceQuota struct {
|
||||
NameSpace string `json:"namespace"`
|
||||
Data v1.ResourceQuotaStatus `json:"data"`
|
||||
UpdateTimeStamp int64 `json:"updateTimeStamp"`
|
||||
NameSpace string `json:"namespace"`
|
||||
Data v1.ResourceQuotaStatus `json:"data"`
|
||||
}
|
||||
|
||||
func GetNamespaceQuota(namespace string) (*resourceQuota, error) {
|
||||
|
||||
cli, err := client.NewEtcdClient()
|
||||
func getUsage(namespace, resource string) int {
|
||||
ctl, err := getController(resource)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return 0
|
||||
}
|
||||
defer cli.Close()
|
||||
|
||||
key := constants.Root + "/" + constants.QuotaKey + "/" + namespace
|
||||
value, err := cli.Get(key)
|
||||
var data = v1.ResourceQuotaStatus{make(v1.ResourceList), make(v1.ResourceList)}
|
||||
var res = resourceQuota{Data: data}
|
||||
|
||||
err = json.Unmarshal(value, &res)
|
||||
if time.Now().Unix()-res.UpdateTimeStamp > 5*constants.UpdateCircle {
|
||||
err = errors.New("internal server error")
|
||||
return nil, err
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
return ctl.Count(namespace)
|
||||
}
|
||||
|
||||
func GetClusterQuota() (*resourceQuota, error) {
|
||||
|
||||
return GetNamespaceQuota("\"\"")
|
||||
quota := v1.ResourceQuotaStatus{Hard: make(v1.ResourceList), Used: make(v1.ResourceList)}
|
||||
for k, v := range resourceMap {
|
||||
used := getUsage("", v)
|
||||
var quantity resource.Quantity
|
||||
quantity.Set(int64(used))
|
||||
quota.Used[v1.ResourceName(k)] = quantity
|
||||
}
|
||||
|
||||
return &resourceQuota{NameSpace: "\"\"", Data: quota}, nil
|
||||
|
||||
}
|
||||
|
||||
func GetNamespaceQuota(namespace string) (*resourceQuota, error) {
|
||||
quota, err := getNamespaceResourceQuota(namespace)
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
if quota == nil {
|
||||
quota = &v1.ResourceQuotaStatus{Hard: make(v1.ResourceList), Used: make(v1.ResourceList)}
|
||||
}
|
||||
|
||||
for k, v := range resourceMap {
|
||||
if _, exist := quota.Used[v1.ResourceName(k)]; !exist {
|
||||
if k == namespaceKey || k == storageClassesKey {
|
||||
continue
|
||||
}
|
||||
|
||||
used := getUsage(namespace, v)
|
||||
var quantity resource.Quantity
|
||||
quantity.Set(int64(used))
|
||||
quota.Used[v1.ResourceName(k)] = quantity
|
||||
}
|
||||
}
|
||||
|
||||
return &resourceQuota{NameSpace: namespace, Data: *quota}, nil
|
||||
}
|
||||
|
||||
func updateNamespaceQuota(tmpResourceList, resourceList v1.ResourceList) {
|
||||
if tmpResourceList == nil {
|
||||
tmpResourceList = resourceList
|
||||
}
|
||||
for resource, usage := range resourceList {
|
||||
tmpUsage, exist := tmpResourceList[resource]
|
||||
if !exist {
|
||||
tmpResourceList[resource] = usage
|
||||
}
|
||||
if tmpUsage.Cmp(usage) == 1 {
|
||||
tmpResourceList[resource] = usage
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getNamespaceResourceQuota(namespace string) (*v1.ResourceQuotaStatus, error) {
|
||||
quotaList, err := client.NewK8sClient().CoreV1().ResourceQuotas(namespace).List(metaV1.ListOptions{})
|
||||
if err != nil || len(quotaList.Items) == 0 {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
quotaStatus := v1.ResourceQuotaStatus{Hard: make(v1.ResourceList), Used: make(v1.ResourceList)}
|
||||
|
||||
for _, quota := range quotaList.Items {
|
||||
updateNamespaceQuota(quotaStatus.Hard, quota.Status.Hard)
|
||||
updateNamespaceQuota(quotaStatus.Used, quota.Status.Used)
|
||||
}
|
||||
|
||||
return "aStatus, nil
|
||||
}
|
||||
|
||||
163
pkg/models/resources.go
Normal file
163
pkg/models/resources.go
Normal file
@@ -0,0 +1,163 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/models/controllers"
|
||||
)
|
||||
|
||||
type ResourceList struct {
|
||||
Total int `json:"total,omitempty"`
|
||||
Page int `json:"page,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Items interface{} `json:"items,omitempty"`
|
||||
}
|
||||
|
||||
func getController(resource string) (controllers.Controller, error) {
|
||||
var ctl controllers.Controller
|
||||
attr := controllers.CommonAttribute{DB: client.NewDBClient()}
|
||||
switch resource {
|
||||
case controllers.Deployments:
|
||||
ctl = &controllers.DeploymentCtl{attr}
|
||||
case controllers.Statefulsets:
|
||||
ctl = &controllers.StatefulsetCtl{attr}
|
||||
case controllers.Daemonsets:
|
||||
ctl = &controllers.DaemonsetCtl{attr}
|
||||
case controllers.Ingresses:
|
||||
ctl = &controllers.IngressCtl{attr}
|
||||
case controllers.PersistentVolumeClaim:
|
||||
ctl = &controllers.PvcCtl{attr}
|
||||
case controllers.Roles:
|
||||
ctl = &controllers.RoleCtl{attr}
|
||||
case controllers.ClusterRoles:
|
||||
ctl = &controllers.ClusterRoleCtl{attr}
|
||||
case controllers.Services:
|
||||
ctl = &controllers.ServiceCtl{attr}
|
||||
case controllers.Pods:
|
||||
ctl = &controllers.PodCtl{attr}
|
||||
case controllers.Namespaces:
|
||||
ctl = &controllers.NamespaceCtl{attr}
|
||||
case controllers.StorageClasses:
|
||||
ctl = &controllers.StorageClassCtl{attr}
|
||||
default:
|
||||
return nil, errors.New("invalid resource type")
|
||||
}
|
||||
return ctl, nil
|
||||
|
||||
}
|
||||
|
||||
func getConditions(str string) (map[string]string, error) {
|
||||
dict := make(map[string]string)
|
||||
if len(str) == 0 {
|
||||
return dict, nil
|
||||
}
|
||||
list := strings.Split(str, ",")
|
||||
for _, item := range list {
|
||||
kvs := strings.Split(item, "=")
|
||||
if len(kvs) < 2 {
|
||||
return nil, errors.New("invalid condition input")
|
||||
}
|
||||
dict[kvs[0]] = kvs[1]
|
||||
}
|
||||
return dict, nil
|
||||
}
|
||||
|
||||
func getPaging(str string) (map[string]int, error) {
|
||||
paging := make(map[string]int)
|
||||
if len(str) == 0 {
|
||||
return paging, nil
|
||||
}
|
||||
list := strings.Split(str, ",")
|
||||
for _, item := range list {
|
||||
kvs := strings.Split(item, "=")
|
||||
if len(kvs) < 2 {
|
||||
return nil, errors.New("invalid Paging input")
|
||||
}
|
||||
|
||||
value, err := strconv.Atoi(kvs[1])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
paging[kvs[0]] = value
|
||||
}
|
||||
return paging, nil
|
||||
}
|
||||
|
||||
func ListResource(resourceName, conditonSrt, pagingStr string) (*ResourceList, error) {
|
||||
conditions, err := getConditions(conditonSrt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pagingMap, err := getPaging(pagingStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conditionStr, paging := generateConditionAndPaging(conditions, pagingMap)
|
||||
|
||||
ctl, err := getController(resourceName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
total, items, err := ctl.ListWithConditions(conditionStr, paging)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &ResourceList{Total: total, Items: items, Page: pagingMap["page"], Limit: pagingMap["limit"]}, nil
|
||||
}
|
||||
|
||||
func generateConditionAndPaging(conditions map[string]string, paging map[string]int) (string, *controllers.Paging) {
|
||||
conditionStr := ""
|
||||
|
||||
for k, v := range conditions {
|
||||
if len(conditionStr) == 0 {
|
||||
conditionStr = fmt.Sprintf("%s = \"%s\" ", k, v)
|
||||
} else {
|
||||
conditionStr = fmt.Sprintf("%s AND %s = \"%s\" ", conditionStr, k, v)
|
||||
}
|
||||
}
|
||||
|
||||
if paging["limit"] > 0 && paging["page"] >= 0 {
|
||||
offset := (paging["page"] - 1) * paging["limit"]
|
||||
return conditionStr, &controllers.Paging{Limit: paging["limit"], Offset: offset}
|
||||
}
|
||||
|
||||
return conditionStr, nil
|
||||
}
|
||||
|
||||
type workLoadStatus struct {
|
||||
NameSpace string `json:"namespace"`
|
||||
Count map[string]int `json:"data"`
|
||||
Items map[string]interface{}
|
||||
}
|
||||
|
||||
func GetNamespacesResourceStatus(namespace string) (*workLoadStatus, error) {
|
||||
|
||||
res := workLoadStatus{Count: make(map[string]int), NameSpace: namespace, Items: make(map[string]interface{})}
|
||||
for _, resource := range []string{controllers.Deployments, controllers.Statefulsets, controllers.Daemonsets} {
|
||||
status, err := ListResource(resource, "status=updating", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
count := status.Total
|
||||
items := status.Items
|
||||
res.Count[resource] = count
|
||||
res.Items[resource] = items
|
||||
}
|
||||
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func GetClusterResourceStatus() (*workLoadStatus, error) {
|
||||
|
||||
return GetNamespacesResourceStatus("")
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 The KubeSphere Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"kubesphere.io/kubesphere/pkg/client"
|
||||
"kubesphere.io/kubesphere/pkg/constants"
|
||||
)
|
||||
|
||||
type workLoadStatus struct {
|
||||
NameSpace string `json:"namespace"`
|
||||
Data map[string]int `json:"data"`
|
||||
UpdateTimeStamp int64 `json:"updateTimeStamp"`
|
||||
}
|
||||
|
||||
var resourceList = []string{"deployments", "daemonsets", "statefulsets"}
|
||||
|
||||
func GetNamespacesResourceStatus(namespace string) (*workLoadStatus, error) {
|
||||
|
||||
cli, err := client.NewEtcdClient()
|
||||
if err != nil {
|
||||
glog.Error(err)
|
||||
return nil, err
|
||||
}
|
||||
defer cli.Close()
|
||||
|
||||
res := workLoadStatus{Data: make(map[string]int)}
|
||||
|
||||
key := constants.Root + "/" + constants.WorkloadStatusKey + "/" + namespace
|
||||
value, err := cli.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
err = json.Unmarshal(value, &res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if time.Now().Unix()-res.UpdateTimeStamp > 5*constants.UpdateCircle {
|
||||
err = errors.New("data in etcd is too old")
|
||||
return nil, err
|
||||
}
|
||||
return &res, nil
|
||||
}
|
||||
|
||||
func GetClusterResourceStatus() (*workLoadStatus, error) {
|
||||
|
||||
return GetNamespacesResourceStatus("\"\"")
|
||||
}
|
||||
@@ -51,6 +51,10 @@ type ServerRunOptions struct {
|
||||
etcdKeyFile string
|
||||
etcdCaFile string
|
||||
kubectlImage string
|
||||
mysqlUser string
|
||||
mysqlPasswd string
|
||||
mysqlAddress string
|
||||
opAddress string
|
||||
}
|
||||
|
||||
// NewServerRunOptions creates a new ServerRunOptions object with default parameters
|
||||
@@ -97,6 +101,17 @@ func (s *ServerRunOptions) addFlags(fs *pflag.FlagSet) {
|
||||
|
||||
fs.StringVar(&s.kubectlImage, "kubectl-image", "kubectl:1.0",
|
||||
"kubectl pod's image")
|
||||
fs.StringVar(&s.mysqlAddress, "mysql-addr", "127.0.0.1:3306",
|
||||
"Address of mysql, exp:127.0.0.1:3306.")
|
||||
|
||||
fs.StringVar(&s.mysqlPasswd, "mysql-password", "123456",
|
||||
"Password of mysql")
|
||||
|
||||
fs.StringVar(&s.mysqlUser, "mysql-user", "mysql",
|
||||
"User of mysql.")
|
||||
|
||||
fs.StringVar(&s.opAddress, "openpitrix-address", "http://openpitrix-api-gateway.openpitrix-system.svc",
|
||||
"Address of openPitrix")
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetApiServerHost() string {
|
||||
@@ -181,6 +196,22 @@ func (s *ServerRunOptions) GetKubectlImage() string {
|
||||
return s.kubectlImage
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetMysqlAddr() string {
|
||||
return s.mysqlAddress
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetMysqlUser() string {
|
||||
return s.mysqlUser
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetMysqlPassword() string {
|
||||
return s.mysqlPasswd
|
||||
}
|
||||
|
||||
func (s *ServerRunOptions) GetOpAddress() string {
|
||||
return s.opAddress
|
||||
}
|
||||
|
||||
var ServerOptions = NewServerRunOptions()
|
||||
|
||||
func AddFlags(fs *pflag.FlagSet) {
|
||||
|
||||
24
vendor/github.com/docker/distribution/AUTHORS
generated
vendored
24
vendor/github.com/docker/distribution/AUTHORS
generated
vendored
@@ -1,4 +1,3 @@
|
||||
a-palchikov <deemok@gmail.com>
|
||||
Aaron Lehmann <aaron.lehmann@docker.com>
|
||||
Aaron Schlesinger <aschlesinger@deis.com>
|
||||
Aaron Vinson <avinson.public@gmail.com>
|
||||
@@ -18,10 +17,11 @@ Andrew T Nguyen <andrew.nguyen@docker.com>
|
||||
Andrey Kostov <kostov.andrey@gmail.com>
|
||||
Andy Goldstein <agoldste@redhat.com>
|
||||
Anis Elleuch <vadmeste@gmail.com>
|
||||
Anton Tiurin <noxiouz@yandex.ru>
|
||||
Antonio Mercado <amercado@thinknode.com>
|
||||
Antonio Murdaca <runcom@redhat.com>
|
||||
Anton Tiurin <noxiouz@yandex.ru>
|
||||
Anusha Ragunathan <anusha@docker.com>
|
||||
a-palchikov <deemok@gmail.com>
|
||||
Arien Holthuizen <aholthuizen@schubergphilis.com>
|
||||
Arnaud Porterie <arnaud.porterie@docker.com>
|
||||
Arthur Baars <arthur@semmle.com>
|
||||
@@ -46,9 +46,9 @@ Darren Shepherd <darren@rancher.com>
|
||||
Dave Trombley <dave.trombley@gmail.com>
|
||||
Dave Tucker <dt@docker.com>
|
||||
David Lawrence <david.lawrence@docker.com>
|
||||
davidli <wenquan.li@hp.com>
|
||||
David Verhasselt <david@crowdway.com>
|
||||
David Xia <dxia@spotify.com>
|
||||
davidli <wenquan.li@hp.com>
|
||||
Dejan Golja <dejan@golja.org>
|
||||
Derek McGowan <derek@mcgstyle.net>
|
||||
Diogo Mónica <diogo.monica@gmail.com>
|
||||
@@ -68,8 +68,8 @@ gabriell nascimento <gabriell@bluesoft.com.br>
|
||||
Gleb Schukin <gschukin@ptsecurity.com>
|
||||
harche <p.harshal@gmail.com>
|
||||
Henri Gomez <henri.gomez@gmail.com>
|
||||
Hu Keping <hukeping@huawei.com>
|
||||
Hua Wang <wanghua.humble@gmail.com>
|
||||
Hu Keping <hukeping@huawei.com>
|
||||
HuKeping <hukeping@huawei.com>
|
||||
Ian Babrou <ibobrik@gmail.com>
|
||||
igayoso <igayoso@gmail.com>
|
||||
@@ -86,21 +86,21 @@ Jihoon Chung <jihoon@gmail.com>
|
||||
Joao Fernandes <joao.fernandes@docker.com>
|
||||
John Mulhausen <john@docker.com>
|
||||
John Starks <jostarks@microsoft.com>
|
||||
Jonathan Boulle <jonathanboulle@gmail.com>
|
||||
Jon Johnson <jonjohnson@google.com>
|
||||
Jon Poler <jonathan.poler@apcera.com>
|
||||
Jonathan Boulle <jonathanboulle@gmail.com>
|
||||
Jordan Liggitt <jliggitt@redhat.com>
|
||||
Josh Chorlton <josh.chorlton@docker.com>
|
||||
Josh Hawn <josh.hawn@docker.com>
|
||||
Julien Fernandez <julien.fernandez@gmail.com>
|
||||
Ke Xu <leonhartx.k@gmail.com>
|
||||
Keerthan Mala <kmala@engineyard.com>
|
||||
Kelsey Hightower <kelsey.hightower@gmail.com>
|
||||
Kenneth Lim <kennethlimcp@gmail.com>
|
||||
Kenny Leung <kleung@google.com>
|
||||
Li Yi <denverdino@gmail.com>
|
||||
Liu Hua <sdu.liu@huawei.com>
|
||||
Ke Xu <leonhartx.k@gmail.com>
|
||||
liuchang0812 <liuchang0812@gmail.com>
|
||||
Liu Hua <sdu.liu@huawei.com>
|
||||
Li Yi <denverdino@gmail.com>
|
||||
Lloyd Ramey <lnr0626@gmail.com>
|
||||
Louis Kottmann <louis.kottmann@gmail.com>
|
||||
Luke Carpenter <x@rubynerd.net>
|
||||
@@ -108,15 +108,14 @@ Marcus Martins <marcus@docker.com>
|
||||
Mary Anthony <mary@docker.com>
|
||||
Matt Bentley <mbentley@mbentley.net>
|
||||
Matt Duch <matt@learnmetrics.com>
|
||||
Matthew Green <greenmr@live.co.uk>
|
||||
Matt Moore <mattmoor@google.com>
|
||||
Matt Robenolt <matt@ydekproductions.com>
|
||||
Matthew Green <greenmr@live.co.uk>
|
||||
Michael Prokop <mika@grml.org>
|
||||
Michal Minar <miminar@redhat.com>
|
||||
Michal Minář <miminar@redhat.com>
|
||||
Mike Brown <brownwm@us.ibm.com>
|
||||
Miquel Sabaté <msabate@suse.com>
|
||||
Misty Stanley-Jones <misty@apache.org>
|
||||
Misty Stanley-Jones <misty@docker.com>
|
||||
Morgan Bauer <mbauer@us.ibm.com>
|
||||
moxiegirl <mary@docker.com>
|
||||
@@ -165,17 +164,18 @@ Tonis Tiigi <tonistiigi@gmail.com>
|
||||
Tony Holdstock-Brown <tony@docker.com>
|
||||
Trevor Pounds <trevor.pounds@gmail.com>
|
||||
Troels Thomsen <troels@thomsen.io>
|
||||
Victor Vieux <vieux@docker.com>
|
||||
Victoria Bialas <victoria.bialas@docker.com>
|
||||
Victor Vieux <vieux@docker.com>
|
||||
Vincent Batts <vbatts@redhat.com>
|
||||
Vincent Demeester <vincent@sbr.pm>
|
||||
Vincent Giersch <vincent.giersch@ovh.net>
|
||||
W. Trevor King <wking@tremily.us>
|
||||
weiyuan.yl <weiyuan.yl@alibaba-inc.com>
|
||||
W. Trevor King <wking@tremily.us>
|
||||
xg.song <xg.song@venusource.com>
|
||||
xiekeyang <xiekeyang@huawei.com>
|
||||
Yann ROBERT <yann.robert@anantaplex.fr>
|
||||
yaoyao.xyy <yaoyao.xyy@alibaba-inc.com>
|
||||
yixi zhang <yixi@memsql.com>
|
||||
yuexiao-wang <wang.yuexiao@zte.com.cn>
|
||||
yuzou <zouyu7@huawei.com>
|
||||
zhouhaibing089 <zhouhaibing089@gmail.com>
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2017 Docker, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package digest
|
||||
|
||||
import (
|
||||
@@ -22,6 +8,11 @@ import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// DigestSha256EmptyTar is the canonical sha256 digest of empty data
|
||||
DigestSha256EmptyTar = "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
)
|
||||
|
||||
// Digest allows simple protection of hex formatted digest strings, prefixed
|
||||
// by their algorithm. Strings of type Digest have some guarantee of being in
|
||||
// the correct format and it provides quick access to the components of a
|
||||
@@ -45,21 +36,16 @@ func NewDigest(alg Algorithm, h hash.Hash) Digest {
|
||||
// functions. This is also useful for rebuilding digests from binary
|
||||
// serializations.
|
||||
func NewDigestFromBytes(alg Algorithm, p []byte) Digest {
|
||||
return NewDigestFromEncoded(alg, alg.Encode(p))
|
||||
return Digest(fmt.Sprintf("%s:%x", alg, p))
|
||||
}
|
||||
|
||||
// NewDigestFromHex is deprecated. Please use NewDigestFromEncoded.
|
||||
// NewDigestFromHex returns a Digest from alg and a the hex encoded digest.
|
||||
func NewDigestFromHex(alg, hex string) Digest {
|
||||
return NewDigestFromEncoded(Algorithm(alg), hex)
|
||||
}
|
||||
|
||||
// NewDigestFromEncoded returns a Digest from alg and the encoded digest.
|
||||
func NewDigestFromEncoded(alg Algorithm, encoded string) Digest {
|
||||
return Digest(fmt.Sprintf("%s:%s", alg, encoded))
|
||||
return Digest(fmt.Sprintf("%s:%s", alg, hex))
|
||||
}
|
||||
|
||||
// DigestRegexp matches valid digest types.
|
||||
var DigestRegexp = regexp.MustCompile(`[a-z0-9]+(?:[.+_-][a-z0-9]+)*:[a-zA-Z0-9=_-]+`)
|
||||
var DigestRegexp = regexp.MustCompile(`[a-zA-Z0-9-_+.]+:[a-fA-F0-9]+`)
|
||||
|
||||
// DigestRegexpAnchored matches valid digest types, anchored to the start and end of the match.
|
||||
var DigestRegexpAnchored = regexp.MustCompile(`^` + DigestRegexp.String() + `$`)
|
||||
@@ -75,14 +61,16 @@ var (
|
||||
ErrDigestUnsupported = fmt.Errorf("unsupported digest algorithm")
|
||||
)
|
||||
|
||||
// Parse parses s and returns the validated digest object. An error will
|
||||
// ParseDigest parses s and returns the validated digest object. An error will
|
||||
// be returned if the format is invalid.
|
||||
func Parse(s string) (Digest, error) {
|
||||
func ParseDigest(s string) (Digest, error) {
|
||||
d := Digest(s)
|
||||
|
||||
return d, d.Validate()
|
||||
}
|
||||
|
||||
// FromReader consumes the content of rd until io.EOF, returning canonical digest.
|
||||
// FromReader returns the most valid digest for the underlying content using
|
||||
// the canonical digest algorithm.
|
||||
func FromReader(rd io.Reader) (Digest, error) {
|
||||
return Canonical.FromReader(rd)
|
||||
}
|
||||
@@ -92,27 +80,36 @@ func FromBytes(p []byte) Digest {
|
||||
return Canonical.FromBytes(p)
|
||||
}
|
||||
|
||||
// FromString digests the input and returns a Digest.
|
||||
func FromString(s string) Digest {
|
||||
return Canonical.FromString(s)
|
||||
}
|
||||
|
||||
// Validate checks that the contents of d is a valid digest, returning an
|
||||
// error if not.
|
||||
func (d Digest) Validate() error {
|
||||
s := string(d)
|
||||
i := strings.Index(s, ":")
|
||||
if i <= 0 || i+1 == len(s) {
|
||||
|
||||
if !DigestRegexpAnchored.MatchString(s) {
|
||||
return ErrDigestInvalidFormat
|
||||
}
|
||||
algorithm, encoded := Algorithm(s[:i]), s[i+1:]
|
||||
if !algorithm.Available() {
|
||||
if !DigestRegexpAnchored.MatchString(s) {
|
||||
return ErrDigestInvalidFormat
|
||||
|
||||
i := strings.Index(s, ":")
|
||||
if i < 0 {
|
||||
return ErrDigestInvalidFormat
|
||||
}
|
||||
|
||||
// case: "sha256:" with no hex.
|
||||
if i+1 == len(s) {
|
||||
return ErrDigestInvalidFormat
|
||||
}
|
||||
|
||||
switch algorithm := Algorithm(s[:i]); algorithm {
|
||||
case SHA256, SHA384, SHA512:
|
||||
if algorithm.Size()*2 != len(s[i+1:]) {
|
||||
return ErrDigestInvalidLength
|
||||
}
|
||||
break
|
||||
default:
|
||||
return ErrDigestUnsupported
|
||||
}
|
||||
return algorithm.Validate(encoded)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Algorithm returns the algorithm portion of the digest. This will panic if
|
||||
@@ -121,24 +118,10 @@ func (d Digest) Algorithm() Algorithm {
|
||||
return Algorithm(d[:d.sepIndex()])
|
||||
}
|
||||
|
||||
// Verifier returns a writer object that can be used to verify a stream of
|
||||
// content against the digest. If the digest is invalid, the method will panic.
|
||||
func (d Digest) Verifier() Verifier {
|
||||
return hashVerifier{
|
||||
hash: d.Algorithm().Hash(),
|
||||
digest: d,
|
||||
}
|
||||
}
|
||||
|
||||
// Encoded returns the encoded portion of the digest. This will panic if the
|
||||
// Hex returns the hex digest portion of the digest. This will panic if the
|
||||
// underlying digest is not in a valid format.
|
||||
func (d Digest) Encoded() string {
|
||||
return string(d[d.sepIndex()+1:])
|
||||
}
|
||||
|
||||
// Hex is deprecated. Please use Digest.Encoded.
|
||||
func (d Digest) Hex() string {
|
||||
return d.Encoded()
|
||||
return string(d[d.sepIndex()+1:])
|
||||
}
|
||||
|
||||
func (d Digest) String() string {
|
||||
@@ -149,7 +132,7 @@ func (d Digest) sepIndex() int {
|
||||
i := strings.Index(string(d), ":")
|
||||
|
||||
if i < 0 {
|
||||
panic(fmt.Sprintf("no ':' separator in digest %q", d))
|
||||
panic("could not find ':' in digest: " + d)
|
||||
}
|
||||
|
||||
return i
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2017 Docker, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package digest
|
||||
|
||||
import (
|
||||
@@ -19,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// Algorithm identifies and implementation of a digester by an identifier.
|
||||
@@ -29,9 +14,9 @@ type Algorithm string
|
||||
|
||||
// supported digest types
|
||||
const (
|
||||
SHA256 Algorithm = "sha256" // sha256 with hex encoding (lower case only)
|
||||
SHA384 Algorithm = "sha384" // sha384 with hex encoding (lower case only)
|
||||
SHA512 Algorithm = "sha512" // sha512 with hex encoding (lower case only)
|
||||
SHA256 Algorithm = "sha256" // sha256 with hex encoding
|
||||
SHA384 Algorithm = "sha384" // sha384 with hex encoding
|
||||
SHA512 Algorithm = "sha512" // sha512 with hex encoding
|
||||
|
||||
// Canonical is the primary digest algorithm used with the distribution
|
||||
// project. Other digests may be used but this one is the primary storage
|
||||
@@ -51,18 +36,10 @@ var (
|
||||
SHA384: crypto.SHA384,
|
||||
SHA512: crypto.SHA512,
|
||||
}
|
||||
|
||||
// anchoredEncodedRegexps contains anchored regular expressions for hex-encoded digests.
|
||||
// Note that /A-F/ disallowed.
|
||||
anchoredEncodedRegexps = map[Algorithm]*regexp.Regexp{
|
||||
SHA256: regexp.MustCompile(`^[a-f0-9]{64}$`),
|
||||
SHA384: regexp.MustCompile(`^[a-f0-9]{96}$`),
|
||||
SHA512: regexp.MustCompile(`^[a-f0-9]{128}$`),
|
||||
}
|
||||
)
|
||||
|
||||
// Available returns true if the digest type is available for use. If this
|
||||
// returns false, Digester and Hash will return nil.
|
||||
// returns false, New and Hash will return nil.
|
||||
func (a Algorithm) Available() bool {
|
||||
h, ok := algorithms[a]
|
||||
if !ok {
|
||||
@@ -95,17 +72,13 @@ func (a *Algorithm) Set(value string) error {
|
||||
*a = Algorithm(value)
|
||||
}
|
||||
|
||||
if !a.Available() {
|
||||
return ErrDigestUnsupported
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Digester returns a new digester for the specified algorithm. If the algorithm
|
||||
// New returns a new digester for the specified algorithm. If the algorithm
|
||||
// does not have a digester implementation, nil will be returned. This can be
|
||||
// checked by calling Available before calling Digester.
|
||||
func (a Algorithm) Digester() Digester {
|
||||
// checked by calling Available before calling New.
|
||||
func (a Algorithm) New() Digester {
|
||||
return &digester{
|
||||
alg: a,
|
||||
hash: a.Hash(),
|
||||
@@ -116,11 +89,6 @@ func (a Algorithm) Digester() Digester {
|
||||
// method will panic. Check Algorithm.Available() before calling.
|
||||
func (a Algorithm) Hash() hash.Hash {
|
||||
if !a.Available() {
|
||||
// Empty algorithm string is invalid
|
||||
if a == "" {
|
||||
panic(fmt.Sprintf("empty digest algorithm, validate before calling Algorithm.Hash()"))
|
||||
}
|
||||
|
||||
// NOTE(stevvooe): A missing hash is usually a programming error that
|
||||
// must be resolved at compile time. We don't import in the digest
|
||||
// package to allow users to choose their hash implementation (such as
|
||||
@@ -134,17 +102,9 @@ func (a Algorithm) Hash() hash.Hash {
|
||||
return algorithms[a].New()
|
||||
}
|
||||
|
||||
// Encode encodes the raw bytes of a digest, typically from a hash.Hash, into
|
||||
// the encoded portion of the digest.
|
||||
func (a Algorithm) Encode(d []byte) string {
|
||||
// TODO(stevvooe): Currently, all algorithms use a hex encoding. When we
|
||||
// add support for back registration, we can modify this accordingly.
|
||||
return fmt.Sprintf("%x", d)
|
||||
}
|
||||
|
||||
// FromReader returns the digest of the reader using the algorithm.
|
||||
func (a Algorithm) FromReader(rd io.Reader) (Digest, error) {
|
||||
digester := a.Digester()
|
||||
digester := a.New()
|
||||
|
||||
if _, err := io.Copy(digester.Hash(), rd); err != nil {
|
||||
return "", err
|
||||
@@ -155,7 +115,7 @@ func (a Algorithm) FromReader(rd io.Reader) (Digest, error) {
|
||||
|
||||
// FromBytes digests the input and returns a Digest.
|
||||
func (a Algorithm) FromBytes(p []byte) Digest {
|
||||
digester := a.Digester()
|
||||
digester := a.New()
|
||||
|
||||
if _, err := digester.Hash().Write(p); err != nil {
|
||||
// Writes to a Hash should never fail. None of the existing
|
||||
@@ -169,24 +129,27 @@ func (a Algorithm) FromBytes(p []byte) Digest {
|
||||
return digester.Digest()
|
||||
}
|
||||
|
||||
// FromString digests the string input and returns a Digest.
|
||||
func (a Algorithm) FromString(s string) Digest {
|
||||
return a.FromBytes([]byte(s))
|
||||
// TODO(stevvooe): Allow resolution of verifiers using the digest type and
|
||||
// this registration system.
|
||||
|
||||
// Digester calculates the digest of written data. Writes should go directly
|
||||
// to the return value of Hash, while calling Digest will return the current
|
||||
// value of the digest.
|
||||
type Digester interface {
|
||||
Hash() hash.Hash // provides direct access to underlying hash instance.
|
||||
Digest() Digest
|
||||
}
|
||||
|
||||
// Validate validates the encoded portion string
|
||||
func (a Algorithm) Validate(encoded string) error {
|
||||
r, ok := anchoredEncodedRegexps[a]
|
||||
if !ok {
|
||||
return ErrDigestUnsupported
|
||||
}
|
||||
// Digests much always be hex-encoded, ensuring that their hex portion will
|
||||
// always be size*2
|
||||
if a.Size()*2 != len(encoded) {
|
||||
return ErrDigestInvalidLength
|
||||
}
|
||||
if r.MatchString(encoded) {
|
||||
return nil
|
||||
}
|
||||
return ErrDigestInvalidFormat
|
||||
// digester provides a simple digester definition that embeds a hasher.
|
||||
type digester struct {
|
||||
alg Algorithm
|
||||
hash hash.Hash
|
||||
}
|
||||
|
||||
func (d *digester) Hash() hash.Hash {
|
||||
return d.hash
|
||||
}
|
||||
|
||||
func (d *digester) Digest() Digest {
|
||||
return NewDigest(d.alg, d.hash)
|
||||
}
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2017 Docker, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package digest provides a generalized type to opaquely represent message
|
||||
// digests and their operations within the registry. The Digest type is
|
||||
// designed to serve as a flexible identifier in a content-addressable system.
|
||||
@@ -1,12 +1,10 @@
|
||||
package digestset
|
||||
package digest
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
digest "github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -46,7 +44,7 @@ func NewSet() *Set {
|
||||
// values or short values. This function does not test equality,
|
||||
// rather whether the second value could match against the first
|
||||
// value.
|
||||
func checkShortMatch(alg digest.Algorithm, hex, shortAlg, shortHex string) bool {
|
||||
func checkShortMatch(alg Algorithm, hex, shortAlg, shortHex string) bool {
|
||||
if len(hex) == len(shortHex) {
|
||||
if hex != shortHex {
|
||||
return false
|
||||
@@ -66,7 +64,7 @@ func checkShortMatch(alg digest.Algorithm, hex, shortAlg, shortHex string) bool
|
||||
// If no digests could be found ErrDigestNotFound will be returned
|
||||
// with an empty digest value. If multiple matches are found
|
||||
// ErrDigestAmbiguous will be returned with an empty digest value.
|
||||
func (dst *Set) Lookup(d string) (digest.Digest, error) {
|
||||
func (dst *Set) Lookup(d string) (Digest, error) {
|
||||
dst.mutex.RLock()
|
||||
defer dst.mutex.RUnlock()
|
||||
if len(dst.entries) == 0 {
|
||||
@@ -74,11 +72,11 @@ func (dst *Set) Lookup(d string) (digest.Digest, error) {
|
||||
}
|
||||
var (
|
||||
searchFunc func(int) bool
|
||||
alg digest.Algorithm
|
||||
alg Algorithm
|
||||
hex string
|
||||
)
|
||||
dgst, err := digest.Parse(d)
|
||||
if err == digest.ErrDigestInvalidFormat {
|
||||
dgst, err := ParseDigest(d)
|
||||
if err == ErrDigestInvalidFormat {
|
||||
hex = d
|
||||
searchFunc = func(i int) bool {
|
||||
return dst.entries[i].val >= d
|
||||
@@ -110,7 +108,7 @@ func (dst *Set) Lookup(d string) (digest.Digest, error) {
|
||||
// Add adds the given digest to the set. An error will be returned
|
||||
// if the given digest is invalid. If the digest already exists in the
|
||||
// set, this operation will be a no-op.
|
||||
func (dst *Set) Add(d digest.Digest) error {
|
||||
func (dst *Set) Add(d Digest) error {
|
||||
if err := d.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -141,7 +139,7 @@ func (dst *Set) Add(d digest.Digest) error {
|
||||
// Remove removes the given digest from the set. An err will be
|
||||
// returned if the given digest is invalid. If the digest does
|
||||
// not exist in the set, this operation will be a no-op.
|
||||
func (dst *Set) Remove(d digest.Digest) error {
|
||||
func (dst *Set) Remove(d Digest) error {
|
||||
if err := d.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -169,10 +167,10 @@ func (dst *Set) Remove(d digest.Digest) error {
|
||||
}
|
||||
|
||||
// All returns all the digests in the set
|
||||
func (dst *Set) All() []digest.Digest {
|
||||
func (dst *Set) All() []Digest {
|
||||
dst.mutex.RLock()
|
||||
defer dst.mutex.RUnlock()
|
||||
retValues := make([]digest.Digest, len(dst.entries))
|
||||
retValues := make([]Digest, len(dst.entries))
|
||||
for i := range dst.entries {
|
||||
retValues[i] = dst.entries[i].digest
|
||||
}
|
||||
@@ -185,10 +183,10 @@ func (dst *Set) All() []digest.Digest {
|
||||
// entire value of digest if uniqueness cannot be achieved without the
|
||||
// full value. This function will attempt to make short codes as short
|
||||
// as possible to be unique.
|
||||
func ShortCodeTable(dst *Set, length int) map[digest.Digest]string {
|
||||
func ShortCodeTable(dst *Set, length int) map[Digest]string {
|
||||
dst.mutex.RLock()
|
||||
defer dst.mutex.RUnlock()
|
||||
m := make(map[digest.Digest]string, len(dst.entries))
|
||||
m := make(map[Digest]string, len(dst.entries))
|
||||
l := length
|
||||
resetIdx := 0
|
||||
for i := 0; i < len(dst.entries); i++ {
|
||||
@@ -224,9 +222,9 @@ func ShortCodeTable(dst *Set, length int) map[digest.Digest]string {
|
||||
}
|
||||
|
||||
type digestEntry struct {
|
||||
alg digest.Algorithm
|
||||
alg Algorithm
|
||||
val string
|
||||
digest digest.Digest
|
||||
digest Digest
|
||||
}
|
||||
|
||||
type digestEntries []*digestEntry
|
||||
@@ -1,17 +1,3 @@
|
||||
// Copyright 2017 Docker, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package digest
|
||||
|
||||
import (
|
||||
@@ -31,6 +17,19 @@ type Verifier interface {
|
||||
Verified() bool
|
||||
}
|
||||
|
||||
// NewDigestVerifier returns a verifier that compares the written bytes
|
||||
// against a passed in digest.
|
||||
func NewDigestVerifier(d Digest) (Verifier, error) {
|
||||
if err := d.Validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hashVerifier{
|
||||
hash: d.Algorithm().Hash(),
|
||||
digest: d,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type hashVerifier struct {
|
||||
digest Digest
|
||||
hash hash.Hash
|
||||
42
vendor/github.com/docker/distribution/reference/helpers.go
generated
vendored
42
vendor/github.com/docker/distribution/reference/helpers.go
generated
vendored
@@ -1,42 +0,0 @@
|
||||
package reference
|
||||
|
||||
import "path"
|
||||
|
||||
// IsNameOnly returns true if reference only contains a repo name.
|
||||
func IsNameOnly(ref Named) bool {
|
||||
if _, ok := ref.(NamedTagged); ok {
|
||||
return false
|
||||
}
|
||||
if _, ok := ref.(Canonical); ok {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// FamiliarName returns the familiar name string
|
||||
// for the given named, familiarizing if needed.
|
||||
func FamiliarName(ref Named) string {
|
||||
if nn, ok := ref.(normalizedNamed); ok {
|
||||
return nn.Familiar().Name()
|
||||
}
|
||||
return ref.Name()
|
||||
}
|
||||
|
||||
// FamiliarString returns the familiar string representation
|
||||
// for the given reference, familiarizing if needed.
|
||||
func FamiliarString(ref Reference) string {
|
||||
if nn, ok := ref.(normalizedNamed); ok {
|
||||
return nn.Familiar().String()
|
||||
}
|
||||
return ref.String()
|
||||
}
|
||||
|
||||
// FamiliarMatch reports whether ref matches the specified pattern.
|
||||
// See https://godoc.org/path#Match for supported patterns.
|
||||
func FamiliarMatch(pattern string, ref Reference) (bool, error) {
|
||||
matched, err := path.Match(pattern, FamiliarString(ref))
|
||||
if namedRef, isNamed := ref.(Named); isNamed && !matched {
|
||||
matched, _ = path.Match(pattern, FamiliarName(namedRef))
|
||||
}
|
||||
return matched, err
|
||||
}
|
||||
170
vendor/github.com/docker/distribution/reference/normalize.go
generated
vendored
170
vendor/github.com/docker/distribution/reference/normalize.go
generated
vendored
@@ -1,170 +0,0 @@
|
||||
package reference
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/distribution/digestset"
|
||||
"github.com/opencontainers/go-digest"
|
||||
)
|
||||
|
||||
var (
|
||||
legacyDefaultDomain = "index.docker.io"
|
||||
defaultDomain = "docker.io"
|
||||
officialRepoName = "library"
|
||||
defaultTag = "latest"
|
||||
)
|
||||
|
||||
// normalizedNamed represents a name which has been
|
||||
// normalized and has a familiar form. A familiar name
|
||||
// is what is used in Docker UI. An example normalized
|
||||
// name is "docker.io/library/ubuntu" and corresponding
|
||||
// familiar name of "ubuntu".
|
||||
type normalizedNamed interface {
|
||||
Named
|
||||
Familiar() Named
|
||||
}
|
||||
|
||||
// ParseNormalizedNamed parses a string into a named reference
|
||||
// transforming a familiar name from Docker UI to a fully
|
||||
// qualified reference. If the value may be an identifier
|
||||
// use ParseAnyReference.
|
||||
func ParseNormalizedNamed(s string) (Named, error) {
|
||||
if ok := anchoredIdentifierRegexp.MatchString(s); ok {
|
||||
return nil, fmt.Errorf("invalid repository name (%s), cannot specify 64-byte hexadecimal strings", s)
|
||||
}
|
||||
domain, remainder := splitDockerDomain(s)
|
||||
var remoteName string
|
||||
if tagSep := strings.IndexRune(remainder, ':'); tagSep > -1 {
|
||||
remoteName = remainder[:tagSep]
|
||||
} else {
|
||||
remoteName = remainder
|
||||
}
|
||||
if strings.ToLower(remoteName) != remoteName {
|
||||
return nil, errors.New("invalid reference format: repository name must be lowercase")
|
||||
}
|
||||
|
||||
ref, err := Parse(domain + "/" + remainder)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
named, isNamed := ref.(Named)
|
||||
if !isNamed {
|
||||
return nil, fmt.Errorf("reference %s has no name", ref.String())
|
||||
}
|
||||
return named, nil
|
||||
}
|
||||
|
||||
// splitDockerDomain splits a repository name to domain and remotename string.
|
||||
// If no valid domain is found, the default domain is used. Repository name
|
||||
// needs to be already validated before.
|
||||
func splitDockerDomain(name string) (domain, remainder string) {
|
||||
i := strings.IndexRune(name, '/')
|
||||
if i == -1 || (!strings.ContainsAny(name[:i], ".:") && name[:i] != "localhost") {
|
||||
domain, remainder = defaultDomain, name
|
||||
} else {
|
||||
domain, remainder = name[:i], name[i+1:]
|
||||
}
|
||||
if domain == legacyDefaultDomain {
|
||||
domain = defaultDomain
|
||||
}
|
||||
if domain == defaultDomain && !strings.ContainsRune(remainder, '/') {
|
||||
remainder = officialRepoName + "/" + remainder
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// familiarizeName returns a shortened version of the name familiar
|
||||
// to to the Docker UI. Familiar names have the default domain
|
||||
// "docker.io" and "library/" repository prefix removed.
|
||||
// For example, "docker.io/library/redis" will have the familiar
|
||||
// name "redis" and "docker.io/dmcgowan/myapp" will be "dmcgowan/myapp".
|
||||
// Returns a familiarized named only reference.
|
||||
func familiarizeName(named namedRepository) repository {
|
||||
repo := repository{
|
||||
domain: named.Domain(),
|
||||
path: named.Path(),
|
||||
}
|
||||
|
||||
if repo.domain == defaultDomain {
|
||||
repo.domain = ""
|
||||
// Handle official repositories which have the pattern "library/<official repo name>"
|
||||
if split := strings.Split(repo.path, "/"); len(split) == 2 && split[0] == officialRepoName {
|
||||
repo.path = split[1]
|
||||
}
|
||||
}
|
||||
return repo
|
||||
}
|
||||
|
||||
func (r reference) Familiar() Named {
|
||||
return reference{
|
||||
namedRepository: familiarizeName(r.namedRepository),
|
||||
tag: r.tag,
|
||||
digest: r.digest,
|
||||
}
|
||||
}
|
||||
|
||||
func (r repository) Familiar() Named {
|
||||
return familiarizeName(r)
|
||||
}
|
||||
|
||||
func (t taggedReference) Familiar() Named {
|
||||
return taggedReference{
|
||||
namedRepository: familiarizeName(t.namedRepository),
|
||||
tag: t.tag,
|
||||
}
|
||||
}
|
||||
|
||||
func (c canonicalReference) Familiar() Named {
|
||||
return canonicalReference{
|
||||
namedRepository: familiarizeName(c.namedRepository),
|
||||
digest: c.digest,
|
||||
}
|
||||
}
|
||||
|
||||
// TagNameOnly adds the default tag "latest" to a reference if it only has
|
||||
// a repo name.
|
||||
func TagNameOnly(ref Named) Named {
|
||||
if IsNameOnly(ref) {
|
||||
namedTagged, err := WithTag(ref, defaultTag)
|
||||
if err != nil {
|
||||
// Default tag must be valid, to create a NamedTagged
|
||||
// type with non-validated input the WithTag function
|
||||
// should be used instead
|
||||
panic(err)
|
||||
}
|
||||
return namedTagged
|
||||
}
|
||||
return ref
|
||||
}
|
||||
|
||||
// ParseAnyReference parses a reference string as a possible identifier,
|
||||
// full digest, or familiar name.
|
||||
func ParseAnyReference(ref string) (Reference, error) {
|
||||
if ok := anchoredIdentifierRegexp.MatchString(ref); ok {
|
||||
return digestReference("sha256:" + ref), nil
|
||||
}
|
||||
if dgst, err := digest.Parse(ref); err == nil {
|
||||
return digestReference(dgst), nil
|
||||
}
|
||||
|
||||
return ParseNormalizedNamed(ref)
|
||||
}
|
||||
|
||||
// ParseAnyReferenceWithSet parses a reference string as a possible short
|
||||
// identifier to be matched in a digest set, a full digest, or familiar name.
|
||||
func ParseAnyReferenceWithSet(ref string, ds *digestset.Set) (Reference, error) {
|
||||
if ok := anchoredShortIdentifierRegexp.MatchString(ref); ok {
|
||||
dgst, err := ds.Lookup(ref)
|
||||
if err == nil {
|
||||
return digestReference(dgst), nil
|
||||
}
|
||||
} else {
|
||||
if dgst, err := digest.Parse(ref); err == nil {
|
||||
return digestReference(dgst), nil
|
||||
}
|
||||
}
|
||||
|
||||
return ParseNormalizedNamed(ref)
|
||||
}
|
||||
211
vendor/github.com/docker/distribution/reference/reference.go
generated
vendored
211
vendor/github.com/docker/distribution/reference/reference.go
generated
vendored
@@ -4,32 +4,30 @@
|
||||
// Grammar
|
||||
//
|
||||
// reference := name [ ":" tag ] [ "@" digest ]
|
||||
// name := [domain '/'] path-component ['/' path-component]*
|
||||
// domain := domain-component ['.' domain-component]* [':' port-number]
|
||||
// domain-component := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
|
||||
// name := [hostname '/'] component ['/' component]*
|
||||
// hostname := hostcomponent ['.' hostcomponent]* [':' port-number]
|
||||
// hostcomponent := /([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])/
|
||||
// port-number := /[0-9]+/
|
||||
// path-component := alpha-numeric [separator alpha-numeric]*
|
||||
// component := alpha-numeric [separator alpha-numeric]*
|
||||
// alpha-numeric := /[a-z0-9]+/
|
||||
// separator := /[_.]|__|[-]*/
|
||||
//
|
||||
// tag := /[\w][\w.-]{0,127}/
|
||||
//
|
||||
// digest := digest-algorithm ":" digest-hex
|
||||
// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]*
|
||||
// digest-algorithm := digest-algorithm-component [ digest-algorithm-separator digest-algorithm-component ]
|
||||
// digest-algorithm-separator := /[+.-_]/
|
||||
// digest-algorithm-component := /[A-Za-z][A-Za-z0-9]*/
|
||||
// digest-hex := /[0-9a-fA-F]{32,}/ ; At least 128 bit digest value
|
||||
//
|
||||
// identifier := /[a-f0-9]{64}/
|
||||
// short-identifier := /[a-f0-9]{6,64}/
|
||||
package reference
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/docker/distribution/digest"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -55,9 +53,6 @@ var (
|
||||
|
||||
// ErrNameTooLong is returned when a repository name is longer than NameTotalLengthMax.
|
||||
ErrNameTooLong = fmt.Errorf("repository name must not be more than %v characters", NameTotalLengthMax)
|
||||
|
||||
// ErrNameNotCanonical is returned when a name is not canonical.
|
||||
ErrNameNotCanonical = errors.New("repository name must be canonical")
|
||||
)
|
||||
|
||||
// Reference is an opaque object reference identifier that may include
|
||||
@@ -131,56 +126,23 @@ type Digested interface {
|
||||
}
|
||||
|
||||
// Canonical reference is an object with a fully unique
|
||||
// name including a name with domain and digest
|
||||
// name including a name with hostname and digest
|
||||
type Canonical interface {
|
||||
Named
|
||||
Digest() digest.Digest
|
||||
}
|
||||
|
||||
// namedRepository is a reference to a repository with a name.
|
||||
// A namedRepository has both domain and path components.
|
||||
type namedRepository interface {
|
||||
Named
|
||||
Domain() string
|
||||
Path() string
|
||||
}
|
||||
|
||||
// Domain returns the domain part of the Named reference
|
||||
func Domain(named Named) string {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Domain()
|
||||
}
|
||||
domain, _ := splitDomain(named.Name())
|
||||
return domain
|
||||
}
|
||||
|
||||
// Path returns the name without the domain part of the Named reference
|
||||
func Path(named Named) (name string) {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Path()
|
||||
}
|
||||
_, path := splitDomain(named.Name())
|
||||
return path
|
||||
}
|
||||
|
||||
func splitDomain(name string) (string, string) {
|
||||
match := anchoredNameRegexp.FindStringSubmatch(name)
|
||||
if len(match) != 3 {
|
||||
return "", name
|
||||
}
|
||||
return match[1], match[2]
|
||||
}
|
||||
|
||||
// SplitHostname splits a named reference into a
|
||||
// hostname and name string. If no valid hostname is
|
||||
// found, the hostname is empty and the full value
|
||||
// is returned as name
|
||||
// DEPRECATED: Use Domain or Path
|
||||
func SplitHostname(named Named) (string, string) {
|
||||
if r, ok := named.(namedRepository); ok {
|
||||
return r.Domain(), r.Path()
|
||||
name := named.Name()
|
||||
match := anchoredNameRegexp.FindStringSubmatch(name)
|
||||
if len(match) != 3 {
|
||||
return "", name
|
||||
}
|
||||
return splitDomain(named.Name())
|
||||
return match[1], match[2]
|
||||
}
|
||||
|
||||
// Parse parses s and returns a syntactically valid Reference.
|
||||
@@ -202,24 +164,13 @@ func Parse(s string) (Reference, error) {
|
||||
return nil, ErrNameTooLong
|
||||
}
|
||||
|
||||
var repo repository
|
||||
|
||||
nameMatch := anchoredNameRegexp.FindStringSubmatch(matches[1])
|
||||
if nameMatch != nil && len(nameMatch) == 3 {
|
||||
repo.domain = nameMatch[1]
|
||||
repo.path = nameMatch[2]
|
||||
} else {
|
||||
repo.domain = ""
|
||||
repo.path = matches[1]
|
||||
}
|
||||
|
||||
ref := reference{
|
||||
namedRepository: repo,
|
||||
tag: matches[2],
|
||||
name: matches[1],
|
||||
tag: matches[2],
|
||||
}
|
||||
if matches[3] != "" {
|
||||
var err error
|
||||
ref.digest, err = digest.Parse(matches[3])
|
||||
ref.digest, err = digest.ParseDigest(matches[3])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -234,17 +185,18 @@ func Parse(s string) (Reference, error) {
|
||||
}
|
||||
|
||||
// ParseNamed parses s and returns a syntactically valid reference implementing
|
||||
// the Named interface. The reference must have a name and be in the canonical
|
||||
// form, otherwise an error is returned.
|
||||
// the Named interface. The reference must have a name, otherwise an error is
|
||||
// returned.
|
||||
// If an error was encountered it is returned, along with a nil Reference.
|
||||
// NOTE: ParseNamed will not handle short digests.
|
||||
func ParseNamed(s string) (Named, error) {
|
||||
named, err := ParseNormalizedNamed(s)
|
||||
ref, err := Parse(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if named.String() != s {
|
||||
return nil, ErrNameNotCanonical
|
||||
named, isNamed := ref.(Named)
|
||||
if !isNamed {
|
||||
return nil, fmt.Errorf("reference %s has no name", ref.String())
|
||||
}
|
||||
return named, nil
|
||||
}
|
||||
@@ -255,15 +207,10 @@ func WithName(name string) (Named, error) {
|
||||
if len(name) > NameTotalLengthMax {
|
||||
return nil, ErrNameTooLong
|
||||
}
|
||||
|
||||
match := anchoredNameRegexp.FindStringSubmatch(name)
|
||||
if match == nil || len(match) != 3 {
|
||||
if !anchoredNameRegexp.MatchString(name) {
|
||||
return nil, ErrReferenceInvalidFormat
|
||||
}
|
||||
return repository{
|
||||
domain: match[1],
|
||||
path: match[2],
|
||||
}, nil
|
||||
return repository(name), nil
|
||||
}
|
||||
|
||||
// WithTag combines the name from "name" and the tag from "tag" to form a
|
||||
@@ -272,23 +219,16 @@ func WithTag(name Named, tag string) (NamedTagged, error) {
|
||||
if !anchoredTagRegexp.MatchString(tag) {
|
||||
return nil, ErrTagInvalidFormat
|
||||
}
|
||||
var repo repository
|
||||
if r, ok := name.(namedRepository); ok {
|
||||
repo.domain = r.Domain()
|
||||
repo.path = r.Path()
|
||||
} else {
|
||||
repo.path = name.Name()
|
||||
}
|
||||
if canonical, ok := name.(Canonical); ok {
|
||||
return reference{
|
||||
namedRepository: repo,
|
||||
tag: tag,
|
||||
digest: canonical.Digest(),
|
||||
name: name.Name(),
|
||||
tag: tag,
|
||||
digest: canonical.Digest(),
|
||||
}, nil
|
||||
}
|
||||
return taggedReference{
|
||||
namedRepository: repo,
|
||||
tag: tag,
|
||||
name: name.Name(),
|
||||
tag: tag,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -298,37 +238,36 @@ func WithDigest(name Named, digest digest.Digest) (Canonical, error) {
|
||||
if !anchoredDigestRegexp.MatchString(digest.String()) {
|
||||
return nil, ErrDigestInvalidFormat
|
||||
}
|
||||
var repo repository
|
||||
if r, ok := name.(namedRepository); ok {
|
||||
repo.domain = r.Domain()
|
||||
repo.path = r.Path()
|
||||
} else {
|
||||
repo.path = name.Name()
|
||||
}
|
||||
if tagged, ok := name.(Tagged); ok {
|
||||
return reference{
|
||||
namedRepository: repo,
|
||||
tag: tagged.Tag(),
|
||||
digest: digest,
|
||||
name: name.Name(),
|
||||
tag: tagged.Tag(),
|
||||
digest: digest,
|
||||
}, nil
|
||||
}
|
||||
return canonicalReference{
|
||||
namedRepository: repo,
|
||||
digest: digest,
|
||||
name: name.Name(),
|
||||
digest: digest,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Match reports whether ref matches the specified pattern.
|
||||
// See https://godoc.org/path#Match for supported patterns.
|
||||
func Match(pattern string, ref Reference) (bool, error) {
|
||||
matched, err := path.Match(pattern, ref.String())
|
||||
if namedRef, isNamed := ref.(Named); isNamed && !matched {
|
||||
matched, _ = path.Match(pattern, namedRef.Name())
|
||||
}
|
||||
return matched, err
|
||||
}
|
||||
|
||||
// TrimNamed removes any tag or digest from the named reference.
|
||||
func TrimNamed(ref Named) Named {
|
||||
domain, path := SplitHostname(ref)
|
||||
return repository{
|
||||
domain: domain,
|
||||
path: path,
|
||||
}
|
||||
return repository(ref.Name())
|
||||
}
|
||||
|
||||
func getBestReferenceType(ref reference) Reference {
|
||||
if ref.Name() == "" {
|
||||
if ref.name == "" {
|
||||
// Allow digest only references
|
||||
if ref.digest != "" {
|
||||
return digestReference(ref.digest)
|
||||
@@ -338,16 +277,16 @@ func getBestReferenceType(ref reference) Reference {
|
||||
if ref.tag == "" {
|
||||
if ref.digest != "" {
|
||||
return canonicalReference{
|
||||
namedRepository: ref.namedRepository,
|
||||
digest: ref.digest,
|
||||
name: ref.name,
|
||||
digest: ref.digest,
|
||||
}
|
||||
}
|
||||
return ref.namedRepository
|
||||
return repository(ref.name)
|
||||
}
|
||||
if ref.digest == "" {
|
||||
return taggedReference{
|
||||
namedRepository: ref.namedRepository,
|
||||
tag: ref.tag,
|
||||
name: ref.name,
|
||||
tag: ref.tag,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,13 +294,17 @@ func getBestReferenceType(ref reference) Reference {
|
||||
}
|
||||
|
||||
type reference struct {
|
||||
namedRepository
|
||||
name string
|
||||
tag string
|
||||
digest digest.Digest
|
||||
}
|
||||
|
||||
func (r reference) String() string {
|
||||
return r.Name() + ":" + r.tag + "@" + r.digest.String()
|
||||
return r.name + ":" + r.tag + "@" + r.digest.String()
|
||||
}
|
||||
|
||||
func (r reference) Name() string {
|
||||
return r.name
|
||||
}
|
||||
|
||||
func (r reference) Tag() string {
|
||||
@@ -372,34 +315,20 @@ func (r reference) Digest() digest.Digest {
|
||||
return r.digest
|
||||
}
|
||||
|
||||
type repository struct {
|
||||
domain string
|
||||
path string
|
||||
}
|
||||
type repository string
|
||||
|
||||
func (r repository) String() string {
|
||||
return r.Name()
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func (r repository) Name() string {
|
||||
if r.domain == "" {
|
||||
return r.path
|
||||
}
|
||||
return r.domain + "/" + r.path
|
||||
}
|
||||
|
||||
func (r repository) Domain() string {
|
||||
return r.domain
|
||||
}
|
||||
|
||||
func (r repository) Path() string {
|
||||
return r.path
|
||||
return string(r)
|
||||
}
|
||||
|
||||
type digestReference digest.Digest
|
||||
|
||||
func (d digestReference) String() string {
|
||||
return digest.Digest(d).String()
|
||||
return d.String()
|
||||
}
|
||||
|
||||
func (d digestReference) Digest() digest.Digest {
|
||||
@@ -407,12 +336,16 @@ func (d digestReference) Digest() digest.Digest {
|
||||
}
|
||||
|
||||
type taggedReference struct {
|
||||
namedRepository
|
||||
tag string
|
||||
name string
|
||||
tag string
|
||||
}
|
||||
|
||||
func (t taggedReference) String() string {
|
||||
return t.Name() + ":" + t.tag
|
||||
return t.name + ":" + t.tag
|
||||
}
|
||||
|
||||
func (t taggedReference) Name() string {
|
||||
return t.name
|
||||
}
|
||||
|
||||
func (t taggedReference) Tag() string {
|
||||
@@ -420,12 +353,16 @@ func (t taggedReference) Tag() string {
|
||||
}
|
||||
|
||||
type canonicalReference struct {
|
||||
namedRepository
|
||||
name string
|
||||
digest digest.Digest
|
||||
}
|
||||
|
||||
func (c canonicalReference) String() string {
|
||||
return c.Name() + "@" + c.digest.String()
|
||||
return c.name + "@" + c.digest.String()
|
||||
}
|
||||
|
||||
func (c canonicalReference) Name() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c canonicalReference) Digest() digest.Digest {
|
||||
|
||||
41
vendor/github.com/docker/distribution/reference/regexp.go
generated
vendored
41
vendor/github.com/docker/distribution/reference/regexp.go
generated
vendored
@@ -19,18 +19,18 @@ var (
|
||||
alphaNumericRegexp,
|
||||
optional(repeated(separatorRegexp, alphaNumericRegexp)))
|
||||
|
||||
// domainComponentRegexp restricts the registry domain component of a
|
||||
// repository name to start with a component as defined by DomainRegexp
|
||||
// hostnameComponentRegexp restricts the registry hostname component of a
|
||||
// repository name to start with a component as defined by hostnameRegexp
|
||||
// and followed by an optional port.
|
||||
domainComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
|
||||
hostnameComponentRegexp = match(`(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])`)
|
||||
|
||||
// DomainRegexp defines the structure of potential domain components
|
||||
// hostnameRegexp defines the structure of potential hostname components
|
||||
// that may be part of image names. This is purposely a subset of what is
|
||||
// allowed by DNS to ensure backwards compatibility with Docker image
|
||||
// names.
|
||||
DomainRegexp = expression(
|
||||
domainComponentRegexp,
|
||||
optional(repeated(literal(`.`), domainComponentRegexp)),
|
||||
hostnameRegexp = expression(
|
||||
hostnameComponentRegexp,
|
||||
optional(repeated(literal(`.`), hostnameComponentRegexp)),
|
||||
optional(literal(`:`), match(`[0-9]+`)))
|
||||
|
||||
// TagRegexp matches valid tag names. From docker/docker:graph/tags.go.
|
||||
@@ -48,17 +48,17 @@ var (
|
||||
anchoredDigestRegexp = anchored(DigestRegexp)
|
||||
|
||||
// NameRegexp is the format for the name component of references. The
|
||||
// regexp has capturing groups for the domain and name part omitting
|
||||
// regexp has capturing groups for the hostname and name part omitting
|
||||
// the separating forward slash from either.
|
||||
NameRegexp = expression(
|
||||
optional(DomainRegexp, literal(`/`)),
|
||||
optional(hostnameRegexp, literal(`/`)),
|
||||
nameComponentRegexp,
|
||||
optional(repeated(literal(`/`), nameComponentRegexp)))
|
||||
|
||||
// anchoredNameRegexp is used to parse a name value, capturing the
|
||||
// domain and trailing components.
|
||||
// hostname and trailing components.
|
||||
anchoredNameRegexp = anchored(
|
||||
optional(capture(DomainRegexp), literal(`/`)),
|
||||
optional(capture(hostnameRegexp), literal(`/`)),
|
||||
capture(nameComponentRegexp,
|
||||
optional(repeated(literal(`/`), nameComponentRegexp))))
|
||||
|
||||
@@ -68,25 +68,6 @@ var (
|
||||
ReferenceRegexp = anchored(capture(NameRegexp),
|
||||
optional(literal(":"), capture(TagRegexp)),
|
||||
optional(literal("@"), capture(DigestRegexp)))
|
||||
|
||||
// IdentifierRegexp is the format for string identifier used as a
|
||||
// content addressable identifier using sha256. These identifiers
|
||||
// are like digests without the algorithm, since sha256 is used.
|
||||
IdentifierRegexp = match(`([a-f0-9]{64})`)
|
||||
|
||||
// ShortIdentifierRegexp is the format used to represent a prefix
|
||||
// of an identifier. A prefix may be used to match a sha256 identifier
|
||||
// within a list of trusted identifiers.
|
||||
ShortIdentifierRegexp = match(`([a-f0-9]{6,64})`)
|
||||
|
||||
// anchoredIdentifierRegexp is used to check or match an
|
||||
// identifier value, anchored at start and end of string.
|
||||
anchoredIdentifierRegexp = anchored(IdentifierRegexp)
|
||||
|
||||
// anchoredShortIdentifierRegexp is used to check if a value
|
||||
// is a possible identifier prefix, anchored at start and end
|
||||
// of string.
|
||||
anchoredShortIdentifierRegexp = anchored(ShortIdentifierRegexp)
|
||||
)
|
||||
|
||||
// match compiles the string to a regular expression.
|
||||
|
||||
572
vendor/github.com/docker/docker/AUTHORS
generated
vendored
572
vendor/github.com/docker/docker/AUTHORS
generated
vendored
File diff suppressed because it is too large
Load Diff
2
vendor/github.com/docker/docker/LICENSE
generated
vendored
2
vendor/github.com/docker/docker/LICENSE
generated
vendored
@@ -176,7 +176,7 @@
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright 2013-2017 Docker, Inc.
|
||||
Copyright 2013-2016 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
2
vendor/github.com/docker/docker/NOTICE
generated
vendored
2
vendor/github.com/docker/docker/NOTICE
generated
vendored
@@ -1,5 +1,5 @@
|
||||
Docker
|
||||
Copyright 2012-2017 Docker, Inc.
|
||||
Copyright 2012-2016 Docker, Inc.
|
||||
|
||||
This product includes software developed at Docker, Inc. (https://www.docker.com).
|
||||
|
||||
|
||||
42
vendor/github.com/docker/docker/api/README.md
generated
vendored
42
vendor/github.com/docker/docker/api/README.md
generated
vendored
@@ -1,42 +0,0 @@
|
||||
# Working on the Engine API
|
||||
|
||||
The Engine API is an HTTP API used by the command-line client to communicate with the daemon. It can also be used by third-party software to control the daemon.
|
||||
|
||||
It consists of various components in this repository:
|
||||
|
||||
- `api/swagger.yaml` A Swagger definition of the API.
|
||||
- `api/types/` Types shared by both the client and server, representing various objects, options, responses, etc. Most are written manually, but some are automatically generated from the Swagger definition. See [#27919](https://github.com/docker/docker/issues/27919) for progress on this.
|
||||
- `cli/` The command-line client.
|
||||
- `client/` The Go client used by the command-line client. It can also be used by third-party Go programs.
|
||||
- `daemon/` The daemon, which serves the API.
|
||||
|
||||
## Swagger definition
|
||||
|
||||
The API is defined by the [Swagger](http://swagger.io/specification/) definition in `api/swagger.yaml`. This definition can be used to:
|
||||
|
||||
1. Automatically generate documentation.
|
||||
2. Automatically generate the Go server and client. (A work-in-progress.)
|
||||
3. Provide a machine readable version of the API for introspecting what it can do, automatically generating clients for other languages, etc.
|
||||
|
||||
## Updating the API documentation
|
||||
|
||||
The API documentation is generated entirely from `api/swagger.yaml`. If you make updates to the API, edit this file to represent the change in the documentation.
|
||||
|
||||
The file is split into two main sections:
|
||||
|
||||
- `definitions`, which defines re-usable objects used in requests and responses
|
||||
- `paths`, which defines the API endpoints (and some inline objects which don't need to be reusable)
|
||||
|
||||
To make an edit, first look for the endpoint you want to edit under `paths`, then make the required edits. Endpoints may reference reusable objects with `$ref`, which can be found in the `definitions` section.
|
||||
|
||||
There is hopefully enough example material in the file for you to copy a similar pattern from elsewhere in the file (e.g. adding new fields or endpoints), but for the full reference, see the [Swagger specification](https://github.com/docker/docker/issues/27919).
|
||||
|
||||
`swagger.yaml` is validated by `hack/validate/swagger` to ensure it is a valid Swagger definition. This is useful when making edits to ensure you are doing the right thing.
|
||||
|
||||
## Viewing the API documentation
|
||||
|
||||
When you make edits to `swagger.yaml`, you may want to check the generated API documentation to ensure it renders correctly.
|
||||
|
||||
Run `make swagger-docs` and a preview will be running at `http://localhost`. Some of the styling may be incorrect, but you'll be able to ensure that it is generating the correct documentation.
|
||||
|
||||
The production documentation is generated by vendoring `swagger.yaml` into [docker/docker.github.io](https://github.com/docker/docker.github.io).
|
||||
11
vendor/github.com/docker/docker/api/common.go
generated
vendored
11
vendor/github.com/docker/docker/api/common.go
generated
vendored
@@ -1,11 +0,0 @@
|
||||
package api // import "github.com/docker/docker/api"
|
||||
|
||||
// Common constants for daemon and client.
|
||||
const (
|
||||
// DefaultVersion of Current REST API
|
||||
DefaultVersion = "1.38"
|
||||
|
||||
// NoBaseImageSpecifier is the symbol used by the FROM
|
||||
// command to specify that no base image is to be used.
|
||||
NoBaseImageSpecifier = "scratch"
|
||||
)
|
||||
6
vendor/github.com/docker/docker/api/common_unix.go
generated
vendored
6
vendor/github.com/docker/docker/api/common_unix.go
generated
vendored
@@ -1,6 +0,0 @@
|
||||
// +build !windows
|
||||
|
||||
package api // import "github.com/docker/docker/api"
|
||||
|
||||
// MinVersion represents Minimum REST API version supported
|
||||
const MinVersion = "1.12"
|
||||
8
vendor/github.com/docker/docker/api/common_windows.go
generated
vendored
8
vendor/github.com/docker/docker/api/common_windows.go
generated
vendored
@@ -1,8 +0,0 @@
|
||||
package api // import "github.com/docker/docker/api"
|
||||
|
||||
// MinVersion represents Minimum REST API version supported
|
||||
// Technically the first daemon API version released on Windows is v1.25 in
|
||||
// engine version 1.13. However, some clients are explicitly using downlevel
|
||||
// APIs (e.g. docker-compose v2.1 file format) and that is just too restrictive.
|
||||
// Hence also allowing 1.24 on Windows.
|
||||
const MinVersion string = "1.24"
|
||||
12
vendor/github.com/docker/docker/api/swagger-gen.yaml
generated
vendored
12
vendor/github.com/docker/docker/api/swagger-gen.yaml
generated
vendored
@@ -1,12 +0,0 @@
|
||||
|
||||
layout:
|
||||
models:
|
||||
- name: definition
|
||||
source: asset:model
|
||||
target: "{{ joinFilePath .Target .ModelPackage }}"
|
||||
file_name: "{{ (snakize (pascalize .Name)) }}.go"
|
||||
operations:
|
||||
- name: handler
|
||||
source: asset:serverOperation
|
||||
target: "{{ joinFilePath .Target .APIPackage .Package }}"
|
||||
file_name: "{{ (snakize (pascalize .Name)) }}.go"
|
||||
10136
vendor/github.com/docker/docker/api/swagger.yaml
generated
vendored
10136
vendor/github.com/docker/docker/api/swagger.yaml
generated
vendored
File diff suppressed because it is too large
Load Diff
2
vendor/github.com/docker/docker/api/types/auth.go
generated
vendored
2
vendor/github.com/docker/docker/api/types/auth.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package types // import "github.com/docker/docker/api/types"
|
||||
package types
|
||||
|
||||
// AuthConfig contains authorization information for connecting to a Registry
|
||||
type AuthConfig struct {
|
||||
|
||||
2
vendor/github.com/docker/docker/api/types/blkiodev/blkio.go
generated
vendored
2
vendor/github.com/docker/docker/api/types/blkiodev/blkio.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package blkiodev // import "github.com/docker/docker/api/types/blkiodev"
|
||||
package blkiodev
|
||||
|
||||
import "fmt"
|
||||
|
||||
|
||||
96
vendor/github.com/docker/docker/api/types/client.go
generated
vendored
96
vendor/github.com/docker/docker/api/types/client.go
generated
vendored
@@ -1,9 +1,10 @@
|
||||
package types // import "github.com/docker/docker/api/types"
|
||||
package types
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
@@ -74,7 +75,6 @@ type ContainerLogsOptions struct {
|
||||
ShowStdout bool
|
||||
ShowStderr bool
|
||||
Since string
|
||||
Until string
|
||||
Timestamps bool
|
||||
Follow bool
|
||||
Tail string
|
||||
@@ -98,7 +98,6 @@ type ContainerStartOptions struct {
|
||||
// about files to copy into a container
|
||||
type CopyToContainerOptions struct {
|
||||
AllowOverwriteDirWithFile bool
|
||||
CopyUIDGID bool
|
||||
}
|
||||
|
||||
// EventsOptions holds parameters to filter events with.
|
||||
@@ -161,10 +160,9 @@ type ImageBuildOptions struct {
|
||||
ShmSize int64
|
||||
Dockerfile string
|
||||
Ulimits []*units.Ulimit
|
||||
// BuildArgs needs to be a *string instead of just a string so that
|
||||
// we can tell the difference between "" (empty string) and no value
|
||||
// at all (nil). See the parsing of buildArgs in
|
||||
// api/server/router/build/build_routes.go for even more info.
|
||||
// See the parsing of buildArgs in api/server/router/build/build_routes.go
|
||||
// for an explaination of why BuildArgs needs to use *string instead of
|
||||
// just a string
|
||||
BuildArgs map[string]*string
|
||||
AuthConfigs map[string]AuthConfig
|
||||
Context io.Reader
|
||||
@@ -177,28 +175,8 @@ type ImageBuildOptions struct {
|
||||
// specified here do not need to have a valid parent chain to match cache.
|
||||
CacheFrom []string
|
||||
SecurityOpt []string
|
||||
ExtraHosts []string // List of extra hosts
|
||||
Target string
|
||||
SessionID string
|
||||
Platform string
|
||||
// Version specifies the version of the unerlying builder to use
|
||||
Version BuilderVersion
|
||||
// BuildID is an optional identifier that can be passed together with the
|
||||
// build request. The same identifier can be used to gracefully cancel the
|
||||
// build with the cancel request.
|
||||
BuildID string
|
||||
}
|
||||
|
||||
// BuilderVersion sets the version of underlying builder to use
|
||||
type BuilderVersion string
|
||||
|
||||
const (
|
||||
// BuilderV1 is the first generation builder in docker daemon
|
||||
BuilderV1 BuilderVersion = "1"
|
||||
// BuilderBuildKit is builder based on moby/buildkit project
|
||||
BuilderBuildKit = "2"
|
||||
)
|
||||
|
||||
// ImageBuildResponse holds information
|
||||
// returned by a server after building
|
||||
// an image.
|
||||
@@ -209,22 +187,20 @@ type ImageBuildResponse struct {
|
||||
|
||||
// ImageCreateOptions holds information to create images.
|
||||
type ImageCreateOptions struct {
|
||||
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry.
|
||||
Platform string // Platform is the target platform of the image if it needs to be pulled from the registry.
|
||||
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
|
||||
}
|
||||
|
||||
// ImageImportSource holds source information for ImageImport
|
||||
type ImageImportSource struct {
|
||||
Source io.Reader // Source is the data to send to the server to create this image from. You must set SourceName to "-" to leverage this.
|
||||
SourceName string // SourceName is the name of the image to pull. Set to "-" to leverage the Source attribute.
|
||||
Source io.Reader // Source is the data to send to the server to create this image from (mutually exclusive with SourceName)
|
||||
SourceName string // SourceName is the name of the image to pull (mutually exclusive with Source)
|
||||
}
|
||||
|
||||
// ImageImportOptions holds information to import images from the client host.
|
||||
type ImageImportOptions struct {
|
||||
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
|
||||
Message string // Message is the message to tag the image with
|
||||
Changes []string // Changes are the raw changes to apply to this image
|
||||
Platform string // Platform is the target platform of the image
|
||||
Tag string // Tag is the name to tag this image with. This attribute is deprecated.
|
||||
Message string // Message is the message to tag the image with
|
||||
Changes []string // Changes are the raw changes to apply to this image
|
||||
}
|
||||
|
||||
// ImageListOptions holds parameters to filter the list of images with.
|
||||
@@ -245,7 +221,6 @@ type ImagePullOptions struct {
|
||||
All bool
|
||||
RegistryAuth string // RegistryAuth is the base64 encoded credentials for the registry
|
||||
PrivilegeFunc RequestPrivilegeFunc
|
||||
Platform string
|
||||
}
|
||||
|
||||
// RequestPrivilegeFunc is a function interface that
|
||||
@@ -281,6 +256,18 @@ type ResizeOptions struct {
|
||||
Width uint
|
||||
}
|
||||
|
||||
// VersionResponse holds version information for the client and the server
|
||||
type VersionResponse struct {
|
||||
Client *Version
|
||||
Server *Version
|
||||
}
|
||||
|
||||
// ServerOK returns true when the client could connect to the docker server
|
||||
// and parse the information received. It returns false otherwise.
|
||||
func (v VersionResponse) ServerOK() bool {
|
||||
return v.Server != nil
|
||||
}
|
||||
|
||||
// NodeListOptions holds parameters to list nodes with.
|
||||
type NodeListOptions struct {
|
||||
Filters filters.Args
|
||||
@@ -298,12 +285,6 @@ type ServiceCreateOptions struct {
|
||||
//
|
||||
// This field follows the format of the X-Registry-Auth header.
|
||||
EncodedRegistryAuth string
|
||||
|
||||
// QueryRegistry indicates whether the service update requires
|
||||
// contacting a registry. A registry may be contacted to retrieve
|
||||
// the image digest and manifest, which in turn can be used to update
|
||||
// platform or other information about the service.
|
||||
QueryRegistry bool
|
||||
}
|
||||
|
||||
// ServiceCreateResponse contains the information returned to a client
|
||||
@@ -337,32 +318,14 @@ type ServiceUpdateOptions struct {
|
||||
// credentials if they are not given in EncodedRegistryAuth. Valid
|
||||
// values are "spec" and "previous-spec".
|
||||
RegistryAuthFrom string
|
||||
|
||||
// Rollback indicates whether a server-side rollback should be
|
||||
// performed. When this is set, the provided spec will be ignored.
|
||||
// The valid values are "previous" and "none". An empty value is the
|
||||
// same as "none".
|
||||
Rollback string
|
||||
|
||||
// QueryRegistry indicates whether the service update requires
|
||||
// contacting a registry. A registry may be contacted to retrieve
|
||||
// the image digest and manifest, which in turn can be used to update
|
||||
// platform or other information about the service.
|
||||
QueryRegistry bool
|
||||
}
|
||||
|
||||
// ServiceListOptions holds parameters to list services with.
|
||||
// ServiceListOptions holds parameters to list services with.
|
||||
type ServiceListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
|
||||
// ServiceInspectOptions holds parameters related to the "service inspect"
|
||||
// operation.
|
||||
type ServiceInspectOptions struct {
|
||||
InsertDefaults bool
|
||||
}
|
||||
|
||||
// TaskListOptions holds parameters to list tasks with.
|
||||
// TaskListOptions holds parameters to list tasks with.
|
||||
type TaskListOptions struct {
|
||||
Filters filters.Args
|
||||
}
|
||||
@@ -393,6 +356,15 @@ type PluginInstallOptions struct {
|
||||
Args []string
|
||||
}
|
||||
|
||||
// SecretRequestOption is a type for requesting secrets
|
||||
type SecretRequestOption struct {
|
||||
Source string
|
||||
Target string
|
||||
UID string
|
||||
GID string
|
||||
Mode os.FileMode
|
||||
}
|
||||
|
||||
// SwarmUnlockKeyResponse contains the response for Engine API:
|
||||
// GET /swarm/unlockkey
|
||||
type SwarmUnlockKeyResponse struct {
|
||||
|
||||
16
vendor/github.com/docker/docker/api/types/configs.go
generated
vendored
16
vendor/github.com/docker/docker/api/types/configs.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package types // import "github.com/docker/docker/api/types"
|
||||
package types
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/types/container"
|
||||
@@ -25,6 +25,19 @@ type ContainerRmConfig struct {
|
||||
ForceRemove, RemoveVolume, RemoveLink bool
|
||||
}
|
||||
|
||||
// ContainerCommitConfig contains build configs for commit operation,
|
||||
// and is used when making a commit with the current state of the container.
|
||||
type ContainerCommitConfig struct {
|
||||
Pause bool
|
||||
Repo string
|
||||
Tag string
|
||||
Author string
|
||||
Comment string
|
||||
// merge container config into commit config before commit
|
||||
MergeConfigs bool
|
||||
Config *container.Config
|
||||
}
|
||||
|
||||
// ExecConfig is a small subset of the Config struct that holds the configuration
|
||||
// for the exec feature of docker.
|
||||
type ExecConfig struct {
|
||||
@@ -37,7 +50,6 @@ type ExecConfig struct {
|
||||
Detach bool // Execute in detach mode
|
||||
DetachKeys string // Escape keys for detach
|
||||
Env []string // Environment variables
|
||||
WorkingDir string // Working directory
|
||||
Cmd []string // Execution commands and args
|
||||
}
|
||||
|
||||
|
||||
13
vendor/github.com/docker/docker/api/types/container/config.go
generated
vendored
13
vendor/github.com/docker/docker/api/types/container/config.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package container // import "github.com/docker/docker/api/types/container"
|
||||
package container
|
||||
|
||||
import (
|
||||
"time"
|
||||
@@ -7,12 +7,6 @@ import (
|
||||
"github.com/docker/go-connections/nat"
|
||||
)
|
||||
|
||||
// MinimumDuration puts a minimum on user configured duration.
|
||||
// This is to prevent API error on time unit. For example, API may
|
||||
// set 3 as healthcheck interval with intention of 3 seconds, but
|
||||
// Docker interprets it as 3 nanoseconds.
|
||||
const MinimumDuration = 1 * time.Millisecond
|
||||
|
||||
// HealthConfig holds configuration settings for the HEALTHCHECK feature.
|
||||
type HealthConfig struct {
|
||||
// Test is the test to perform to check that the container is healthy.
|
||||
@@ -25,9 +19,8 @@ type HealthConfig struct {
|
||||
Test []string `json:",omitempty"`
|
||||
|
||||
// Zero means to inherit. Durations are expressed as integer nanoseconds.
|
||||
Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
|
||||
Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
|
||||
StartPeriod time.Duration `json:",omitempty"` // The start period for the container to initialize before the retries starts to count down.
|
||||
Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
|
||||
Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
|
||||
|
||||
// Retries is the number of consecutive failures needed to consider a container as unhealthy.
|
||||
// Zero means inherit.
|
||||
|
||||
21
vendor/github.com/docker/docker/api/types/container/container_changes.go
generated
vendored
21
vendor/github.com/docker/docker/api/types/container/container_changes.go
generated
vendored
@@ -1,21 +0,0 @@
|
||||
package container
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DO NOT EDIT THIS FILE
|
||||
// This file was generated by `swagger generate operation`
|
||||
//
|
||||
// See hack/generate-swagger-api.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ContainerChangeResponseItem change item in response to ContainerChanges operation
|
||||
// swagger:model ContainerChangeResponseItem
|
||||
type ContainerChangeResponseItem struct {
|
||||
|
||||
// Kind of change
|
||||
// Required: true
|
||||
Kind uint8 `json:"Kind"`
|
||||
|
||||
// Path to file that has changed
|
||||
// Required: true
|
||||
Path string `json:"Path"`
|
||||
}
|
||||
4
vendor/github.com/docker/docker/api/types/container/container_create.go
generated
vendored
4
vendor/github.com/docker/docker/api/types/container/container_create.go
generated
vendored
@@ -4,10 +4,10 @@ package container
|
||||
// DO NOT EDIT THIS FILE
|
||||
// This file was generated by `swagger generate operation`
|
||||
//
|
||||
// See hack/generate-swagger-api.sh
|
||||
// See hack/swagger-gen.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ContainerCreateCreatedBody OK response to ContainerCreate operation
|
||||
// ContainerCreateCreatedBody container create created body
|
||||
// swagger:model ContainerCreateCreatedBody
|
||||
type ContainerCreateCreatedBody struct {
|
||||
|
||||
|
||||
21
vendor/github.com/docker/docker/api/types/container/container_top.go
generated
vendored
21
vendor/github.com/docker/docker/api/types/container/container_top.go
generated
vendored
@@ -1,21 +0,0 @@
|
||||
package container
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DO NOT EDIT THIS FILE
|
||||
// This file was generated by `swagger generate operation`
|
||||
//
|
||||
// See hack/generate-swagger-api.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ContainerTopOKBody OK response to ContainerTop operation
|
||||
// swagger:model ContainerTopOKBody
|
||||
type ContainerTopOKBody struct {
|
||||
|
||||
// Each process running in the container, where each is process is an array of values corresponding to the titles
|
||||
// Required: true
|
||||
Processes [][]string `json:"Processes"`
|
||||
|
||||
// The ps column titles
|
||||
// Required: true
|
||||
Titles []string `json:"Titles"`
|
||||
}
|
||||
4
vendor/github.com/docker/docker/api/types/container/container_update.go
generated
vendored
4
vendor/github.com/docker/docker/api/types/container/container_update.go
generated
vendored
@@ -4,10 +4,10 @@ package container
|
||||
// DO NOT EDIT THIS FILE
|
||||
// This file was generated by `swagger generate operation`
|
||||
//
|
||||
// See hack/generate-swagger-api.sh
|
||||
// See hack/swagger-gen.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ContainerUpdateOKBody OK response to ContainerUpdate operation
|
||||
// ContainerUpdateOKBody container update o k body
|
||||
// swagger:model ContainerUpdateOKBody
|
||||
type ContainerUpdateOKBody struct {
|
||||
|
||||
|
||||
16
vendor/github.com/docker/docker/api/types/container/container_wait.go
generated
vendored
16
vendor/github.com/docker/docker/api/types/container/container_wait.go
generated
vendored
@@ -4,25 +4,13 @@ package container
|
||||
// DO NOT EDIT THIS FILE
|
||||
// This file was generated by `swagger generate operation`
|
||||
//
|
||||
// See hack/generate-swagger-api.sh
|
||||
// See hack/swagger-gen.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ContainerWaitOKBodyError container waiting error, if any
|
||||
// swagger:model ContainerWaitOKBodyError
|
||||
type ContainerWaitOKBodyError struct {
|
||||
|
||||
// Details of an error
|
||||
Message string `json:"Message,omitempty"`
|
||||
}
|
||||
|
||||
// ContainerWaitOKBody OK response to ContainerWait operation
|
||||
// ContainerWaitOKBody container wait o k body
|
||||
// swagger:model ContainerWaitOKBody
|
||||
type ContainerWaitOKBody struct {
|
||||
|
||||
// error
|
||||
// Required: true
|
||||
Error *ContainerWaitOKBodyError `json:"Error"`
|
||||
|
||||
// Exit code of the container
|
||||
// Required: true
|
||||
StatusCode int64 `json:"StatusCode"`
|
||||
|
||||
127
vendor/github.com/docker/docker/api/types/container/host_config.go
generated
vendored
127
vendor/github.com/docker/docker/api/types/container/host_config.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package container // import "github.com/docker/docker/api/types/container"
|
||||
package container
|
||||
|
||||
import (
|
||||
"strings"
|
||||
@@ -10,6 +10,9 @@ import (
|
||||
"github.com/docker/go-units"
|
||||
)
|
||||
|
||||
// NetworkMode represents the container network stack.
|
||||
type NetworkMode string
|
||||
|
||||
// Isolation represents the isolation technology of a container. The supported
|
||||
// values are platform specific
|
||||
type Isolation string
|
||||
@@ -20,101 +23,42 @@ func (i Isolation) IsDefault() bool {
|
||||
return strings.ToLower(string(i)) == "default" || string(i) == ""
|
||||
}
|
||||
|
||||
// IsHyperV indicates the use of a Hyper-V partition for isolation
|
||||
func (i Isolation) IsHyperV() bool {
|
||||
return strings.ToLower(string(i)) == "hyperv"
|
||||
}
|
||||
|
||||
// IsProcess indicates the use of process isolation
|
||||
func (i Isolation) IsProcess() bool {
|
||||
return strings.ToLower(string(i)) == "process"
|
||||
}
|
||||
|
||||
const (
|
||||
// IsolationEmpty is unspecified (same behavior as default)
|
||||
IsolationEmpty = Isolation("")
|
||||
// IsolationDefault is the default isolation mode on current daemon
|
||||
IsolationDefault = Isolation("default")
|
||||
// IsolationProcess is process isolation mode
|
||||
IsolationProcess = Isolation("process")
|
||||
// IsolationHyperV is HyperV isolation mode
|
||||
IsolationHyperV = Isolation("hyperv")
|
||||
)
|
||||
|
||||
// IpcMode represents the container ipc stack.
|
||||
type IpcMode string
|
||||
|
||||
// IsPrivate indicates whether the container uses its own private ipc namespace which can not be shared.
|
||||
// IsPrivate indicates whether the container uses its private ipc stack.
|
||||
func (n IpcMode) IsPrivate() bool {
|
||||
return n == "private"
|
||||
return !(n.IsHost() || n.IsContainer())
|
||||
}
|
||||
|
||||
// IsHost indicates whether the container shares the host's ipc namespace.
|
||||
// IsHost indicates whether the container uses the host's ipc stack.
|
||||
func (n IpcMode) IsHost() bool {
|
||||
return n == "host"
|
||||
}
|
||||
|
||||
// IsShareable indicates whether the container's ipc namespace can be shared with another container.
|
||||
func (n IpcMode) IsShareable() bool {
|
||||
return n == "shareable"
|
||||
}
|
||||
|
||||
// IsContainer indicates whether the container uses another container's ipc namespace.
|
||||
// IsContainer indicates whether the container uses a container's ipc stack.
|
||||
func (n IpcMode) IsContainer() bool {
|
||||
parts := strings.SplitN(string(n), ":", 2)
|
||||
return len(parts) > 1 && parts[0] == "container"
|
||||
}
|
||||
|
||||
// IsNone indicates whether container IpcMode is set to "none".
|
||||
func (n IpcMode) IsNone() bool {
|
||||
return n == "none"
|
||||
}
|
||||
|
||||
// IsEmpty indicates whether container IpcMode is empty
|
||||
func (n IpcMode) IsEmpty() bool {
|
||||
return n == ""
|
||||
}
|
||||
|
||||
// Valid indicates whether the ipc mode is valid.
|
||||
// Valid indicates whether the ipc stack is valid.
|
||||
func (n IpcMode) Valid() bool {
|
||||
return n.IsEmpty() || n.IsNone() || n.IsPrivate() || n.IsHost() || n.IsShareable() || n.IsContainer()
|
||||
parts := strings.Split(string(n), ":")
|
||||
switch mode := parts[0]; mode {
|
||||
case "", "host":
|
||||
case "container":
|
||||
if len(parts) != 2 || parts[1] == "" {
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Container returns the name of the container ipc stack is going to be used.
|
||||
func (n IpcMode) Container() string {
|
||||
parts := strings.SplitN(string(n), ":", 2)
|
||||
if len(parts) > 1 && parts[0] == "container" {
|
||||
return parts[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NetworkMode represents the container network stack.
|
||||
type NetworkMode string
|
||||
|
||||
// IsNone indicates whether container isn't using a network stack.
|
||||
func (n NetworkMode) IsNone() bool {
|
||||
return n == "none"
|
||||
}
|
||||
|
||||
// IsDefault indicates whether container uses the default network stack.
|
||||
func (n NetworkMode) IsDefault() bool {
|
||||
return n == "default"
|
||||
}
|
||||
|
||||
// IsPrivate indicates whether container uses its private network stack.
|
||||
func (n NetworkMode) IsPrivate() bool {
|
||||
return !(n.IsHost() || n.IsContainer())
|
||||
}
|
||||
|
||||
// IsContainer indicates whether container uses a container network stack.
|
||||
func (n NetworkMode) IsContainer() bool {
|
||||
parts := strings.SplitN(string(n), ":", 2)
|
||||
return len(parts) > 1 && parts[0] == "container"
|
||||
}
|
||||
|
||||
// ConnectedContainer is the id of the container which network this container is connected to.
|
||||
func (n NetworkMode) ConnectedContainer() string {
|
||||
parts := strings.SplitN(string(n), ":", 2)
|
||||
if len(parts) > 1 {
|
||||
return parts[1]
|
||||
@@ -122,14 +66,6 @@ func (n NetworkMode) ConnectedContainer() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
//UserDefined indicates user-created network
|
||||
func (n NetworkMode) UserDefined() string {
|
||||
if n.IsUserDefined() {
|
||||
return string(n)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// UsernsMode represents userns mode in the container.
|
||||
type UsernsMode string
|
||||
|
||||
@@ -287,17 +223,6 @@ func (rp *RestartPolicy) IsSame(tp *RestartPolicy) bool {
|
||||
return rp.Name == tp.Name && rp.MaximumRetryCount == tp.MaximumRetryCount
|
||||
}
|
||||
|
||||
// LogMode is a type to define the available modes for logging
|
||||
// These modes affect how logs are handled when log messages start piling up.
|
||||
type LogMode string
|
||||
|
||||
// Available logging modes
|
||||
const (
|
||||
LogModeUnset = ""
|
||||
LogModeBlocking LogMode = "blocking"
|
||||
LogModeNonBlock LogMode = "non-blocking"
|
||||
)
|
||||
|
||||
// LogConfig represents the logging configuration of the container.
|
||||
type LogConfig struct {
|
||||
Type string
|
||||
@@ -326,7 +251,6 @@ type Resources struct {
|
||||
CpusetCpus string // CpusetCpus 0-2, 0,1
|
||||
CpusetMems string // CpusetMems 0-2, 0,1
|
||||
Devices []DeviceMapping // List of devices to map inside the container
|
||||
DeviceCgroupRules []string // List of rule to be added to the device cgroup
|
||||
DiskQuota int64 // Disk limit (in bytes)
|
||||
KernelMemory int64 // Kernel memory limit (in bytes)
|
||||
MemoryReservation int64 // Memory soft limit (in bytes)
|
||||
@@ -393,7 +317,7 @@ type HostConfig struct {
|
||||
|
||||
// Applicable to Windows
|
||||
ConsoleSize [2]uint // Initial console size (height,width)
|
||||
Isolation Isolation // Isolation technology of the container (e.g. default, hyperv)
|
||||
Isolation Isolation // Isolation technology of the container (eg default, hyperv)
|
||||
|
||||
// Contains container's resources (cgroups, ulimits)
|
||||
Resources
|
||||
@@ -401,12 +325,9 @@ type HostConfig struct {
|
||||
// Mounts specs used by the container
|
||||
Mounts []mount.Mount `json:",omitempty"`
|
||||
|
||||
// MaskedPaths is the list of paths to be masked inside the container (this overrides the default set of paths)
|
||||
MaskedPaths []string
|
||||
|
||||
// ReadonlyPaths is the list of paths to be set as read-only inside the container (this overrides the default set of paths)
|
||||
ReadonlyPaths []string
|
||||
|
||||
// Run a custom init inside the container, if null, use the daemon's configured settings
|
||||
Init *bool `json:",omitempty"`
|
||||
|
||||
// Custom init path
|
||||
InitPath string `json:",omitempty"`
|
||||
}
|
||||
|
||||
42
vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go
generated
vendored
42
vendor/github.com/docker/docker/api/types/container/hostconfig_unix.go
generated
vendored
@@ -1,12 +1,24 @@
|
||||
// +build !windows
|
||||
|
||||
package container // import "github.com/docker/docker/api/types/container"
|
||||
package container
|
||||
|
||||
import "strings"
|
||||
|
||||
// IsValid indicates if an isolation technology is valid
|
||||
func (i Isolation) IsValid() bool {
|
||||
return i.IsDefault()
|
||||
}
|
||||
|
||||
// IsPrivate indicates whether container uses its private network stack.
|
||||
func (n NetworkMode) IsPrivate() bool {
|
||||
return !(n.IsHost() || n.IsContainer())
|
||||
}
|
||||
|
||||
// IsDefault indicates whether container uses the default network stack.
|
||||
func (n NetworkMode) IsDefault() bool {
|
||||
return n == "default"
|
||||
}
|
||||
|
||||
// NetworkName returns the name of the network stack.
|
||||
func (n NetworkMode) NetworkName() string {
|
||||
if n.IsBridge() {
|
||||
@@ -35,7 +47,35 @@ func (n NetworkMode) IsHost() bool {
|
||||
return n == "host"
|
||||
}
|
||||
|
||||
// IsContainer indicates whether container uses a container network stack.
|
||||
func (n NetworkMode) IsContainer() bool {
|
||||
parts := strings.SplitN(string(n), ":", 2)
|
||||
return len(parts) > 1 && parts[0] == "container"
|
||||
}
|
||||
|
||||
// IsNone indicates whether container isn't using a network stack.
|
||||
func (n NetworkMode) IsNone() bool {
|
||||
return n == "none"
|
||||
}
|
||||
|
||||
// ConnectedContainer is the id of the container which network this container is connected to.
|
||||
func (n NetworkMode) ConnectedContainer() string {
|
||||
parts := strings.SplitN(string(n), ":", 2)
|
||||
if len(parts) > 1 {
|
||||
return parts[1]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsUserDefined indicates user-created network
|
||||
func (n NetworkMode) IsUserDefined() bool {
|
||||
return !n.IsDefault() && !n.IsBridge() && !n.IsHost() && !n.IsNone() && !n.IsContainer()
|
||||
}
|
||||
|
||||
//UserDefined indicates user-created network
|
||||
func (n NetworkMode) UserDefined() string {
|
||||
if n.IsUserDefined() {
|
||||
return string(n)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
55
vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go
generated
vendored
55
vendor/github.com/docker/docker/api/types/container/hostconfig_windows.go
generated
vendored
@@ -1,4 +1,24 @@
|
||||
package container // import "github.com/docker/docker/api/types/container"
|
||||
package container
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IsDefault indicates whether container uses the default network stack.
|
||||
func (n NetworkMode) IsDefault() bool {
|
||||
return n == "default"
|
||||
}
|
||||
|
||||
// IsNone indicates whether container isn't using a network stack.
|
||||
func (n NetworkMode) IsNone() bool {
|
||||
return n == "none"
|
||||
}
|
||||
|
||||
// IsContainer indicates whether container uses a container network stack.
|
||||
// Returns false as windows doesn't support this mode
|
||||
func (n NetworkMode) IsContainer() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsBridge indicates whether container uses the bridge network stack
|
||||
// in windows it is given the name NAT
|
||||
@@ -12,9 +32,30 @@ func (n NetworkMode) IsHost() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsPrivate indicates whether container uses its private network stack.
|
||||
func (n NetworkMode) IsPrivate() bool {
|
||||
return !(n.IsHost() || n.IsContainer())
|
||||
}
|
||||
|
||||
// ConnectedContainer is the id of the container which network this container is connected to.
|
||||
// Returns blank string on windows
|
||||
func (n NetworkMode) ConnectedContainer() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// IsUserDefined indicates user-created network
|
||||
func (n NetworkMode) IsUserDefined() bool {
|
||||
return !n.IsDefault() && !n.IsNone() && !n.IsBridge() && !n.IsContainer()
|
||||
return !n.IsDefault() && !n.IsNone() && !n.IsBridge()
|
||||
}
|
||||
|
||||
// IsHyperV indicates the use of a Hyper-V partition for isolation
|
||||
func (i Isolation) IsHyperV() bool {
|
||||
return strings.ToLower(string(i)) == "hyperv"
|
||||
}
|
||||
|
||||
// IsProcess indicates the use of process isolation
|
||||
func (i Isolation) IsProcess() bool {
|
||||
return strings.ToLower(string(i)) == "process"
|
||||
}
|
||||
|
||||
// IsValid indicates if an isolation technology is valid
|
||||
@@ -30,11 +71,17 @@ func (n NetworkMode) NetworkName() string {
|
||||
return "nat"
|
||||
} else if n.IsNone() {
|
||||
return "none"
|
||||
} else if n.IsContainer() {
|
||||
return "container"
|
||||
} else if n.IsUserDefined() {
|
||||
return n.UserDefined()
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
//UserDefined indicates user-created network
|
||||
func (n NetworkMode) UserDefined() string {
|
||||
if n.IsUserDefined() {
|
||||
return string(n)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
22
vendor/github.com/docker/docker/api/types/container/waitcondition.go
generated
vendored
22
vendor/github.com/docker/docker/api/types/container/waitcondition.go
generated
vendored
@@ -1,22 +0,0 @@
|
||||
package container // import "github.com/docker/docker/api/types/container"
|
||||
|
||||
// WaitCondition is a type used to specify a container state for which
|
||||
// to wait.
|
||||
type WaitCondition string
|
||||
|
||||
// Possible WaitCondition Values.
|
||||
//
|
||||
// WaitConditionNotRunning (default) is used to wait for any of the non-running
|
||||
// states: "created", "exited", "dead", "removing", or "removed".
|
||||
//
|
||||
// WaitConditionNextExit is used to wait for the next time the state changes
|
||||
// to a non-running state. If the state is currently "created" or "exited",
|
||||
// this would cause Wait() to block until either the container runs and exits
|
||||
// or is removed.
|
||||
//
|
||||
// WaitConditionRemoved is used to wait for the container to be removed.
|
||||
const (
|
||||
WaitConditionNotRunning WaitCondition = "not-running"
|
||||
WaitConditionNextExit WaitCondition = "next-exit"
|
||||
WaitConditionRemoved WaitCondition = "removed"
|
||||
)
|
||||
12
vendor/github.com/docker/docker/api/types/events/events.go
generated
vendored
12
vendor/github.com/docker/docker/api/types/events/events.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package events // import "github.com/docker/docker/api/types/events"
|
||||
package events
|
||||
|
||||
const (
|
||||
// ContainerEventType is the event type that containers generate
|
||||
@@ -13,14 +13,6 @@ const (
|
||||
PluginEventType = "plugin"
|
||||
// VolumeEventType is the event type that volumes generate
|
||||
VolumeEventType = "volume"
|
||||
// ServiceEventType is the event type that services generate
|
||||
ServiceEventType = "service"
|
||||
// NodeEventType is the event type that nodes generate
|
||||
NodeEventType = "node"
|
||||
// SecretEventType is the event type that secrets generate
|
||||
SecretEventType = "secret"
|
||||
// ConfigEventType is the event type that configs generate
|
||||
ConfigEventType = "config"
|
||||
)
|
||||
|
||||
// Actor describes something that generates events,
|
||||
@@ -44,8 +36,6 @@ type Message struct {
|
||||
Type string
|
||||
Action string
|
||||
Actor Actor
|
||||
// Engine events are local scope. Cluster events are swarm scope.
|
||||
Scope string `json:"scope,omitempty"`
|
||||
|
||||
Time int64 `json:"time,omitempty"`
|
||||
TimeNano int64 `json:"timeNano,omitempty"`
|
||||
|
||||
282
vendor/github.com/docker/docker/api/types/filters/parse.go
generated
vendored
282
vendor/github.com/docker/docker/api/types/filters/parse.go
generated
vendored
@@ -1,45 +1,38 @@
|
||||
/*Package filters provides tools for encoding a mapping of keys to a set of
|
||||
multiple values.
|
||||
*/
|
||||
package filters // import "github.com/docker/docker/api/types/filters"
|
||||
// Package filters provides helper function to parse and handle command line
|
||||
// filter, used for example in docker ps or docker images commands.
|
||||
package filters
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/docker/docker/api/types/versions"
|
||||
)
|
||||
|
||||
// Args stores a mapping of keys to a set of multiple values.
|
||||
// Args stores filter arguments as map key:{map key: bool}.
|
||||
// It contains an aggregation of the map of arguments (which are in the form
|
||||
// of -f 'key=value') based on the key, and stores values for the same key
|
||||
// in a map with string keys and boolean values.
|
||||
// e.g given -f 'label=label1=1' -f 'label=label2=2' -f 'image.name=ubuntu'
|
||||
// the args will be {"image.name":{"ubuntu":true},"label":{"label1=1":true,"label2=2":true}}
|
||||
type Args struct {
|
||||
fields map[string]map[string]bool
|
||||
}
|
||||
|
||||
// KeyValuePair are used to initialize a new Args
|
||||
type KeyValuePair struct {
|
||||
Key string
|
||||
Value string
|
||||
// NewArgs initializes a new Args struct.
|
||||
func NewArgs() Args {
|
||||
return Args{fields: map[string]map[string]bool{}}
|
||||
}
|
||||
|
||||
// Arg creates a new KeyValuePair for initializing Args
|
||||
func Arg(key, value string) KeyValuePair {
|
||||
return KeyValuePair{Key: key, Value: value}
|
||||
}
|
||||
|
||||
// NewArgs returns a new Args populated with the initial args
|
||||
func NewArgs(initialArgs ...KeyValuePair) Args {
|
||||
args := Args{fields: map[string]map[string]bool{}}
|
||||
for _, arg := range initialArgs {
|
||||
args.Add(arg.Key, arg.Value)
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
// ParseFlag parses a key=value string and adds it to an Args.
|
||||
// ParseFlag parses the argument to the filter flag. Like
|
||||
//
|
||||
// Deprecated: Use Args.Add()
|
||||
// `docker ps -f 'created=today' -f 'image.name=ubuntu*'`
|
||||
//
|
||||
// If prev map is provided, then it is appended to, and returned. By default a new
|
||||
// map is created.
|
||||
func ParseFlag(arg string, prev Args) (Args, error) {
|
||||
filters := prev
|
||||
if len(arg) == 0 {
|
||||
@@ -60,95 +53,74 @@ func ParseFlag(arg string, prev Args) (Args, error) {
|
||||
return filters, nil
|
||||
}
|
||||
|
||||
// ErrBadFormat is an error returned when a filter is not in the form key=value
|
||||
//
|
||||
// Deprecated: this error will be removed in a future version
|
||||
// ErrBadFormat is an error returned in case of bad format for a filter.
|
||||
var ErrBadFormat = errors.New("bad format of filter (expected name=value)")
|
||||
|
||||
// ToParam encodes the Args as args JSON encoded string
|
||||
//
|
||||
// Deprecated: use ToJSON
|
||||
// ToParam packs the Args into a string for easy transport from client to server.
|
||||
func ToParam(a Args) (string, error) {
|
||||
return ToJSON(a)
|
||||
}
|
||||
|
||||
// MarshalJSON returns a JSON byte representation of the Args
|
||||
func (args Args) MarshalJSON() ([]byte, error) {
|
||||
if len(args.fields) == 0 {
|
||||
return []byte{}, nil
|
||||
}
|
||||
return json.Marshal(args.fields)
|
||||
}
|
||||
|
||||
// ToJSON returns the Args as a JSON encoded string
|
||||
func ToJSON(a Args) (string, error) {
|
||||
// this way we don't URL encode {}, just empty space
|
||||
if a.Len() == 0 {
|
||||
return "", nil
|
||||
}
|
||||
buf, err := json.Marshal(a)
|
||||
return string(buf), err
|
||||
|
||||
buf, err := json.Marshal(a.fields)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
// ToParamWithVersion encodes Args as a JSON string. If version is less than 1.22
|
||||
// then the encoded format will use an older legacy format where the values are a
|
||||
// list of strings, instead of a set.
|
||||
//
|
||||
// Deprecated: Use ToJSON
|
||||
// ToParamWithVersion packs the Args into a string for easy transport from client to server.
|
||||
// The generated string will depend on the specified version (corresponding to the API version).
|
||||
func ToParamWithVersion(version string, a Args) (string, error) {
|
||||
// this way we don't URL encode {}, just empty space
|
||||
if a.Len() == 0 {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// for daemons older than v1.10, filter must be of the form map[string][]string
|
||||
buf := []byte{}
|
||||
err := errors.New("")
|
||||
if version != "" && versions.LessThan(version, "1.22") {
|
||||
buf, err := json.Marshal(convertArgsToSlice(a.fields))
|
||||
return string(buf), err
|
||||
buf, err = json.Marshal(convertArgsToSlice(a.fields))
|
||||
} else {
|
||||
buf, err = json.Marshal(a.fields)
|
||||
}
|
||||
|
||||
return ToJSON(a)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(buf), nil
|
||||
}
|
||||
|
||||
// FromParam decodes a JSON encoded string into Args
|
||||
//
|
||||
// Deprecated: use FromJSON
|
||||
// FromParam unpacks the filter Args.
|
||||
func FromParam(p string) (Args, error) {
|
||||
return FromJSON(p)
|
||||
if len(p) == 0 {
|
||||
return NewArgs(), nil
|
||||
}
|
||||
|
||||
r := strings.NewReader(p)
|
||||
d := json.NewDecoder(r)
|
||||
|
||||
m := map[string]map[string]bool{}
|
||||
if err := d.Decode(&m); err != nil {
|
||||
r.Seek(0, 0)
|
||||
|
||||
// Allow parsing old arguments in slice format.
|
||||
// Because other libraries might be sending them in this format.
|
||||
deprecated := map[string][]string{}
|
||||
if deprecatedErr := d.Decode(&deprecated); deprecatedErr == nil {
|
||||
m = deprecatedArgs(deprecated)
|
||||
} else {
|
||||
return NewArgs(), err
|
||||
}
|
||||
}
|
||||
return Args{m}, nil
|
||||
}
|
||||
|
||||
// FromJSON decodes a JSON encoded string into Args
|
||||
func FromJSON(p string) (Args, error) {
|
||||
args := NewArgs()
|
||||
|
||||
if p == "" {
|
||||
return args, nil
|
||||
}
|
||||
|
||||
raw := []byte(p)
|
||||
err := json.Unmarshal(raw, &args)
|
||||
if err == nil {
|
||||
return args, nil
|
||||
}
|
||||
|
||||
// Fallback to parsing arguments in the legacy slice format
|
||||
deprecated := map[string][]string{}
|
||||
if legacyErr := json.Unmarshal(raw, &deprecated); legacyErr != nil {
|
||||
return args, err
|
||||
}
|
||||
|
||||
args.fields = deprecatedArgs(deprecated)
|
||||
return args, nil
|
||||
}
|
||||
|
||||
// UnmarshalJSON populates the Args from JSON encode bytes
|
||||
func (args Args) UnmarshalJSON(raw []byte) error {
|
||||
if len(raw) == 0 {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(raw, &args.fields)
|
||||
}
|
||||
|
||||
// Get returns the list of values associated with the key
|
||||
func (args Args) Get(key string) []string {
|
||||
values := args.fields[key]
|
||||
// Get returns the list of values associates with a field.
|
||||
// It returns a slice of strings to keep backwards compatibility with old code.
|
||||
func (filters Args) Get(field string) []string {
|
||||
values := filters.fields[field]
|
||||
if values == nil {
|
||||
return make([]string, 0)
|
||||
}
|
||||
@@ -159,34 +131,37 @@ func (args Args) Get(key string) []string {
|
||||
return slice
|
||||
}
|
||||
|
||||
// Add a new value to the set of values
|
||||
func (args Args) Add(key, value string) {
|
||||
if _, ok := args.fields[key]; ok {
|
||||
args.fields[key][value] = true
|
||||
// Add adds a new value to a filter field.
|
||||
func (filters Args) Add(name, value string) {
|
||||
if _, ok := filters.fields[name]; ok {
|
||||
filters.fields[name][value] = true
|
||||
} else {
|
||||
args.fields[key] = map[string]bool{value: true}
|
||||
filters.fields[name] = map[string]bool{value: true}
|
||||
}
|
||||
}
|
||||
|
||||
// Del removes a value from the set
|
||||
func (args Args) Del(key, value string) {
|
||||
if _, ok := args.fields[key]; ok {
|
||||
delete(args.fields[key], value)
|
||||
if len(args.fields[key]) == 0 {
|
||||
delete(args.fields, key)
|
||||
// Del removes a value from a filter field.
|
||||
func (filters Args) Del(name, value string) {
|
||||
if _, ok := filters.fields[name]; ok {
|
||||
delete(filters.fields[name], value)
|
||||
if len(filters.fields[name]) == 0 {
|
||||
delete(filters.fields, name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Len returns the number of keys in the mapping
|
||||
func (args Args) Len() int {
|
||||
return len(args.fields)
|
||||
// Len returns the number of fields in the arguments.
|
||||
func (filters Args) Len() int {
|
||||
return len(filters.fields)
|
||||
}
|
||||
|
||||
// MatchKVList returns true if all the pairs in sources exist as key=value
|
||||
// pairs in the mapping at key, or if there are no values at key.
|
||||
func (args Args) MatchKVList(key string, sources map[string]string) bool {
|
||||
fieldValues := args.fields[key]
|
||||
// MatchKVList returns true if the values for the specified field matches the ones
|
||||
// from the sources.
|
||||
// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}},
|
||||
// field is 'label' and sources are {'label1': '1', 'label2': '2'}
|
||||
// it returns true.
|
||||
func (filters Args) MatchKVList(field string, sources map[string]string) bool {
|
||||
fieldValues := filters.fields[field]
|
||||
|
||||
//do not filter if there is no filter set or cannot determine filter
|
||||
if len(fieldValues) == 0 {
|
||||
@@ -197,8 +172,8 @@ func (args Args) MatchKVList(key string, sources map[string]string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
for value := range fieldValues {
|
||||
testKV := strings.SplitN(value, "=", 2)
|
||||
for name2match := range fieldValues {
|
||||
testKV := strings.SplitN(name2match, "=", 2)
|
||||
|
||||
v, ok := sources[testKV[0]]
|
||||
if !ok {
|
||||
@@ -212,13 +187,16 @@ func (args Args) MatchKVList(key string, sources map[string]string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// Match returns true if any of the values at key match the source string
|
||||
func (args Args) Match(field, source string) bool {
|
||||
if args.ExactMatch(field, source) {
|
||||
// Match returns true if the values for the specified field matches the source string
|
||||
// e.g. given Args are {'label': {'label1=1','label2=1'}, 'image.name', {'ubuntu'}},
|
||||
// field is 'image.name' and source is 'ubuntu'
|
||||
// it returns true.
|
||||
func (filters Args) Match(field, source string) bool {
|
||||
if filters.ExactMatch(field, source) {
|
||||
return true
|
||||
}
|
||||
|
||||
fieldValues := args.fields[field]
|
||||
fieldValues := filters.fields[field]
|
||||
for name2match := range fieldValues {
|
||||
match, err := regexp.MatchString(name2match, source)
|
||||
if err != nil {
|
||||
@@ -231,9 +209,9 @@ func (args Args) Match(field, source string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ExactMatch returns true if the source matches exactly one of the values.
|
||||
func (args Args) ExactMatch(key, source string) bool {
|
||||
fieldValues, ok := args.fields[key]
|
||||
// ExactMatch returns true if the source matches exactly one of the filters.
|
||||
func (filters Args) ExactMatch(field, source string) bool {
|
||||
fieldValues, ok := filters.fields[field]
|
||||
//do not filter if there is no filter set or cannot determine filter
|
||||
if !ok || len(fieldValues) == 0 {
|
||||
return true
|
||||
@@ -243,15 +221,14 @@ func (args Args) ExactMatch(key, source string) bool {
|
||||
return fieldValues[source]
|
||||
}
|
||||
|
||||
// UniqueExactMatch returns true if there is only one value and the source
|
||||
// matches exactly the value.
|
||||
func (args Args) UniqueExactMatch(key, source string) bool {
|
||||
fieldValues := args.fields[key]
|
||||
// UniqueExactMatch returns true if there is only one filter and the source matches exactly this one.
|
||||
func (filters Args) UniqueExactMatch(field, source string) bool {
|
||||
fieldValues := filters.fields[field]
|
||||
//do not filter if there is no filter set or cannot determine filter
|
||||
if len(fieldValues) == 0 {
|
||||
return true
|
||||
}
|
||||
if len(args.fields[key]) != 1 {
|
||||
if len(filters.fields[field]) != 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -259,14 +236,14 @@ func (args Args) UniqueExactMatch(key, source string) bool {
|
||||
return fieldValues[source]
|
||||
}
|
||||
|
||||
// FuzzyMatch returns true if the source matches exactly one value, or the
|
||||
// source has one of the values as a prefix.
|
||||
func (args Args) FuzzyMatch(key, source string) bool {
|
||||
if args.ExactMatch(key, source) {
|
||||
// FuzzyMatch returns true if the source matches exactly one of the filters,
|
||||
// or the source has one of the filters as a prefix.
|
||||
func (filters Args) FuzzyMatch(field, source string) bool {
|
||||
if filters.ExactMatch(field, source) {
|
||||
return true
|
||||
}
|
||||
|
||||
fieldValues := args.fields[key]
|
||||
fieldValues := filters.fields[field]
|
||||
for prefix := range fieldValues {
|
||||
if strings.HasPrefix(source, prefix) {
|
||||
return true
|
||||
@@ -275,47 +252,30 @@ func (args Args) FuzzyMatch(key, source string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// Include returns true if the key exists in the mapping
|
||||
//
|
||||
// Deprecated: use Contains
|
||||
func (args Args) Include(field string) bool {
|
||||
_, ok := args.fields[field]
|
||||
// Include returns true if the name of the field to filter is in the filters.
|
||||
func (filters Args) Include(field string) bool {
|
||||
_, ok := filters.fields[field]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Contains returns true if the key exists in the mapping
|
||||
func (args Args) Contains(field string) bool {
|
||||
_, ok := args.fields[field]
|
||||
return ok
|
||||
}
|
||||
|
||||
type invalidFilter string
|
||||
|
||||
func (e invalidFilter) Error() string {
|
||||
return "Invalid filter '" + string(e) + "'"
|
||||
}
|
||||
|
||||
func (invalidFilter) InvalidParameter() {}
|
||||
|
||||
// Validate compared the set of accepted keys against the keys in the mapping.
|
||||
// An error is returned if any mapping keys are not in the accepted set.
|
||||
func (args Args) Validate(accepted map[string]bool) error {
|
||||
for name := range args.fields {
|
||||
// Validate ensures that all the fields in the filter are valid.
|
||||
// It returns an error as soon as it finds an invalid field.
|
||||
func (filters Args) Validate(accepted map[string]bool) error {
|
||||
for name := range filters.fields {
|
||||
if !accepted[name] {
|
||||
return invalidFilter(name)
|
||||
return fmt.Errorf("Invalid filter '%s'", name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WalkValues iterates over the list of values for a key in the mapping and calls
|
||||
// op() for each value. If op returns an error the iteration stops and the
|
||||
// error is returned.
|
||||
func (args Args) WalkValues(field string, op func(value string) error) error {
|
||||
if _, ok := args.fields[field]; !ok {
|
||||
// WalkValues iterates over the list of filtered values for a field.
|
||||
// It stops the iteration if it finds an error and it returns that error.
|
||||
func (filters Args) WalkValues(field string, op func(value string) error) error {
|
||||
if _, ok := filters.fields[field]; !ok {
|
||||
return nil
|
||||
}
|
||||
for v := range args.fields[field] {
|
||||
for v := range filters.fields[field] {
|
||||
if err := op(v); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
17
vendor/github.com/docker/docker/api/types/graph_driver_data.go
generated
vendored
17
vendor/github.com/docker/docker/api/types/graph_driver_data.go
generated
vendored
@@ -1,17 +0,0 @@
|
||||
package types
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
// GraphDriverData Information about a container's graph driver.
|
||||
// swagger:model GraphDriverData
|
||||
type GraphDriverData struct {
|
||||
|
||||
// data
|
||||
// Required: true
|
||||
Data map[string]string `json:"Data"`
|
||||
|
||||
// name
|
||||
// Required: true
|
||||
Name string `json:"Name"`
|
||||
}
|
||||
37
vendor/github.com/docker/docker/api/types/image/image_history.go
generated
vendored
37
vendor/github.com/docker/docker/api/types/image/image_history.go
generated
vendored
@@ -1,37 +0,0 @@
|
||||
package image
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DO NOT EDIT THIS FILE
|
||||
// This file was generated by `swagger generate operation`
|
||||
//
|
||||
// See hack/generate-swagger-api.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// HistoryResponseItem individual image layer information in response to ImageHistory operation
|
||||
// swagger:model HistoryResponseItem
|
||||
type HistoryResponseItem struct {
|
||||
|
||||
// comment
|
||||
// Required: true
|
||||
Comment string `json:"Comment"`
|
||||
|
||||
// created
|
||||
// Required: true
|
||||
Created int64 `json:"Created"`
|
||||
|
||||
// created by
|
||||
// Required: true
|
||||
CreatedBy string `json:"CreatedBy"`
|
||||
|
||||
// Id
|
||||
// Required: true
|
||||
ID string `json:"Id"`
|
||||
|
||||
// size
|
||||
// Required: true
|
||||
Size int64 `json:"Size"`
|
||||
|
||||
// tags
|
||||
// Required: true
|
||||
Tags []string `json:"Tags"`
|
||||
}
|
||||
15
vendor/github.com/docker/docker/api/types/image_delete_response_item.go
generated
vendored
15
vendor/github.com/docker/docker/api/types/image_delete_response_item.go
generated
vendored
@@ -1,15 +0,0 @@
|
||||
package types
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
// ImageDeleteResponseItem image delete response item
|
||||
// swagger:model ImageDeleteResponseItem
|
||||
type ImageDeleteResponseItem struct {
|
||||
|
||||
// The image ID of an image that was deleted
|
||||
Deleted string `json:"Deleted,omitempty"`
|
||||
|
||||
// The image ID of an image that was untagged
|
||||
Untagged string `json:"Untagged,omitempty"`
|
||||
}
|
||||
27
vendor/github.com/docker/docker/api/types/mount/mount.go
generated
vendored
27
vendor/github.com/docker/docker/api/types/mount/mount.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package mount // import "github.com/docker/docker/api/types/mount"
|
||||
package mount
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -15,8 +15,6 @@ const (
|
||||
TypeVolume Type = "volume"
|
||||
// TypeTmpfs is the type for mounting tmpfs
|
||||
TypeTmpfs Type = "tmpfs"
|
||||
// TypeNamedPipe is the type for mounting Windows named pipes
|
||||
TypeNamedPipe Type = "npipe"
|
||||
)
|
||||
|
||||
// Mount represents a mount (volume).
|
||||
@@ -25,10 +23,9 @@ type Mount struct {
|
||||
// Source specifies the name of the mount. Depending on mount type, this
|
||||
// may be a volume name or a host path, or even ignored.
|
||||
// Source is not supported for tmpfs (must be an empty value)
|
||||
Source string `json:",omitempty"`
|
||||
Target string `json:",omitempty"`
|
||||
ReadOnly bool `json:",omitempty"`
|
||||
Consistency Consistency `json:",omitempty"`
|
||||
Source string `json:",omitempty"`
|
||||
Target string `json:",omitempty"`
|
||||
ReadOnly bool `json:",omitempty"`
|
||||
|
||||
BindOptions *BindOptions `json:",omitempty"`
|
||||
VolumeOptions *VolumeOptions `json:",omitempty"`
|
||||
@@ -63,20 +60,6 @@ var Propagations = []Propagation{
|
||||
PropagationSlave,
|
||||
}
|
||||
|
||||
// Consistency represents the consistency requirements of a mount.
|
||||
type Consistency string
|
||||
|
||||
const (
|
||||
// ConsistencyFull guarantees bind mount-like consistency
|
||||
ConsistencyFull Consistency = "consistent"
|
||||
// ConsistencyCached mounts can cache read data and FS structure
|
||||
ConsistencyCached Consistency = "cached"
|
||||
// ConsistencyDelegated mounts can cache read and written data and structure
|
||||
ConsistencyDelegated Consistency = "delegated"
|
||||
// ConsistencyDefault provides "consistent" behavior unless overridden
|
||||
ConsistencyDefault Consistency = "default"
|
||||
)
|
||||
|
||||
// BindOptions defines options specific to mounts of type "bind".
|
||||
type BindOptions struct {
|
||||
Propagation Propagation `json:",omitempty"`
|
||||
@@ -100,7 +83,7 @@ type TmpfsOptions struct {
|
||||
// Size sets the size of the tmpfs, in bytes.
|
||||
//
|
||||
// This will be converted to an operating system specific value
|
||||
// depending on the host. For example, on linux, it will be converted to
|
||||
// depending on the host. For example, on linux, it will be convered to
|
||||
// use a 'k', 'm' or 'g' syntax. BSD, though not widely supported with
|
||||
// docker, uses a straight byte value.
|
||||
//
|
||||
|
||||
53
vendor/github.com/docker/docker/api/types/network/network.go
generated
vendored
53
vendor/github.com/docker/docker/api/types/network/network.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package network // import "github.com/docker/docker/api/types/network"
|
||||
package network
|
||||
|
||||
// Address represents an IP address
|
||||
type Address struct {
|
||||
@@ -28,15 +28,7 @@ type EndpointIPAMConfig struct {
|
||||
LinkLocalIPs []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Copy makes a copy of the endpoint ipam config
|
||||
func (cfg *EndpointIPAMConfig) Copy() *EndpointIPAMConfig {
|
||||
cfgCopy := *cfg
|
||||
cfgCopy.LinkLocalIPs = make([]string, 0, len(cfg.LinkLocalIPs))
|
||||
cfgCopy.LinkLocalIPs = append(cfgCopy.LinkLocalIPs, cfg.LinkLocalIPs...)
|
||||
return &cfgCopy
|
||||
}
|
||||
|
||||
// PeerInfo represents one peer of an overlay network
|
||||
// PeerInfo represents one peer of a overlay network
|
||||
type PeerInfo struct {
|
||||
Name string
|
||||
IP string
|
||||
@@ -58,42 +50,6 @@ type EndpointSettings struct {
|
||||
GlobalIPv6Address string
|
||||
GlobalIPv6PrefixLen int
|
||||
MacAddress string
|
||||
DriverOpts map[string]string
|
||||
}
|
||||
|
||||
// Task carries the information about one backend task
|
||||
type Task struct {
|
||||
Name string
|
||||
EndpointID string
|
||||
EndpointIP string
|
||||
Info map[string]string
|
||||
}
|
||||
|
||||
// ServiceInfo represents service parameters with the list of service's tasks
|
||||
type ServiceInfo struct {
|
||||
VIP string
|
||||
Ports []string
|
||||
LocalLBIndex int
|
||||
Tasks []Task
|
||||
}
|
||||
|
||||
// Copy makes a deep copy of `EndpointSettings`
|
||||
func (es *EndpointSettings) Copy() *EndpointSettings {
|
||||
epCopy := *es
|
||||
if es.IPAMConfig != nil {
|
||||
epCopy.IPAMConfig = es.IPAMConfig.Copy()
|
||||
}
|
||||
|
||||
if es.Links != nil {
|
||||
links := make([]string, 0, len(es.Links))
|
||||
epCopy.Links = append(links, es.Links...)
|
||||
}
|
||||
|
||||
if es.Aliases != nil {
|
||||
aliases := make([]string, 0, len(es.Aliases))
|
||||
epCopy.Aliases = append(aliases, es.Aliases...)
|
||||
}
|
||||
return &epCopy
|
||||
}
|
||||
|
||||
// NetworkingConfig represents the container's networking configuration for each of its interfaces
|
||||
@@ -101,8 +57,3 @@ func (es *EndpointSettings) Copy() *EndpointSettings {
|
||||
type NetworkingConfig struct {
|
||||
EndpointsConfig map[string]*EndpointSettings // Endpoint configs for each connecting network
|
||||
}
|
||||
|
||||
// ConfigReference specifies the source which provides a network's configuration
|
||||
type ConfigReference struct {
|
||||
Network string
|
||||
}
|
||||
|
||||
16
vendor/github.com/docker/docker/api/types/plugin.go
generated
vendored
16
vendor/github.com/docker/docker/api/types/plugin.go
generated
vendored
@@ -11,7 +11,7 @@ type Plugin struct {
|
||||
// Required: true
|
||||
Config PluginConfig `json:"Config"`
|
||||
|
||||
// True if the plugin is running. False if the plugin is not running, only installed.
|
||||
// True when the plugin is running. False when the plugin is not running, only installed.
|
||||
// Required: true
|
||||
Enabled bool `json:"Enabled"`
|
||||
|
||||
@@ -42,9 +42,6 @@ type PluginConfig struct {
|
||||
// Required: true
|
||||
Description string `json:"Description"`
|
||||
|
||||
// Docker Version used to create the plugin
|
||||
DockerVersion string `json:"DockerVersion,omitempty"`
|
||||
|
||||
// documentation
|
||||
// Required: true
|
||||
Documentation string `json:"Documentation"`
|
||||
@@ -61,10 +58,6 @@ type PluginConfig struct {
|
||||
// Required: true
|
||||
Interface PluginConfigInterface `json:"Interface"`
|
||||
|
||||
// ipc host
|
||||
// Required: true
|
||||
IpcHost bool `json:"IpcHost"`
|
||||
|
||||
// linux
|
||||
// Required: true
|
||||
Linux PluginConfigLinux `json:"Linux"`
|
||||
@@ -77,10 +70,6 @@ type PluginConfig struct {
|
||||
// Required: true
|
||||
Network PluginConfigNetwork `json:"Network"`
|
||||
|
||||
// pid host
|
||||
// Required: true
|
||||
PidHost bool `json:"PidHost"`
|
||||
|
||||
// propagated mount
|
||||
// Required: true
|
||||
PropagatedMount string `json:"PropagatedMount"`
|
||||
@@ -121,9 +110,6 @@ type PluginConfigArgs struct {
|
||||
// swagger:model PluginConfigInterface
|
||||
type PluginConfigInterface struct {
|
||||
|
||||
// Protocol to use for clients connecting to the plugin.
|
||||
ProtocolScheme string `json:"ProtocolScheme,omitempty"`
|
||||
|
||||
// socket
|
||||
// Required: true
|
||||
Socket string `json:"Socket"`
|
||||
|
||||
25
vendor/github.com/docker/docker/api/types/plugin_responses.go
generated
vendored
25
vendor/github.com/docker/docker/api/types/plugin_responses.go
generated
vendored
@@ -1,14 +1,21 @@
|
||||
package types // import "github.com/docker/docker/api/types"
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// PluginsListResponse contains the response for the Engine API
|
||||
type PluginsListResponse []*Plugin
|
||||
|
||||
const (
|
||||
authzDriver = "AuthzDriver"
|
||||
graphDriver = "GraphDriver"
|
||||
ipamDriver = "IpamDriver"
|
||||
networkDriver = "NetworkDriver"
|
||||
volumeDriver = "VolumeDriver"
|
||||
)
|
||||
|
||||
// UnmarshalJSON implements json.Unmarshaler for PluginInterfaceType
|
||||
func (t *PluginInterfaceType) UnmarshalJSON(p []byte) error {
|
||||
versionIndex := len(p)
|
||||
@@ -55,17 +62,3 @@ type PluginPrivilege struct {
|
||||
|
||||
// PluginPrivileges is a list of PluginPrivilege
|
||||
type PluginPrivileges []PluginPrivilege
|
||||
|
||||
func (s PluginPrivileges) Len() int {
|
||||
return len(s)
|
||||
}
|
||||
|
||||
func (s PluginPrivileges) Less(i, j int) bool {
|
||||
return s[i].Name < s[j].Name
|
||||
}
|
||||
|
||||
func (s PluginPrivileges) Swap(i, j int) {
|
||||
sort.Strings(s[i].Value)
|
||||
sort.Strings(s[j].Value)
|
||||
s[i], s[j] = s[j], s[i]
|
||||
}
|
||||
|
||||
2
vendor/github.com/docker/docker/api/types/port.go
generated
vendored
2
vendor/github.com/docker/docker/api/types/port.go
generated
vendored
@@ -7,7 +7,7 @@ package types
|
||||
// swagger:model Port
|
||||
type Port struct {
|
||||
|
||||
// Host IP address that the container's port is mapped to
|
||||
// IP
|
||||
IP string `json:"IP,omitempty"`
|
||||
|
||||
// Port on the container
|
||||
|
||||
34
vendor/github.com/docker/docker/api/types/reference/image_reference.go
generated
vendored
Normal file
34
vendor/github.com/docker/docker/api/types/reference/image_reference.go
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package reference
|
||||
|
||||
import (
|
||||
distreference "github.com/docker/distribution/reference"
|
||||
)
|
||||
|
||||
// Parse parses the given references and returns the repository and
|
||||
// tag (if present) from it. If there is an error during parsing, it will
|
||||
// return an error.
|
||||
func Parse(ref string) (string, string, error) {
|
||||
distributionRef, err := distreference.ParseNamed(ref)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
|
||||
tag := GetTagFromNamedRef(distributionRef)
|
||||
return distributionRef.Name(), tag, nil
|
||||
}
|
||||
|
||||
// GetTagFromNamedRef returns a tag from the specified reference.
|
||||
// This function is necessary as long as the docker "server" api makes the distinction between repository
|
||||
// and tags.
|
||||
func GetTagFromNamedRef(ref distreference.Named) string {
|
||||
var tag string
|
||||
switch x := ref.(type) {
|
||||
case distreference.Digested:
|
||||
tag = x.Digest().String()
|
||||
case distreference.NamedTagged:
|
||||
tag = x.Tag()
|
||||
default:
|
||||
tag = "latest"
|
||||
}
|
||||
return tag
|
||||
}
|
||||
4
vendor/github.com/docker/docker/api/types/registry/authenticate.go
generated
vendored
4
vendor/github.com/docker/docker/api/types/registry/authenticate.go
generated
vendored
@@ -1,10 +1,10 @@
|
||||
package registry // import "github.com/docker/docker/api/types/registry"
|
||||
package registry
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// DO NOT EDIT THIS FILE
|
||||
// This file was generated by `swagger generate operation`
|
||||
//
|
||||
// See hack/generate-swagger-api.sh
|
||||
// See hack/swagger-gen.sh
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// AuthenticateOKBody authenticate o k body
|
||||
|
||||
23
vendor/github.com/docker/docker/api/types/registry/registry.go
generated
vendored
23
vendor/github.com/docker/docker/api/types/registry/registry.go
generated
vendored
@@ -1,19 +1,15 @@
|
||||
package registry // import "github.com/docker/docker/api/types/registry"
|
||||
package registry
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
// ServiceConfig stores daemon registry services configuration.
|
||||
type ServiceConfig struct {
|
||||
AllowNondistributableArtifactsCIDRs []*NetIPNet
|
||||
AllowNondistributableArtifactsHostnames []string
|
||||
InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"`
|
||||
IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"`
|
||||
Mirrors []string
|
||||
InsecureRegistryCIDRs []*NetIPNet `json:"InsecureRegistryCIDRs"`
|
||||
IndexConfigs map[string]*IndexInfo `json:"IndexConfigs"`
|
||||
Mirrors []string
|
||||
}
|
||||
|
||||
// NetIPNet is the net.IPNet type, which can be marshalled and
|
||||
@@ -106,14 +102,3 @@ type SearchResults struct {
|
||||
// Results is a slice containing the actual results for the search
|
||||
Results []SearchResult `json:"results"`
|
||||
}
|
||||
|
||||
// DistributionInspect describes the result obtained from contacting the
|
||||
// registry to retrieve image metadata
|
||||
type DistributionInspect struct {
|
||||
// Descriptor contains information about the manifest, including
|
||||
// the content addressable digest
|
||||
Descriptor v1.Descriptor
|
||||
// Platforms contains the list of platforms supported by the image,
|
||||
// obtained by parsing the manifest
|
||||
Platforms []v1.Platform
|
||||
}
|
||||
|
||||
4
vendor/github.com/docker/docker/api/types/seccomp.go
generated
vendored
4
vendor/github.com/docker/docker/api/types/seccomp.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package types // import "github.com/docker/docker/api/types"
|
||||
package types
|
||||
|
||||
// Seccomp represents the config for a seccomp profile for syscall restriction.
|
||||
type Seccomp struct {
|
||||
@@ -10,7 +10,7 @@ type Seccomp struct {
|
||||
Syscalls []*Syscall `json:"syscalls"`
|
||||
}
|
||||
|
||||
// Architecture is used to represent a specific architecture
|
||||
// Architecture is used to represent an specific architecture
|
||||
// and its sub-architectures
|
||||
type Architecture struct {
|
||||
Arch Arch `json:"architecture"`
|
||||
|
||||
5
vendor/github.com/docker/docker/api/types/stats.go
generated
vendored
5
vendor/github.com/docker/docker/api/types/stats.go
generated
vendored
@@ -1,6 +1,6 @@
|
||||
// Package types is used for API stability in the types and response to the
|
||||
// consumers of the API stats endpoint.
|
||||
package types // import "github.com/docker/docker/api/types"
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
@@ -47,9 +47,6 @@ type CPUStats struct {
|
||||
// System Usage. Linux only.
|
||||
SystemUsage uint64 `json:"system_cpu_usage,omitempty"`
|
||||
|
||||
// Online CPUs. Linux only.
|
||||
OnlineCPUs uint32 `json:"online_cpus,omitempty"`
|
||||
|
||||
// Throttling Data. Linux only.
|
||||
ThrottlingData ThrottlingData `json:"throttling_data,omitempty"`
|
||||
}
|
||||
|
||||
2
vendor/github.com/docker/docker/api/types/strslice/strslice.go
generated
vendored
2
vendor/github.com/docker/docker/api/types/strslice/strslice.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package strslice // import "github.com/docker/docker/api/types/strslice"
|
||||
package strslice
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
|
||||
19
vendor/github.com/docker/docker/api/types/swarm/common.go
generated
vendored
19
vendor/github.com/docker/docker/api/types/swarm/common.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
package swarm
|
||||
|
||||
import "time"
|
||||
|
||||
@@ -17,24 +17,11 @@ type Meta struct {
|
||||
// Annotations represents how to describe an object.
|
||||
type Annotations struct {
|
||||
Name string `json:",omitempty"`
|
||||
Labels map[string]string `json:"Labels"`
|
||||
Labels map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Driver represents a driver (network, logging, secrets backend).
|
||||
// Driver represents a driver (network, logging).
|
||||
type Driver struct {
|
||||
Name string `json:",omitempty"`
|
||||
Options map[string]string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// TLSInfo represents the TLS information about what CA certificate is trusted,
|
||||
// and who the issuer for a TLS certificate is
|
||||
type TLSInfo struct {
|
||||
// TrustRoot is the trusted CA root certificate in PEM format
|
||||
TrustRoot string `json:",omitempty"`
|
||||
|
||||
// CertIssuer is the raw subject bytes of the issuer
|
||||
CertIssuerSubject []byte `json:",omitempty"`
|
||||
|
||||
// CertIssuerPublicKey is the raw public key bytes of the issuer
|
||||
CertIssuerPublicKey []byte `json:",omitempty"`
|
||||
}
|
||||
|
||||
35
vendor/github.com/docker/docker/api/types/swarm/config.go
generated
vendored
35
vendor/github.com/docker/docker/api/types/swarm/config.go
generated
vendored
@@ -1,35 +0,0 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
|
||||
import "os"
|
||||
|
||||
// Config represents a config.
|
||||
type Config struct {
|
||||
ID string
|
||||
Meta
|
||||
Spec ConfigSpec
|
||||
}
|
||||
|
||||
// ConfigSpec represents a config specification from a config in swarm
|
||||
type ConfigSpec struct {
|
||||
Annotations
|
||||
Data []byte `json:",omitempty"`
|
||||
|
||||
// Templating controls whether and how to evaluate the config payload as
|
||||
// a template. If it is not set, no templating is used.
|
||||
Templating *Driver `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ConfigReferenceFileTarget is a file target in a config reference
|
||||
type ConfigReferenceFileTarget struct {
|
||||
Name string
|
||||
UID string
|
||||
GID string
|
||||
Mode os.FileMode
|
||||
}
|
||||
|
||||
// ConfigReference is a reference to a config in swarm
|
||||
type ConfigReference struct {
|
||||
File *ConfigReferenceFileTarget
|
||||
ConfigID string
|
||||
ConfigName string
|
||||
}
|
||||
36
vendor/github.com/docker/docker/api/types/swarm/container.go
generated
vendored
36
vendor/github.com/docker/docker/api/types/swarm/container.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
package swarm
|
||||
|
||||
import (
|
||||
"time"
|
||||
@@ -21,28 +21,6 @@ type DNSConfig struct {
|
||||
Options []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// SELinuxContext contains the SELinux labels of the container.
|
||||
type SELinuxContext struct {
|
||||
Disable bool
|
||||
|
||||
User string
|
||||
Role string
|
||||
Type string
|
||||
Level string
|
||||
}
|
||||
|
||||
// CredentialSpec for managed service account (Windows only)
|
||||
type CredentialSpec struct {
|
||||
File string
|
||||
Registry string
|
||||
}
|
||||
|
||||
// Privileges defines the security options for the container.
|
||||
type Privileges struct {
|
||||
CredentialSpec *CredentialSpec
|
||||
SELinuxContext *SELinuxContext
|
||||
}
|
||||
|
||||
// ContainerSpec represents the spec of a container.
|
||||
type ContainerSpec struct {
|
||||
Image string `json:",omitempty"`
|
||||
@@ -54,21 +32,15 @@ type ContainerSpec struct {
|
||||
Dir string `json:",omitempty"`
|
||||
User string `json:",omitempty"`
|
||||
Groups []string `json:",omitempty"`
|
||||
Privileges *Privileges `json:",omitempty"`
|
||||
Init *bool `json:",omitempty"`
|
||||
StopSignal string `json:",omitempty"`
|
||||
TTY bool `json:",omitempty"`
|
||||
OpenStdin bool `json:",omitempty"`
|
||||
ReadOnly bool `json:",omitempty"`
|
||||
Mounts []mount.Mount `json:",omitempty"`
|
||||
StopGracePeriod *time.Duration `json:",omitempty"`
|
||||
Healthcheck *container.HealthConfig `json:",omitempty"`
|
||||
// The format of extra hosts on swarmkit is specified in:
|
||||
// http://man7.org/linux/man-pages/man5/hosts.5.html
|
||||
// IP_address canonical_hostname [aliases...]
|
||||
Hosts []string `json:",omitempty"`
|
||||
DNSConfig *DNSConfig `json:",omitempty"`
|
||||
Secrets []*SecretReference `json:",omitempty"`
|
||||
Configs []*ConfigReference `json:",omitempty"`
|
||||
Isolation container.Isolation `json:",omitempty"`
|
||||
Hosts []string `json:",omitempty"`
|
||||
DNSConfig *DNSConfig `json:",omitempty"`
|
||||
Secrets []*SecretReference `json:",omitempty"`
|
||||
}
|
||||
|
||||
26
vendor/github.com/docker/docker/api/types/swarm/network.go
generated
vendored
26
vendor/github.com/docker/docker/api/types/swarm/network.go
generated
vendored
@@ -1,8 +1,4 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
|
||||
import (
|
||||
"github.com/docker/docker/api/types/network"
|
||||
)
|
||||
package swarm
|
||||
|
||||
// Endpoint represents an endpoint.
|
||||
type Endpoint struct {
|
||||
@@ -62,8 +58,6 @@ const (
|
||||
PortConfigProtocolTCP PortConfigProtocol = "tcp"
|
||||
// PortConfigProtocolUDP UDP
|
||||
PortConfigProtocolUDP PortConfigProtocol = "udp"
|
||||
// PortConfigProtocolSCTP SCTP
|
||||
PortConfigProtocolSCTP PortConfigProtocol = "sctp"
|
||||
)
|
||||
|
||||
// EndpointVirtualIP represents the virtual ip of a port.
|
||||
@@ -84,21 +78,17 @@ type Network struct {
|
||||
// NetworkSpec represents the spec of a network.
|
||||
type NetworkSpec struct {
|
||||
Annotations
|
||||
DriverConfiguration *Driver `json:",omitempty"`
|
||||
IPv6Enabled bool `json:",omitempty"`
|
||||
Internal bool `json:",omitempty"`
|
||||
Attachable bool `json:",omitempty"`
|
||||
Ingress bool `json:",omitempty"`
|
||||
IPAMOptions *IPAMOptions `json:",omitempty"`
|
||||
ConfigFrom *network.ConfigReference `json:",omitempty"`
|
||||
Scope string `json:",omitempty"`
|
||||
DriverConfiguration *Driver `json:",omitempty"`
|
||||
IPv6Enabled bool `json:",omitempty"`
|
||||
Internal bool `json:",omitempty"`
|
||||
Attachable bool `json:",omitempty"`
|
||||
IPAMOptions *IPAMOptions `json:",omitempty"`
|
||||
}
|
||||
|
||||
// NetworkAttachmentConfig represents the configuration of a network attachment.
|
||||
type NetworkAttachmentConfig struct {
|
||||
Target string `json:",omitempty"`
|
||||
Aliases []string `json:",omitempty"`
|
||||
DriverOpts map[string]string `json:",omitempty"`
|
||||
Target string `json:",omitempty"`
|
||||
Aliases []string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// NetworkAttachment represents a network attachment.
|
||||
|
||||
3
vendor/github.com/docker/docker/api/types/swarm/node.go
generated
vendored
3
vendor/github.com/docker/docker/api/types/swarm/node.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
package swarm
|
||||
|
||||
// Node represents a node.
|
||||
type Node struct {
|
||||
@@ -52,7 +52,6 @@ type NodeDescription struct {
|
||||
Platform Platform `json:",omitempty"`
|
||||
Resources Resources `json:",omitempty"`
|
||||
Engine EngineDescription `json:",omitempty"`
|
||||
TLSInfo TLSInfo `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Platform represents the platform (Arch/OS).
|
||||
|
||||
27
vendor/github.com/docker/docker/api/types/swarm/runtime.go
generated
vendored
27
vendor/github.com/docker/docker/api/types/swarm/runtime.go
generated
vendored
@@ -1,27 +0,0 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
|
||||
// RuntimeType is the type of runtime used for the TaskSpec
|
||||
type RuntimeType string
|
||||
|
||||
// RuntimeURL is the proto type url
|
||||
type RuntimeURL string
|
||||
|
||||
const (
|
||||
// RuntimeContainer is the container based runtime
|
||||
RuntimeContainer RuntimeType = "container"
|
||||
// RuntimePlugin is the plugin based runtime
|
||||
RuntimePlugin RuntimeType = "plugin"
|
||||
// RuntimeNetworkAttachment is the network attachment runtime
|
||||
RuntimeNetworkAttachment RuntimeType = "attachment"
|
||||
|
||||
// RuntimeURLContainer is the proto url for the container type
|
||||
RuntimeURLContainer RuntimeURL = "types.docker.com/RuntimeContainer"
|
||||
// RuntimeURLPlugin is the proto url for the plugin type
|
||||
RuntimeURLPlugin RuntimeURL = "types.docker.com/RuntimePlugin"
|
||||
)
|
||||
|
||||
// NetworkAttachmentSpec represents the runtime spec type for network
|
||||
// attachment tasks
|
||||
type NetworkAttachmentSpec struct {
|
||||
ContainerID string
|
||||
}
|
||||
3
vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go
generated
vendored
3
vendor/github.com/docker/docker/api/types/swarm/runtime/gen.go
generated
vendored
@@ -1,3 +0,0 @@
|
||||
//go:generate protoc -I . --gogofast_out=import_path=github.com/docker/docker/api/types/swarm/runtime:. plugin.proto
|
||||
|
||||
package runtime // import "github.com/docker/docker/api/types/swarm/runtime"
|
||||
712
vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go
generated
vendored
712
vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.pb.go
generated
vendored
@@ -1,712 +0,0 @@
|
||||
// Code generated by protoc-gen-gogo.
|
||||
// source: plugin.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package runtime is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
plugin.proto
|
||||
|
||||
It has these top-level messages:
|
||||
PluginSpec
|
||||
PluginPrivilege
|
||||
*/
|
||||
package runtime
|
||||
|
||||
import proto "github.com/gogo/protobuf/proto"
|
||||
import fmt "fmt"
|
||||
import math "math"
|
||||
|
||||
import io "io"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
|
||||
// PluginSpec defines the base payload which clients can specify for creating
|
||||
// a service with the plugin runtime.
|
||||
type PluginSpec struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Remote string `protobuf:"bytes,2,opt,name=remote,proto3" json:"remote,omitempty"`
|
||||
Privileges []*PluginPrivilege `protobuf:"bytes,3,rep,name=privileges" json:"privileges,omitempty"`
|
||||
Disabled bool `protobuf:"varint,4,opt,name=disabled,proto3" json:"disabled,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PluginSpec) Reset() { *m = PluginSpec{} }
|
||||
func (m *PluginSpec) String() string { return proto.CompactTextString(m) }
|
||||
func (*PluginSpec) ProtoMessage() {}
|
||||
func (*PluginSpec) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{0} }
|
||||
|
||||
func (m *PluginSpec) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PluginSpec) GetRemote() string {
|
||||
if m != nil {
|
||||
return m.Remote
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PluginSpec) GetPrivileges() []*PluginPrivilege {
|
||||
if m != nil {
|
||||
return m.Privileges
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *PluginSpec) GetDisabled() bool {
|
||||
if m != nil {
|
||||
return m.Disabled
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// PluginPrivilege describes a permission the user has to accept
|
||||
// upon installing a plugin.
|
||||
type PluginPrivilege struct {
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"`
|
||||
Value []string `protobuf:"bytes,3,rep,name=value" json:"value,omitempty"`
|
||||
}
|
||||
|
||||
func (m *PluginPrivilege) Reset() { *m = PluginPrivilege{} }
|
||||
func (m *PluginPrivilege) String() string { return proto.CompactTextString(m) }
|
||||
func (*PluginPrivilege) ProtoMessage() {}
|
||||
func (*PluginPrivilege) Descriptor() ([]byte, []int) { return fileDescriptorPlugin, []int{1} }
|
||||
|
||||
func (m *PluginPrivilege) GetName() string {
|
||||
if m != nil {
|
||||
return m.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PluginPrivilege) GetDescription() string {
|
||||
if m != nil {
|
||||
return m.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *PluginPrivilege) GetValue() []string {
|
||||
if m != nil {
|
||||
return m.Value
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*PluginSpec)(nil), "PluginSpec")
|
||||
proto.RegisterType((*PluginPrivilege)(nil), "PluginPrivilege")
|
||||
}
|
||||
func (m *PluginSpec) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PluginSpec) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Name) > 0 {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name)))
|
||||
i += copy(dAtA[i:], m.Name)
|
||||
}
|
||||
if len(m.Remote) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Remote)))
|
||||
i += copy(dAtA[i:], m.Remote)
|
||||
}
|
||||
if len(m.Privileges) > 0 {
|
||||
for _, msg := range m.Privileges {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
i = encodeVarintPlugin(dAtA, i, uint64(msg.Size()))
|
||||
n, err := msg.MarshalTo(dAtA[i:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i += n
|
||||
}
|
||||
}
|
||||
if m.Disabled {
|
||||
dAtA[i] = 0x20
|
||||
i++
|
||||
if m.Disabled {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i++
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func (m *PluginPrivilege) Marshal() (dAtA []byte, err error) {
|
||||
size := m.Size()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalTo(dAtA)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *PluginPrivilege) MarshalTo(dAtA []byte) (int, error) {
|
||||
var i int
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Name) > 0 {
|
||||
dAtA[i] = 0xa
|
||||
i++
|
||||
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Name)))
|
||||
i += copy(dAtA[i:], m.Name)
|
||||
}
|
||||
if len(m.Description) > 0 {
|
||||
dAtA[i] = 0x12
|
||||
i++
|
||||
i = encodeVarintPlugin(dAtA, i, uint64(len(m.Description)))
|
||||
i += copy(dAtA[i:], m.Description)
|
||||
}
|
||||
if len(m.Value) > 0 {
|
||||
for _, s := range m.Value {
|
||||
dAtA[i] = 0x1a
|
||||
i++
|
||||
l = len(s)
|
||||
for l >= 1<<7 {
|
||||
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
|
||||
l >>= 7
|
||||
i++
|
||||
}
|
||||
dAtA[i] = uint8(l)
|
||||
i++
|
||||
i += copy(dAtA[i:], s)
|
||||
}
|
||||
}
|
||||
return i, nil
|
||||
}
|
||||
|
||||
func encodeFixed64Plugin(dAtA []byte, offset int, v uint64) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
dAtA[offset+4] = uint8(v >> 32)
|
||||
dAtA[offset+5] = uint8(v >> 40)
|
||||
dAtA[offset+6] = uint8(v >> 48)
|
||||
dAtA[offset+7] = uint8(v >> 56)
|
||||
return offset + 8
|
||||
}
|
||||
func encodeFixed32Plugin(dAtA []byte, offset int, v uint32) int {
|
||||
dAtA[offset] = uint8(v)
|
||||
dAtA[offset+1] = uint8(v >> 8)
|
||||
dAtA[offset+2] = uint8(v >> 16)
|
||||
dAtA[offset+3] = uint8(v >> 24)
|
||||
return offset + 4
|
||||
}
|
||||
func encodeVarintPlugin(dAtA []byte, offset int, v uint64) int {
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return offset + 1
|
||||
}
|
||||
func (m *PluginSpec) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Name)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovPlugin(uint64(l))
|
||||
}
|
||||
l = len(m.Remote)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovPlugin(uint64(l))
|
||||
}
|
||||
if len(m.Privileges) > 0 {
|
||||
for _, e := range m.Privileges {
|
||||
l = e.Size()
|
||||
n += 1 + l + sovPlugin(uint64(l))
|
||||
}
|
||||
}
|
||||
if m.Disabled {
|
||||
n += 2
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (m *PluginPrivilege) Size() (n int) {
|
||||
var l int
|
||||
_ = l
|
||||
l = len(m.Name)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovPlugin(uint64(l))
|
||||
}
|
||||
l = len(m.Description)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovPlugin(uint64(l))
|
||||
}
|
||||
if len(m.Value) > 0 {
|
||||
for _, s := range m.Value {
|
||||
l = len(s)
|
||||
n += 1 + l + sovPlugin(uint64(l))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovPlugin(x uint64) (n int) {
|
||||
for {
|
||||
n++
|
||||
x >>= 7
|
||||
if x == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
func sozPlugin(x uint64) (n int) {
|
||||
return sovPlugin(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *PluginSpec) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PluginSpec: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PluginSpec: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthPlugin
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Remote", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthPlugin
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Remote = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Privileges", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthPlugin
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Privileges = append(m.Privileges, &PluginPrivilege{})
|
||||
if err := m.Privileges[len(m.Privileges)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Disabled", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.Disabled = bool(v != 0)
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipPlugin(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthPlugin
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func (m *PluginPrivilege) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: PluginPrivilege: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: PluginPrivilege: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthPlugin
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Name = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Description", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthPlugin
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Description = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Value", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthPlugin
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Value = append(m.Value, string(dAtA[iNdEx:postIndex]))
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipPlugin(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if skippy < 0 {
|
||||
return ErrInvalidLengthPlugin
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipPlugin(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
return iNdEx, nil
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
iNdEx += length
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthPlugin
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 3:
|
||||
for {
|
||||
var innerWire uint64
|
||||
var start int = iNdEx
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowPlugin
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
innerWire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
innerWireType := int(innerWire & 0x7)
|
||||
if innerWireType == 4 {
|
||||
break
|
||||
}
|
||||
next, err := skipPlugin(dAtA[start:])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
iNdEx = start + next
|
||||
}
|
||||
return iNdEx, nil
|
||||
case 4:
|
||||
return iNdEx, nil
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
return iNdEx, nil
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
}
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthPlugin = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowPlugin = fmt.Errorf("proto: integer overflow")
|
||||
)
|
||||
|
||||
func init() { proto.RegisterFile("plugin.proto", fileDescriptorPlugin) }
|
||||
|
||||
var fileDescriptorPlugin = []byte{
|
||||
// 196 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xe2, 0xe2, 0x29, 0xc8, 0x29, 0x4d,
|
||||
0xcf, 0xcc, 0xd3, 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x57, 0x6a, 0x63, 0xe4, 0xe2, 0x0a, 0x00, 0x0b,
|
||||
0x04, 0x17, 0xa4, 0x26, 0x0b, 0x09, 0x71, 0xb1, 0xe4, 0x25, 0xe6, 0xa6, 0x4a, 0x30, 0x2a, 0x30,
|
||||
0x6a, 0x70, 0x06, 0x81, 0xd9, 0x42, 0x62, 0x5c, 0x6c, 0x45, 0xa9, 0xb9, 0xf9, 0x25, 0xa9, 0x12,
|
||||
0x4c, 0x60, 0x51, 0x28, 0x4f, 0xc8, 0x80, 0x8b, 0xab, 0xa0, 0x28, 0xb3, 0x2c, 0x33, 0x27, 0x35,
|
||||
0x3d, 0xb5, 0x58, 0x82, 0x59, 0x81, 0x59, 0x83, 0xdb, 0x48, 0x40, 0x0f, 0x62, 0x58, 0x00, 0x4c,
|
||||
0x22, 0x08, 0x49, 0x8d, 0x90, 0x14, 0x17, 0x47, 0x4a, 0x66, 0x71, 0x62, 0x52, 0x4e, 0x6a, 0x8a,
|
||||
0x04, 0x8b, 0x02, 0xa3, 0x06, 0x47, 0x10, 0x9c, 0xaf, 0x14, 0xcb, 0xc5, 0x8f, 0xa6, 0x15, 0xab,
|
||||
0x63, 0x14, 0xb8, 0xb8, 0x53, 0x52, 0x8b, 0x93, 0x8b, 0x32, 0x0b, 0x4a, 0x32, 0xf3, 0xf3, 0xa0,
|
||||
0x2e, 0x42, 0x16, 0x12, 0x12, 0xe1, 0x62, 0x2d, 0x4b, 0xcc, 0x29, 0x4d, 0x05, 0xbb, 0x88, 0x33,
|
||||
0x08, 0xc2, 0x71, 0xe2, 0x39, 0xf1, 0x48, 0x8e, 0xf1, 0xc2, 0x23, 0x39, 0xc6, 0x07, 0x8f, 0xe4,
|
||||
0x18, 0x93, 0xd8, 0xc0, 0x9e, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x84, 0xad, 0x79,
|
||||
0x0c, 0x01, 0x00, 0x00,
|
||||
}
|
||||
20
vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto
generated
vendored
20
vendor/github.com/docker/docker/api/types/swarm/runtime/plugin.proto
generated
vendored
@@ -1,20 +0,0 @@
|
||||
syntax = "proto3";
|
||||
|
||||
option go_package = "github.com/docker/docker/api/types/swarm/runtime;runtime";
|
||||
|
||||
// PluginSpec defines the base payload which clients can specify for creating
|
||||
// a service with the plugin runtime.
|
||||
message PluginSpec {
|
||||
string name = 1;
|
||||
string remote = 2;
|
||||
repeated PluginPrivilege privileges = 3;
|
||||
bool disabled = 4;
|
||||
}
|
||||
|
||||
// PluginPrivilege describes a permission the user has to accept
|
||||
// upon installing a plugin.
|
||||
message PluginPrivilege {
|
||||
string name = 1;
|
||||
string description = 2;
|
||||
repeated string value = 3;
|
||||
}
|
||||
9
vendor/github.com/docker/docker/api/types/swarm/secret.go
generated
vendored
9
vendor/github.com/docker/docker/api/types/swarm/secret.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
package swarm
|
||||
|
||||
import "os"
|
||||
|
||||
@@ -12,12 +12,7 @@ type Secret struct {
|
||||
// SecretSpec represents a secret specification from a secret in swarm
|
||||
type SecretSpec struct {
|
||||
Annotations
|
||||
Data []byte `json:",omitempty"`
|
||||
Driver *Driver `json:",omitempty"` // name of the secrets driver used to fetch the secret's value from an external secret store
|
||||
|
||||
// Templating controls whether and how to evaluate the secret payload as
|
||||
// a template. If it is not set, no templating is used.
|
||||
Templating *Driver `json:",omitempty"`
|
||||
Data []byte `json:",omitempty"`
|
||||
}
|
||||
|
||||
// SecretReferenceFileTarget is a file target in a secret reference
|
||||
|
||||
39
vendor/github.com/docker/docker/api/types/swarm/service.go
generated
vendored
39
vendor/github.com/docker/docker/api/types/swarm/service.go
generated
vendored
@@ -1,4 +1,4 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
package swarm
|
||||
|
||||
import "time"
|
||||
|
||||
@@ -6,10 +6,10 @@ import "time"
|
||||
type Service struct {
|
||||
ID string
|
||||
Meta
|
||||
Spec ServiceSpec `json:",omitempty"`
|
||||
PreviousSpec *ServiceSpec `json:",omitempty"`
|
||||
Endpoint Endpoint `json:",omitempty"`
|
||||
UpdateStatus *UpdateStatus `json:",omitempty"`
|
||||
Spec ServiceSpec `json:",omitempty"`
|
||||
PreviousSpec *ServiceSpec `json:",omitempty"`
|
||||
Endpoint Endpoint `json:",omitempty"`
|
||||
UpdateStatus UpdateStatus `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ServiceSpec represents the spec of a service.
|
||||
@@ -18,10 +18,9 @@ type ServiceSpec struct {
|
||||
|
||||
// TaskTemplate defines how the service should construct new tasks when
|
||||
// orchestrating this service.
|
||||
TaskTemplate TaskSpec `json:",omitempty"`
|
||||
Mode ServiceMode `json:",omitempty"`
|
||||
UpdateConfig *UpdateConfig `json:",omitempty"`
|
||||
RollbackConfig *UpdateConfig `json:",omitempty"`
|
||||
TaskTemplate TaskSpec `json:",omitempty"`
|
||||
Mode ServiceMode `json:",omitempty"`
|
||||
UpdateConfig *UpdateConfig `json:",omitempty"`
|
||||
|
||||
// Networks field in ServiceSpec is deprecated. The
|
||||
// same field in TaskSpec should be used instead.
|
||||
@@ -46,19 +45,13 @@ const (
|
||||
UpdateStatePaused UpdateState = "paused"
|
||||
// UpdateStateCompleted is the completed state.
|
||||
UpdateStateCompleted UpdateState = "completed"
|
||||
// UpdateStateRollbackStarted is the state with a rollback in progress.
|
||||
UpdateStateRollbackStarted UpdateState = "rollback_started"
|
||||
// UpdateStateRollbackPaused is the state with a rollback in progress.
|
||||
UpdateStateRollbackPaused UpdateState = "rollback_paused"
|
||||
// UpdateStateRollbackCompleted is the state with a rollback in progress.
|
||||
UpdateStateRollbackCompleted UpdateState = "rollback_completed"
|
||||
)
|
||||
|
||||
// UpdateStatus reports the status of a service update.
|
||||
type UpdateStatus struct {
|
||||
State UpdateState `json:",omitempty"`
|
||||
StartedAt *time.Time `json:",omitempty"`
|
||||
CompletedAt *time.Time `json:",omitempty"`
|
||||
StartedAt time.Time `json:",omitempty"`
|
||||
CompletedAt time.Time `json:",omitempty"`
|
||||
Message string `json:",omitempty"`
|
||||
}
|
||||
|
||||
@@ -75,13 +68,6 @@ const (
|
||||
UpdateFailureActionPause = "pause"
|
||||
// UpdateFailureActionContinue CONTINUE
|
||||
UpdateFailureActionContinue = "continue"
|
||||
// UpdateFailureActionRollback ROLLBACK
|
||||
UpdateFailureActionRollback = "rollback"
|
||||
|
||||
// UpdateOrderStopFirst STOP_FIRST
|
||||
UpdateOrderStopFirst = "stop-first"
|
||||
// UpdateOrderStartFirst START_FIRST
|
||||
UpdateOrderStartFirst = "start-first"
|
||||
)
|
||||
|
||||
// UpdateConfig represents the update configuration.
|
||||
@@ -116,9 +102,4 @@ type UpdateConfig struct {
|
||||
// If the failure action is PAUSE, no more tasks will be updated until
|
||||
// another update is started.
|
||||
MaxFailureRatio float32
|
||||
|
||||
// Order indicates the order of operations when rolling out an updated
|
||||
// task. Either the old task is shut down before the new task is
|
||||
// started, or the new task is started before the old task is shut down.
|
||||
Order string
|
||||
}
|
||||
|
||||
32
vendor/github.com/docker/docker/api/types/swarm/swarm.go
generated
vendored
32
vendor/github.com/docker/docker/api/types/swarm/swarm.go
generated
vendored
@@ -1,15 +1,13 @@
|
||||
package swarm // import "github.com/docker/docker/api/types/swarm"
|
||||
package swarm
|
||||
|
||||
import "time"
|
||||
|
||||
// ClusterInfo represents info about the cluster for outputting in "info"
|
||||
// ClusterInfo represents info about the cluster for outputing in "info"
|
||||
// it contains the same information as "Swarm", but without the JoinTokens
|
||||
type ClusterInfo struct {
|
||||
ID string
|
||||
Meta
|
||||
Spec Spec
|
||||
TLSInfo TLSInfo
|
||||
RootRotationInProgress bool
|
||||
Spec Spec
|
||||
}
|
||||
|
||||
// Swarm represents a swarm.
|
||||
@@ -109,16 +107,6 @@ type CAConfig struct {
|
||||
// ExternalCAs is a list of CAs to which a manager node will make
|
||||
// certificate signing requests for node certificates.
|
||||
ExternalCAs []*ExternalCA `json:",omitempty"`
|
||||
|
||||
// SigningCACert and SigningCAKey specify the desired signing root CA and
|
||||
// root CA key for the swarm. When inspecting the cluster, the key will
|
||||
// be redacted.
|
||||
SigningCACert string `json:",omitempty"`
|
||||
SigningCAKey string `json:",omitempty"`
|
||||
|
||||
// If this value changes, and there is no specified signing cert and key,
|
||||
// then the swarm is forced to generate a new root certificate ane key.
|
||||
ForceRotate uint64 `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ExternalCAProtocol represents type of external CA.
|
||||
@@ -138,31 +126,23 @@ type ExternalCA struct {
|
||||
// Options is a set of additional key/value pairs whose interpretation
|
||||
// depends on the specified CA type.
|
||||
Options map[string]string `json:",omitempty"`
|
||||
|
||||
// CACert specifies which root CA is used by this external CA. This certificate must
|
||||
// be in PEM format.
|
||||
CACert string
|
||||
}
|
||||
|
||||
// InitRequest is the request used to init a swarm.
|
||||
type InitRequest struct {
|
||||
ListenAddr string
|
||||
AdvertiseAddr string
|
||||
DataPathAddr string
|
||||
ForceNewCluster bool
|
||||
Spec Spec
|
||||
AutoLockManagers bool
|
||||
Availability NodeAvailability
|
||||
}
|
||||
|
||||
// JoinRequest is the request used to join a swarm.
|
||||
type JoinRequest struct {
|
||||
ListenAddr string
|
||||
AdvertiseAddr string
|
||||
DataPathAddr string
|
||||
RemoteAddrs []string
|
||||
JoinToken string // accept by secret
|
||||
Availability NodeAvailability
|
||||
}
|
||||
|
||||
// UnlockRequest is the request used to unlock a swarm.
|
||||
@@ -197,10 +177,10 @@ type Info struct {
|
||||
Error string
|
||||
|
||||
RemoteManagers []Peer
|
||||
Nodes int `json:",omitempty"`
|
||||
Managers int `json:",omitempty"`
|
||||
Nodes int
|
||||
Managers int
|
||||
|
||||
Cluster *ClusterInfo `json:",omitempty"`
|
||||
Cluster ClusterInfo
|
||||
}
|
||||
|
||||
// Peer represents a peer.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user