未验证 提交 858facd4 编写于 作者: Z zryfish 提交者: GitHub

Merge pull request #291 from wansir/advanced-2.0-dev

upgrade go version to 1.12

要显示的变更太多。

To preserve performance only 1000 of 1000+ files are displayed.
......@@ -7,7 +7,7 @@ git:
depth: false
go:
- 1.10.3
- 1.12
go_import_path: kubesphere.io/kubesphere
......@@ -17,7 +17,6 @@ before_install:
before_script:
- dep ensure -v
- docker --version
- git clone --single-branch -b v0.11.4 -q https://github.com/mholt/caddy $GOPATH/src/github.com/mholt/caddy
script:
- make test
......@@ -28,4 +27,4 @@ deploy:
provider: script
script: bash hack/docker_push.sh
on:
branch: master
branch: master
\ No newline at end of file
FROM golang:1.10.3 as builder
# Copy in the go src
WORKDIR /go/src/kubesphere.io/kubesphere
COPY pkg/ pkg/
COPY cmd/ cmd/
COPY vendor/ vendor/
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -a -o ks-apiserver kubesphere.io/kubesphere/cmd/ks-apiserver
FROM alpine:3.6
WORKDIR /
COPY --from=builder /go/src/kubesphere.io/kubesphere/ks-apiserver .
COPY ./install/ingress-controller /etc/kubesphere/ingress-controller
COPY ./install/swagger-ui /usr/lib/kubesphere/swagger-ui
CMD ["ks-apiserver"]
此差异已折叠。
......@@ -24,7 +24,6 @@
# go-tests = true
# unused-packages = true
ignored = ["github.com/mholt/caddy","github.com/mholt/caddy/caddyfile","github.com/mholt/caddy/caddyhttp/httpserver","github.com/mholt/caddy/caddyhttp/staticfiles","github.com/mholt/caddy/caddytls","github.com/mholt/caddy/telemetry"]
[[constraint]]
name = "github.com/docker/docker"
......@@ -70,18 +69,21 @@ ignored = ["github.com/mholt/caddy","github.com/mholt/caddy/caddyfile","github.c
name = "k8s.io/kubernetes"
version = "1.12.3"
[[constraint]]
name = "github.com/mholt/caddy"
version = "v0.11.5"
[[constraint]]
name="sigs.k8s.io/controller-runtime"
version="v0.1.9"
name = "sigs.k8s.io/controller-runtime"
version = "v0.1.9"
[[override]]
name="sigs.k8s.io/controller-tools"
version="v0.1.9"
name = "sigs.k8s.io/controller-tools"
version = "v0.1.9"
[[override]]
name="k8s.io/component-base"
branch="master"
name = "k8s.io/component-base"
branch = "master"
[prune]
go-tests = true
......@@ -113,6 +115,11 @@ ignored = ["github.com/mholt/caddy","github.com/mholt/caddy/caddyfile","github.c
# For dependency below: Refer to issue https://github.com/golang/dep/issues/1799
[[override]]
name = "gopkg.in/fsnotify.v1"
source = "https://github.com/fsnotify/fsnotify.git"
version="v1.4.7"
name = "gopkg.in/fsnotify.v1"
source = "https://github.com/fsnotify/fsnotify.git"
version = "v1.4.7"
[[override]]
name = "github.com/russross/blackfriday"
version = "v1.5.2"
\ No newline at end of file
......@@ -40,12 +40,20 @@ define ALL_HELP_INFO
# debugging tools like delve.
endef
.PHONY: all
all: ks-apiserver test
all: test ks-apiserver ks-apigateway ks-iam
# Build ks-apiserver binary
ks-apiserver: generate fmt vet
ks-apiserver: test
hack/gobuild.sh cmd/ks-apiserver
# Build ks-apigateway binary
ks-apigateway: test
hack/gobuild.sh cmd/ks-apigateway
# Build ks-iam binary
ks-iam: test
hack/gobuild.sh cmd/ks-iam
# Run go fmt against code
fmt:
go fmt ./pkg/... ./cmd/...
......@@ -62,7 +70,7 @@ endif
go generate ./pkg/... ./cmd/...
# Build the docker image
docker-build: test
docker-build: all
docker build . -t ${IMG}
# Run tests
......
......@@ -6,23 +6,15 @@
# Use of this source code is governed by a Apache license
# that can be found in the LICENSE file.
FROM golang:1.10.3 as ks-apigateway-builder
FROM golang:1.12 as ks-apigateway-builder
COPY / /go/src/kubesphere.io/kubesphere
RUN git clone --single-branch -b v0.11.4 -q https://github.com/mholt/caddy /go/src/github.com/mholt/caddy
WORKDIR /go/src/github.com/mholt/caddy
RUN sed -i "/\/\/ This is where other plugins get plugged in (imported)/a\\\t\
_ \"kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/authenticate\"\n\t\
_ \"kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/authentication\"\n\t\
_ \"kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/swagger\""\
caddy/caddymain/run.go && \
sed -i "/\/\/ github.com\/BTBurke\/caddy-jwt/a\\\t\"authenticate\",\n\t\"authentication\",\n\t\"swagger\","\
caddyhttp/httpserver/plugin.go && \
go install ./caddy && \
go run /go/src/kubesphere.io/kubesphere/tools/cmd/doc-gen/main.go --output=/go/src/kubesphere.io/kubesphere/install/swagger-ui/api.json
WORKDIR /go/src/kubesphere.io/kubesphere
RUN CGO_ENABLED=0 GO111MODULE=off GOOS=linux GOARCH=amd64 go build -i -ldflags '-w -s' -o ks-apigateway cmd/ks-apigateway/apiserver.go && \
go run tools/cmd/doc-gen/main.go --output=install/swagger-ui/api.json
FROM alpine:3.7
FROM alpine:3.9
RUN apk add --update ca-certificates && update-ca-certificates
COPY --from=ks-apigateway-builder /go/bin/* /usr/local/bin/
COPY --from=ks-apigateway-builder /go/src/kubesphere.io/kubesphere/ks-apigateway /usr/local/bin/
COPY --from=ks-apigateway-builder /go/src/kubesphere.io/kubesphere/install/swagger-ui /var/static/swagger-ui
CMD ["sh"]
\ No newline at end of file
......@@ -5,14 +5,14 @@
# Copyright 2018 The KubeSphere Authors. All rights reserved.
# Use of this source code is governed by a Apache license
# that can be found in the LICENSE file.
FROM golang:1.10.3 as ks-apiserver-builder
FROM golang:1.12 as ks-apiserver-builder
COPY / /go/src/kubesphere.io/kubesphere
WORKDIR /go/src/kubesphere.io/kubesphere
RUN go build -o ks-apiserver cmd/ks-apiserver/apiserver.go
WORKDIR /go/src/kubesphere.io/kubesphere
RUN CGO_ENABLED=0 GO111MODULE=off GOOS=linux GOARCH=amd64 go build -i -ldflags '-w -s' -o ks-apiserver cmd/ks-apiserver/apiserver.go
FROM alpine:3.7
FROM alpine:3.9
RUN apk add --update ca-certificates && update-ca-certificates
COPY --from=ks-apiserver-builder /go/src/kubesphere.io/kubesphere/ks-apiserver /usr/local/bin/
CMD ["sh"]
......@@ -5,14 +5,14 @@
# Copyright 2018 The KubeSphere Authors. All rights reserved.
# Use of this source code is governed by a Apache license
# that can be found in the LICENSE file.
FROM golang:1.10.3 as ks-iam-builder
FROM golang:1.12 as ks-iam-builder
COPY / /go/src/kubesphere.io/kubesphere
WORKDIR /go/src/kubesphere.io/kubesphere
RUN go build -o ks-iam cmd/ks-iam/main.go
WORKDIR /go/src/kubesphere.io/kubesphere
RUN CGO_ENABLED=0 GO111MODULE=off GOOS=linux GOARCH=amd64 go build -i -ldflags '-w -s' -o ks-iam cmd/ks-iam/apiserver.go
FROM alpine:3.7
FROM alpine:3.9
RUN apk add --update ca-certificates && update-ca-certificates
COPY --from=ks-iam-builder /go/src/kubesphere.io/kubesphere/ks-iam /usr/local/bin/
CMD ["sh"]
/*
Copyright 2019 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
Copyright 2019 The KubeSphere Authors.
http://www.apache.org/licenses/LICENSE-2.0
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.
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 main
import (
"flag"
"os"
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/controller/namespace"
"os"
"sigs.k8s.io/controller-runtime/pkg/manager"
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
"sigs.k8s.io/controller-runtime/pkg/runtime/signals"
......@@ -40,7 +43,7 @@ func main() {
// Get a config to talk to the apiserver
log.Info("setting up client for manager")
cfg, err := config.GetConfig()
cfg, err := k8s.Config()
if err != nil {
log.Error(err, "unable to set up client config")
os.Exit(1)
......@@ -76,7 +79,19 @@ func main() {
os.Exit(1)
}
controller.Run(signals.SetupSignalHandler())
err = mgr.Add(manager.RunnableFunc(func(s <-chan struct{}) error {
informerFactory := informers.SharedInformerFactory()
informerFactory.Start(s)
namespace.NewNamespaceController(k8s.Client(),
informerFactory.Core().V1().Namespaces(),
informerFactory.Rbac().V1().Roles()).Start(s)
return nil
}))
if err != nil {
log.Error(err, "error Adding controllers to the Manager")
os.Exit(1)
}
// Start the Cmd
log.Info("Starting the Cmd.")
......
/*
Copyright 2019 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 main
import (
"github.com/mholt/caddy/caddy/caddymain"
"github.com/mholt/caddy/caddyhttp/httpserver"
// Install apis
_ "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/authenticate"
_ "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/authentication"
_ "kubesphere.io/kubesphere/pkg/apigateway/caddy-plugin/swagger"
)
func main() {
httpserver.RegisterDevDirective("authenticate", "jwt")
httpserver.RegisterDevDirective("authentication", "jwt")
httpserver.RegisterDevDirective("swagger", "jwt")
caddymain.Run()
}
......@@ -98,7 +98,7 @@ func waitForResourceSync() {
informerFactory.Apps().V1().DaemonSets().Lister()
informerFactory.Batch().V1().Jobs().Lister()
informerFactory.Batch().V1beta1().CronJobs()
informerFactory.Batch().V1beta1().CronJobs().Lister()
informerFactory.Start(stopChan)
informerFactory.WaitForCacheSync(stopChan)
......
#!/usr/bin/env bash
docker build -f build/ks-apigateway/Dockerfile -t kubespheredev/ks-apigateway:latest .
docker build -f build/ks-apiserver/Dockerfile -t kubespheredev/ks-apiserver:latest .
\ No newline at end of file
docker build -f build/ks-apiserver/Dockerfile -t kubespheredev/ks-apiserver:latest .
docker build -f build/ks-iam/Dockerfile -t kubespheredev/ks-iam:latest .
\ No newline at end of file
......@@ -5,3 +5,4 @@
echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
docker push kubespheredev/ks-apigateway:latest
docker push kubespheredev/ks-apiserver:latest
docker push kubespheredev/ks-iam:latest
......@@ -18,6 +18,7 @@
package authentication
import (
"context"
"errors"
"fmt"
"k8s.io/apiserver/pkg/authorization/authorizer"
......@@ -271,7 +272,7 @@ func pathMatches(path, spec string) bool {
return false
}
func getAuthorizerAttributes(ctx request.Context) (authorizer.Attributes, error) {
func getAuthorizerAttributes(ctx context.Context) (authorizer.Attributes, error) {
attribs := authorizer.AttributesRecord{}
user, ok := request.UserFrom(ctx)
......
......@@ -50,8 +50,13 @@ func Setup(c *caddy.Controller) error {
c.OnStartup(func() error {
stopChan := signals.SetupSignalHandler()
informers.SharedInformerFactory().Start(stopChan)
informers.SharedInformerFactory().WaitForCacheSync(stopChan)
informerFactory := informers.SharedInformerFactory()
informerFactory.Rbac().V1().Roles().Lister()
informerFactory.Rbac().V1().RoleBindings().Lister()
informerFactory.Rbac().V1().ClusterRoles().Lister()
informerFactory.Rbac().V1().ClusterRoleBindings().Lister()
informerFactory.Start(stopChan)
informerFactory.WaitForCacheSync(stopChan)
fmt.Println("Authentication middleware is initiated")
return nil
})
......
......@@ -101,6 +101,7 @@ func addWebService(c *restful.Container) error {
Writes(models.PodInfo{}))
webservice.Route(webservice.GET("/users/{username}/kubeconfig").
Produces("text/plain").
To(resources.GetKubeconfig).
Doc("get users' kubeconfig").
Param(webservice.PathParameter("username", "username")).
......
......@@ -22,6 +22,7 @@ import (
"github.com/dgrijalva/jwt-go"
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/simple/client/ldap"
"net/http"
"kubesphere.io/kubesphere/pkg/errors"
......@@ -113,7 +114,7 @@ func TokenReviewHandler(req *restful.Request, resp *restful.Response) {
username := claims["username"].(string)
conn, err := iam.NewConnection()
conn, err := ldap.Client()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
......
......@@ -19,6 +19,7 @@ package iam
import (
"fmt"
ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"net/http"
"regexp"
"strings"
......@@ -109,7 +110,7 @@ func GroupDetail(req *restful.Request, resp *restful.Response) {
path := req.PathParameter("path")
conn, err := iam.NewConnection()
conn, err := ldapclient.Client()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
......@@ -133,7 +134,7 @@ func GroupUsers(req *restful.Request, resp *restful.Response) {
path := req.PathParameter("path")
conn, err := iam.NewConnection()
conn, err := ldapclient.Client()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
......@@ -228,7 +229,7 @@ func RootGroupList(req *restful.Request, resp *restful.Response) {
groups := make([]*models.Group, 0)
conn, err := iam.NewConnection()
conn, err := ldapclient.Client()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
......
......@@ -31,6 +31,7 @@ import (
"kubesphere.io/kubesphere/pkg/errors"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam"
ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
)
const (
......@@ -166,7 +167,7 @@ func CurrentUserDetail(req *restful.Request, resp *restful.Response) {
username := req.HeaderParameter(constants.UserNameHeader)
conn, err := iam.NewConnection()
conn, err := ldapclient.Client()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
......@@ -228,7 +229,7 @@ func NamespacesListHandler(req *restful.Request, resp *restful.Response) {
func UserDetail(req *restful.Request, resp *restful.Response) {
username := req.PathParameter("name")
conn, err := iam.NewConnection()
conn, err := ldapclient.Client()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
......@@ -296,7 +297,7 @@ func UserList(req *restful.Request, resp *restful.Response) {
return
}
conn, err := iam.NewConnection()
conn, err := ldapclient.Client()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
......
......@@ -19,6 +19,7 @@ package iam
import (
"fmt"
"github.com/go-ldap/ldap"
"net/http"
"regexp"
"sort"
......@@ -26,7 +27,6 @@ import (
"strings"
"github.com/emicklei/go-restful"
"github.com/go-ldap/ldap"
"k8s.io/api/core/v1"
rbac "k8s.io/api/rbac/v1"
apierror "k8s.io/apimachinery/pkg/api/errors"
......@@ -37,6 +37,7 @@ import (
"kubesphere.io/kubesphere/pkg/models/iam"
"kubesphere.io/kubesphere/pkg/models/metrics"
"kubesphere.io/kubesphere/pkg/models/workspaces"
ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
sliceutils "kubesphere.io/kubesphere/pkg/utils"
)
......@@ -656,7 +657,7 @@ func WorkspaceMemberList(req *restful.Request, resp *restful.Response) {
offset = 0
}
conn, err := iam.NewConnection()
conn, err := ldapclient.Client()
if err != nil {
resp.WriteHeaderAndEntity(http.StatusInternalServerError, errors.Wrap(err))
......
......@@ -19,12 +19,12 @@ package monitoring
import (
"github.com/emicklei/go-restful"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/models/metrics"
"kubesphere.io/kubesphere/pkg/simple/client/prometheus"
)
func MonitorPod(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
podName := requestParams.PodName
metricName := requestParams.MetricsName
if podName != "" {
......@@ -49,7 +49,7 @@ func MonitorPod(request *restful.Request, response *restful.Response) {
}
func MonitorContainer(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
metricName := requestParams.MetricsName
if requestParams.MetricsFilter != "" {
rawMetrics := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelContainer)
......@@ -68,7 +68,7 @@ func MonitorContainer(request *restful.Request, response *restful.Response) {
}
func MonitorWorkload(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
rawMetrics := metrics.MonitorAllMetrics(requestParams, metrics.MetricLevelWorkload)
......@@ -95,7 +95,7 @@ func MonitorWorkload(request *restful.Request, response *restful.Response) {
func MonitorAllWorkspaces(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
tp := requestParams.Tp
if tp == "_statistics" {
......@@ -119,7 +119,7 @@ func MonitorAllWorkspaces(request *restful.Request, response *restful.Response)
}
func MonitorOneWorkspace(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
tp := requestParams.Tp
if tp == "rank" {
......@@ -145,7 +145,7 @@ func MonitorOneWorkspace(request *restful.Request, response *restful.Response) {
}
func MonitorNamespace(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
metricName := requestParams.MetricsName
nsName := requestParams.NsName
if nsName != "" {
......@@ -166,7 +166,7 @@ func MonitorNamespace(request *restful.Request, response *restful.Response) {
}
func MonitorCluster(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
metricName := requestParams.MetricsName
if metricName != "" {
......@@ -183,7 +183,7 @@ func MonitorCluster(request *restful.Request, response *restful.Response) {
}
func MonitorNode(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
metricName := requestParams.MetricsName
if metricName != "" {
......@@ -213,7 +213,7 @@ func MonitorNode(request *restful.Request, response *restful.Response) {
// k8s component(controller, scheduler, etcd) status
func MonitorComponentStatus(request *restful.Request, response *restful.Response) {
requestParams := client.ParseMonitoringRequestParams(request)
requestParams := prometheus.ParseMonitoringRequestParams(request)
status := metrics.MonitorComponentStatus(requestParams)
response.WriteAsJson(status)
......
......@@ -51,5 +51,5 @@ func GetKubeconfig(req *restful.Request, resp *restful.Response) {
return
}
resp.WriteAsJson(kubectlConfig)
resp.Write([]byte(kubectlConfig))
}
......@@ -52,5 +52,5 @@ var (
SystemWorkspace = "system-workspace"
DevopsAPIServer = "ks-devops-apiserver.kubesphere-system.svc"
AccountAPIServer = "ks-account.kubesphere-system.svc"
SystemNamespaces = []string{KubeSystemNamespace, OpenPitrixNamespace, KubeSystemNamespace}
SystemNamespaces = []string{KubeSphereNamespace, OpenPitrixNamespace, KubeSystemNamespace}
)
package controller
import (
"kubesphere.io/kubesphere/pkg/controller/namespace"
"log"
"sync"
"time"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/client"
)
const defaultResync = 600 * time.Second
var once sync.Once
func Run(stopCh <-chan struct{}) {
once.Do(func() {
kubeclientset := client.K8sClient()
informerFactory := informers.NewSharedInformerFactory(kubeclientset, defaultResync)
namespaceController := namespace.NewNamespaceController(kubeclientset, informerFactory.Core().V1().Namespaces(), informerFactory.Rbac().V1().Roles())
// data sync
informerFactory.Start(stopCh)
// start workers
namespaceController.Start(stopCh)
log.Println("all controller is running")
})
}
package controller
import (
"testing"
)
// controller test
func TestController(t *testing.T) {
}
......@@ -18,12 +18,11 @@
package informers
import (
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"sync"
"time"
"k8s.io/client-go/informers"
"kubesphere.io/kubesphere/pkg/client"
)
const defaultResync = 600 * time.Second
......@@ -35,7 +34,7 @@ var (
func SharedInformerFactory() informers.SharedInformerFactory {
once.Do(func() {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
informerFactory = informers.NewSharedInformerFactory(k8sClient, defaultResync)
})
return informerFactory
......
......@@ -20,8 +20,7 @@ package components
import (
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/informers"
......@@ -84,7 +83,7 @@ func GetSystemHealthStatus() (map[string]interface{}, error) {
status := make(map[string]interface{})
componentStatuses, err := client.K8sClient().CoreV1().ComponentStatuses().List(meta_v1.ListOptions{})
componentStatuses, err := k8s.Client().CoreV1().ComponentStatuses().List(meta_v1.ListOptions{})
if err != nil {
return nil, err
}
......
......@@ -23,6 +23,8 @@ import (
"fmt"
"io/ioutil"
"kubesphere.io/kubesphere/pkg/informers"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"log"
"net/http"
"regexp"
......@@ -35,7 +37,6 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/kubernetes/pkg/util/slice"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/models/iam/policy"
......@@ -264,7 +265,7 @@ func ClusterRoleUsers(clusterRoleName string) ([]*models.User, error) {
return nil, err
}
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return nil, err
......@@ -306,7 +307,7 @@ func RoleUsers(namespace string, roleName string) ([]*models.User, error) {
return nil, err
}
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return nil, err
......@@ -343,7 +344,7 @@ func NamespaceUsers(namespaceName string) ([]*models.User, error) {
if err != nil {
return nil, err
}
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return nil, err
......@@ -608,7 +609,7 @@ func CreateClusterRoleBinding(username string, clusterRoleName string) error {
}
}
_, err = client.K8sClient().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
_, err = k8s.Client().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
if err != nil {
return err
......@@ -636,7 +637,7 @@ func CreateClusterRoleBinding(username string, clusterRoleName string) error {
if clusterRoleBinding != nil {
clusterRoleBinding.Subjects = append(clusterRoleBinding.Subjects, v1.Subject{Kind: v1.UserKind, Name: username})
_, err := client.K8sClient().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
_, err := k8s.Client().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
if err != nil {
return err
}
......@@ -647,7 +648,7 @@ func CreateClusterRoleBinding(username string, clusterRoleName string) error {
clusterRoleBinding.RoleRef = v1.RoleRef{Name: clusterRoleName, Kind: ClusterRoleKind}
clusterRoleBinding.Subjects = []v1.Subject{{Kind: v1.UserKind, Name: username}}
_, err = client.K8sClient().RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
_, err = k8s.Client().RbacV1().ClusterRoleBindings().Create(clusterRoleBinding)
if err != nil {
return err
......
......@@ -22,7 +22,8 @@ import (
"fmt"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/informers"
"log"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/redis"
"os"
"regexp"
"strconv"
......@@ -35,8 +36,8 @@ import (
"k8s.io/api/rbac/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/models"
jwtutils "kubesphere.io/kubesphere/pkg/utils/jwt"
)
......@@ -62,20 +63,7 @@ func init() {
}
func DatabaseInit() error {
var conn ldap.Client
var err error
maxRetry := 5
for retry := 0; retry < maxRetry; retry++ {
conn, err = NewConnection()
if err == nil {
break
} else if retry == maxRetry-1 {
log.Printf("cannot connect to ldap server ,%s", err)
} else {
log.Printf("cannot connect to ldap server ,retry %d/%d\n after 2s", retry+1, maxRetry)
}
time.Sleep(10 * time.Second)
}
conn, err := ldapclient.Client()
if err != nil {
return err
......@@ -83,141 +71,106 @@ func DatabaseInit() error {
defer conn.Close()
err = checkAndCreateDefaultUser(conn)
if err != nil {
return err
}
// search for the given username
userSearchRequest := ldap.NewSearchRequest(
client.UserSearchBase,
err = checkAndCreateDefaultGroup(conn)
return err
}
func checkAndCreateDefaultGroup(conn ldap.Client) error {
groupSearchRequest := ldap.NewSearchRequest(
ldapclient.GroupSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=inetOrgPerson))",
"(&(objectClass=posixGroup))",
nil,
nil,
)
users, err := conn.Search(userSearchRequest)
groups, err := conn.Search(groupSearchRequest)
if err != nil {
switch err.(type) {
case *ldap.Error:
if err.(*ldap.Error).ResultCode == 32 {
err := createUserBaseDN()
if err != nil {
return fmt.Errorf("UserBaseDN %s create failed: %s\n", client.UserSearchBase, err)
} else {
log.Printf("UserBaseDN %s create success\n", client.UserSearchBase)
}
} else {
return fmt.Errorf("UserBaseDN %s not exist: %s\n", client.UserSearchBase, err)
}
default:
return fmt.Errorf("UserBaseDN %s not exist: %s\n", client.UserSearchBase, err)
}
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
err = createGroupsBaseDN(conn)
}
counter = NewCounter(len(users.Entries))
if err != nil {
return fmt.Errorf("GroupBaseDN %s not exist: %s\n", ldapclient.GroupSearchBase, err)
}
if users == nil || len(users.Entries) == 0 {
err := CreateUser(models.User{Username: constants.AdminUserName, Email: AdminEmail, Password: AdminPWD, Description: "Administrator account that was always created by default."})
if len(groups.Entries) == 0 {
_, err = CreateGroup(models.Group{Path: constants.SystemWorkspace, Name: constants.SystemWorkspace, Creator: constants.AdminUserName, Description: "system workspace"})
if err != nil {
return fmt.Errorf("admin create failed: %s\n", err)
return fmt.Errorf("system-workspace create failed: %s\n", err)
}
log.Println("admin init success")
}
// search user group
groupSearchRequest := ldap.NewSearchRequest(
client.GroupSearchBase,
return nil
}
func checkAndCreateDefaultUser(conn ldap.Client) error {
userSearchRequest := ldap.NewSearchRequest(
ldapclient.UserSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=posixGroup))",
"(&(objectClass=inetOrgPerson))",
nil,
nil,
)
groups, err := conn.Search(groupSearchRequest)
users, err := conn.Search(userSearchRequest)
if err != nil {
switch err.(type) {
case *ldap.Error:
if err.(*ldap.Error).ResultCode == 32 {
err := createGroupsBaseDN()
if err != nil {
return fmt.Errorf("GroupBaseDN %s create failed: %s\n", client.GroupSearchBase, err)
} else {
log.Printf("GroupBaseDN %s create success\n", client.GroupSearchBase)
}
} else {
return fmt.Errorf("GroupBaseDN %s not exist: %s\n", client.GroupSearchBase, err)
}
default:
return fmt.Errorf("GroupBaseDN %s not exist: %s\n", client.GroupSearchBase, err)
}
if ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
err = createUserBaseDN(conn)
}
if groups == nil || len(groups.Entries) == 0 {
systemGroup := models.Group{Path: constants.SystemWorkspace, Name: constants.SystemWorkspace, Creator: constants.AdminUserName, Description: "system workspace"}
if err != nil {
return fmt.Errorf("UserBaseDN %s not exist: %s\n", ldapclient.UserSearchBase, err)
}
_, err = CreateGroup(systemGroup)
if len(users.Entries) == 0 {
err := CreateUser(models.User{Username: constants.AdminUserName, Email: AdminEmail, Password: AdminPWD, Description: "Administrator account that was always created by default."})
if err != nil {
return fmt.Errorf("system-group create failed: %s\n", err)
return fmt.Errorf("admin create failed: %s\n", err)
}
log.Println("system-workspace init success")
}
counter = NewCounter(len(users.Entries))
return nil
}
func createUserBaseDN() error {
func createUserBaseDN(conn ldap.Client) error {
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return err
}
defer conn.Close()
groupsCreateRequest := ldap.NewAddRequest(client.UserSearchBase, nil)
groupsCreateRequest := ldap.NewAddRequest(ldapclient.UserSearchBase, nil)
groupsCreateRequest.Attribute("objectClass", []string{"organizationalUnit", "top"})
groupsCreateRequest.Attribute("ou", []string{"Users"})
return conn.Add(groupsCreateRequest)
}
func createGroupsBaseDN() error {
conn, err := NewConnection()
if err != nil {
return err
}
defer conn.Close()
groupsCreateRequest := ldap.NewAddRequest(client.GroupSearchBase, nil)
func createGroupsBaseDN(conn ldap.Client) error {
groupsCreateRequest := ldap.NewAddRequest(ldapclient.GroupSearchBase, nil)
groupsCreateRequest.Attribute("objectClass", []string{"organizationalUnit", "top"})
groupsCreateRequest.Attribute("ou", []string{"Groups"})
return conn.Add(groupsCreateRequest)
}
func NewConnection() (ldap.Client, error) {
conn, err := client.LdapClient().Get()
if err != nil {
return nil, err
}
err = conn.Bind(client.ManagerDN, client.ManagerPassword)
if err != nil {
return nil, err
}
return conn, nil
}
// User login
func Login(username string, password string, ip string) (string, error) {
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return "", err
......@@ -226,7 +179,7 @@ func Login(username string, password string, ip string) (string, error) {
defer conn.Close()
userSearchRequest := ldap.NewSearchRequest(
client.UserSearchBase,
ldapclient.UserSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", username, username),
[]string{"uid", "mail"},
......@@ -257,7 +210,7 @@ func Login(username string, password string, ip string) (string, error) {
}
if ip != "" {
redisClient := client.RedisClient()
redisClient := redis.Client()
redisClient.RPush(fmt.Sprintf("kubesphere:users:%s:login-log", uid), fmt.Sprintf("%s,%s", time.Now().UTC().Format("2006-01-02T15:04:05Z"), ip))
redisClient.LTrim(fmt.Sprintf("kubesphere:users:%s:login-log", uid), -10, -1)
}
......@@ -277,7 +230,7 @@ func Login(username string, password string, ip string) (string, error) {
func UserList(limit int, offset int) (int, []models.User, error) {
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return 0, nil, err
......@@ -296,7 +249,7 @@ l1:
for {
userSearchRequest := ldap.NewSearchRequest(
client.UserSearchBase,
ldapclient.UserSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=inetOrgPerson))",
[]string{"uid", "mail", "description"},
......@@ -329,7 +282,7 @@ l1:
break
}
redisClient := client.RedisClient()
redisClient := redis.Client()
for _, v := range entries {
......@@ -369,7 +322,7 @@ l1:
}
func LoginLog(username string) ([]string, error) {
redisClient := client.RedisClient()
redisClient := redis.Client()
data, err := redisClient.LRange(fmt.Sprintf("kubesphere:users:%s:login-log", username), -10, -1).Result()
......@@ -382,7 +335,7 @@ func LoginLog(username string) ([]string, error) {
func Search(keyword string, limit int, offset int) (int, []models.User, error) {
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return 0, nil, err
......@@ -400,7 +353,7 @@ func Search(keyword string, limit int, offset int) (int, []models.User, error) {
l1:
for {
userSearchRequest := ldap.NewSearchRequest(
client.UserSearchBase,
ldapclient.UserSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=*%s*)(mail=*%s*)(description=*%s*)))", keyword, keyword, keyword),
[]string{"uid", "mail", "description"},
......@@ -433,7 +386,7 @@ l1:
break
}
redisClient := client.RedisClient()
redisClient := redis.Client()
for _, v := range entries {
......@@ -475,7 +428,7 @@ l1:
func UserDetail(username string, conn ldap.Client) (*models.User, error) {
userSearchRequest := ldap.NewSearchRequest(
client.UserSearchBase,
ldapclient.UserSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(&(objectClass=inetOrgPerson)(uid=%s))", username),
[]string{"mail", "description", "preferredLanguage"},
......@@ -498,7 +451,7 @@ func UserDetail(username string, conn ldap.Client) (*models.User, error) {
user := models.User{Username: username, Email: email, Description: description, Lang: lang}
groupSearchRequest := ldap.NewSearchRequest(
client.GroupSearchBase,
ldapclient.GroupSearchBase,
ldap.ScopeBaseObject, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(&(objectClass=posixGroup)(memberUid=%s))", username),
nil,
......@@ -521,7 +474,7 @@ func UserDetail(username string, conn ldap.Client) (*models.User, error) {
user.Groups = groups
redisClient := client.RedisClient()
redisClient := redis.Client()
avatar, err := redisClient.HMGet("kubesphere:users:avatar", username).Result()
......@@ -553,14 +506,14 @@ func UserDetail(username string, conn ldap.Client) (*models.User, error) {
func DeleteUser(username string) error {
// bind root DN
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return err
}
defer conn.Close()
deleteRequest := ldap.NewDelRequest(fmt.Sprintf("uid=%s,%s", username, client.UserSearchBase), nil)
deleteRequest := ldap.NewDelRequest(fmt.Sprintf("uid=%s,%s", username, ldapclient.UserSearchBase), nil)
err = conn.Del(deleteRequest)
......@@ -602,13 +555,13 @@ func deleteRoleBindings(username string) error {
if length2 == 0 {
deletePolicy := meta_v1.DeletePropagationForeground
err = client.K8sClient().RbacV1().RoleBindings(roleBinding.Namespace).Delete(roleBinding.Name, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
err = k8s.Client().RbacV1().RoleBindings(roleBinding.Namespace).Delete(roleBinding.Name, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
if err != nil {
glog.Errorf("delete role binding %s %s %s failed: %v", username, roleBinding.Namespace, roleBinding.Name, err)
}
} else if length2 < length1 {
_, err = client.K8sClient().RbacV1().RoleBindings(roleBinding.Namespace).Update(roleBinding)
_, err = k8s.Client().RbacV1().RoleBindings(roleBinding.Namespace).Update(roleBinding)
if err != nil {
glog.Errorf("update role binding %s %s %s failed: %v", username, roleBinding.Namespace, roleBinding.Name, err)
......@@ -632,16 +585,16 @@ func deleteRoleBindings(username string) error {
length2 := len(clusterRoleBinding.Subjects)
if length2 == 0 {
if groups := regexp.MustCompile(fmt.Sprintf(`^system:(\S+):(%s)$`, strings.Join(constants.WorkSpaceRoles, "|"))).FindStringSubmatch(clusterRoleBinding.RoleRef.Name); len(groups) == 3 {
_, err = client.K8sClient().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
_, err = k8s.Client().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
} else {
deletePolicy := meta_v1.DeletePropagationForeground
err = client.K8sClient().RbacV1().ClusterRoleBindings().Delete(clusterRoleBinding.Name, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
err = k8s.Client().RbacV1().ClusterRoleBindings().Delete(clusterRoleBinding.Name, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
}
if err != nil {
glog.Errorf("update cluster role binding %s failed:%s", clusterRoleBinding.Name, err)
}
} else if length2 < length1 {
_, err = client.K8sClient().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
_, err = k8s.Client().RbacV1().ClusterRoleBindings().Update(clusterRoleBinding)
if err != nil {
glog.Errorf("update cluster role binding %s failed:%s", clusterRoleBinding.Name, err)
......@@ -656,7 +609,7 @@ func deleteRoleBindings(username string) error {
func UserCreateCheck(check string) (exist bool, err error) {
// bind root DN
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return false, err
......@@ -666,7 +619,7 @@ func UserCreateCheck(check string) (exist bool, err error) {
// search for the given username
userSearchRequest := ldap.NewSearchRequest(
client.UserSearchBase,
ldapclient.UserSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", check, check),
[]string{"uid", "mail"},
......@@ -692,7 +645,7 @@ func CreateUser(user models.User) error {
user.Password = strings.TrimSpace(user.Password)
user.Description = strings.TrimSpace(user.Description)
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return err
......@@ -701,7 +654,7 @@ func CreateUser(user models.User) error {
defer conn.Close()
userSearchRequest := ldap.NewSearchRequest(
client.UserSearchBase,
ldapclient.UserSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
fmt.Sprintf("(&(objectClass=inetOrgPerson)(|(uid=%s)(mail=%s)))", user.Username, user.Email),
[]string{"uid", "mail"},
......@@ -726,7 +679,7 @@ func CreateUser(user models.User) error {
maxUid += 1
userCreateRequest := ldap.NewAddRequest(fmt.Sprintf("uid=%s,%s", user.Username, client.UserSearchBase), nil)
userCreateRequest := ldap.NewAddRequest(fmt.Sprintf("uid=%s,%s", user.Username, ldapclient.UserSearchBase), nil)
userCreateRequest.Attribute("objectClass", []string{"inetOrgPerson", "posixAccount", "top"})
userCreateRequest.Attribute("cn", []string{user.Username}) // RFC4519: common name(s) for which the entity is known by
userCreateRequest.Attribute("sn", []string{" "}) // RFC2256: last (family) name(s) for which the entity is known by
......@@ -759,7 +712,7 @@ func CreateUser(user models.User) error {
}
func getMaxUid(conn ldap.Client) (int, error) {
userSearchRequest := ldap.NewSearchRequest(client.UserSearchBase,
userSearchRequest := ldap.NewSearchRequest(ldapclient.UserSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=inetOrgPerson))",
[]string{"uidNumber"},
......@@ -789,7 +742,7 @@ func getMaxUid(conn ldap.Client) (int, error) {
func getMaxGid(conn ldap.Client) (int, error) {
groupSearchRequest := ldap.NewSearchRequest(client.GroupSearchBase,
groupSearchRequest := ldap.NewSearchRequest(ldapclient.GroupSearchBase,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=posixGroup))",
[]string{"gidNumber"},
......@@ -819,14 +772,14 @@ func getMaxGid(conn ldap.Client) (int, error) {
func UpdateUser(user models.User) error {
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return err
}
defer conn.Close()
dn := fmt.Sprintf("uid=%s,%s", user.Username, client.UserSearchBase)
dn := fmt.Sprintf("uid=%s,%s", user.Username, ldapclient.UserSearchBase)
userModifyRequest := ldap.NewModifyRequest(dn, nil)
if user.Email != "" {
userModifyRequest.Replace("mail", []string{user.Email})
......@@ -860,7 +813,7 @@ func UpdateUser(user models.User) error {
func DeleteGroup(path string) error {
// bind root DN
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return err
}
......@@ -881,7 +834,7 @@ func DeleteGroup(path string) error {
func CreateGroup(group models.Group) (*models.Group, error) {
// bind root DN
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return nil, err
}
......@@ -922,7 +875,7 @@ func CreateGroup(group models.Group) (*models.Group, error) {
group.CreateTime = time.Now().UTC().Format("2006-01-02T15:04:05Z")
redisClient := client.RedisClient()
redisClient := redis.Client()
if err := redisClient.HMSet("kubesphere:groups:create-time", map[string]interface{}{group.Name: group.CreateTime}).Err(); err != nil {
return nil, err
......@@ -937,7 +890,7 @@ func CreateGroup(group models.Group) (*models.Group, error) {
func UpdateGroup(group *models.Group) (*models.Group, error) {
// bind root DN
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return nil, err
}
......@@ -980,7 +933,7 @@ func UpdateGroup(group *models.Group) (*models.Group, error) {
func CountChild(path string) (int, error) {
// bind root DN
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return 0, err
}
......@@ -988,7 +941,7 @@ func CountChild(path string) (int, error) {
var groupSearchRequest *ldap.SearchRequest
if path == "" {
groupSearchRequest = ldap.NewSearchRequest(client.GroupSearchBase,
groupSearchRequest = ldap.NewSearchRequest(ldapclient.GroupSearchBase,
ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=posixGroup))",
[]string{"cn", "gidNumber", "memberUid", "description"},
......@@ -1014,7 +967,7 @@ func CountChild(path string) (int, error) {
func ChildList(path string) ([]models.Group, error) {
// bind root DN
conn, err := NewConnection()
conn, err := ldapclient.Client()
if err != nil {
return nil, err
......@@ -1024,7 +977,7 @@ func ChildList(path string) ([]models.Group, error) {
var groupSearchRequest *ldap.SearchRequest
if path == "" {
groupSearchRequest = ldap.NewSearchRequest(client.GroupSearchBase,
groupSearchRequest = ldap.NewSearchRequest(ldapclient.GroupSearchBase,
ldap.ScopeSingleLevel, ldap.NeverDerefAliases, 0, 0, false,
"(&(objectClass=posixGroup))",
[]string{"cn", "gidNumber", "memberUid", "description"},
......@@ -1076,7 +1029,7 @@ func ChildList(path string) ([]models.Group, error) {
group.ChildGroups = childGroups
redisClient := client.RedisClient()
redisClient := redis.Client()
createTime, _ := redisClient.HMGet("kubesphere:groups:create-time", group.Name).Result()
......@@ -1132,7 +1085,7 @@ func GroupDetail(path string, conn ldap.Client) (*models.Group, error) {
group.ChildGroups = childGroups
redisClient := client.RedisClient()
redisClient := redis.Client()
createTime, _ := redisClient.HMGet("kubesphere:groups:create-time", group.Name).Result()
......
......@@ -19,7 +19,7 @@ package iam
import (
"fmt"
"kubesphere.io/kubesphere/pkg/client"
ldapclient "kubesphere.io/kubesphere/pkg/simple/client/ldap"
"regexp"
"strings"
)
......@@ -60,12 +60,12 @@ func splitPath(path string) (searchBase string, cn string) {
basePath[i], basePath[j] = basePath[j], basePath[i]
}
searchBase = fmt.Sprintf("%s,%s", strings.Join(basePath, ","), client.GroupSearchBase)
searchBase = fmt.Sprintf("%s,%s", strings.Join(basePath, ","), ldapclient.GroupSearchBase)
} else if length == 2 {
searchBase = fmt.Sprintf("cn=%s,%s", paths[0], client.GroupSearchBase)
searchBase = fmt.Sprintf("cn=%s,%s", paths[0], ldapclient.GroupSearchBase)
cn = paths[1]
} else {
searchBase = client.GroupSearchBase
searchBase = ldapclient.GroupSearchBase
if paths[0] == "" {
cn = "*"
} else {
......
......@@ -27,6 +27,7 @@ import (
"encoding/base64"
"encoding/pem"
"io/ioutil"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"math/big"
rd "math/rand"
"time"
......@@ -39,7 +40,6 @@ import (
"k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/constants"
)
......@@ -216,7 +216,7 @@ func createKubeConfig(userName string) (string, error) {
return "", err
}
base64ServerCa := base64.StdEncoding.EncodeToString(serverCa)
tmpClusterInfo := clusterInfo{CertificateAuthorityData: base64ServerCa, Server: client.KubeConfig.Host}
tmpClusterInfo := clusterInfo{CertificateAuthorityData: base64ServerCa, Server: k8s.KubeConfig.Host}
tmpCluster := cluster{Cluster: tmpClusterInfo, Name: clusterName}
tmpKubeConfig.Clusters = append(tmpKubeConfig.Clusters, tmpCluster)
......@@ -243,7 +243,7 @@ func createKubeConfig(userName string) (string, error) {
}
func CreateKubeConfig(user string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
_, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(user, metaV1.GetOptions{})
......@@ -268,7 +268,7 @@ func CreateKubeConfig(user string) error {
}
func GetKubeConfig(user string) (string, error) {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
configMap, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(user, metaV1.GetOptions{})
if err != nil {
glog.Errorf("cannot get user %s's kubeConfig, reason: %v", user, err)
......@@ -278,7 +278,7 @@ func GetKubeConfig(user string) (string, error) {
}
func DelKubeConfig(user string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
_, err := k8sClient.CoreV1().ConfigMaps(constants.KubeSphereControlNamespace).Get(user, metaV1.GetOptions{})
if errors.IsNotFound(err) {
return nil
......
......@@ -21,6 +21,7 @@ package kubectl
import (
"fmt"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"math/rand"
"github.com/golang/glog"
......@@ -31,7 +32,6 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/constants"
)
......@@ -40,7 +40,7 @@ const (
)
func GetKubectlPod(username string) (models.PodInfo, error) {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
deploy, err := k8sClient.AppsV1beta2().Deployments(namespace).Get(username, metav1.GetOptions{})
if err != nil {
glog.Errorln(err)
......@@ -87,7 +87,7 @@ func selectCorrectPod(namespace string, pods []v1.Pod) (kubectlPod v1.Pod, err e
}
func CreateKubectlDeploy(user string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
_, err := k8sClient.AppsV1().Deployments(namespace).Get(user, metav1.GetOptions{})
if err == nil {
return nil
......@@ -128,7 +128,7 @@ func CreateKubectlDeploy(user string) error {
}
func DelKubectlDeploy(user string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
_, err := k8sClient.AppsV1beta2().Deployments(namespace).Get(user, metav1.GetOptions{})
if errors.IsNotFound(err) {
return nil
......
......@@ -21,6 +21,8 @@ package metrics
import (
"fmt"
"kubesphere.io/kubesphere/pkg/models"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/prometheus"
"net/url"
"regexp"
"strings"
......@@ -42,8 +44,6 @@ import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/client"
)
var (
......@@ -145,7 +145,7 @@ func getAllWorkspaces() map[string]int {
paramValues := make(url.Values)
paramValues.Set("query", WorkspaceNamespaceLabelRule)
params := paramValues.Encode()
res := client.SendMonitoringRequest(client.DefaultQueryType, params)
res := prometheus.SendMonitoringRequest(prometheus.DefaultQueryType, params)
metric := ReformatJson(res, "")
......@@ -240,7 +240,7 @@ func unifyMetricHistoryTimeRange(fmtMetrics *FormatedMetric) {
}
}
func AssembleSpecificWorkloadMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string, bool) {
func AssembleSpecificWorkloadMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, metricName string) (string, string, bool) {
nsName := monitoringRequest.NsName
wkName := monitoringRequest.WorkloadName
......@@ -250,7 +250,7 @@ func AssembleSpecificWorkloadMetricRequestInfo(monitoringRequest *client.Monitor
paramValues := monitoringRequest.Params
params := makeRequestParamString(rule, paramValues)
res := client.SendMonitoringRequest(client.DefaultQueryType, params)
res := prometheus.SendMonitoringRequest(prometheus.DefaultQueryType, params)
podNamesFilter := getPodNameRegexInWorkload(res, podsFilter)
......@@ -261,7 +261,7 @@ func AssembleSpecificWorkloadMetricRequestInfo(monitoringRequest *client.Monitor
return queryType, params, rule == ""
}
func AssembleAllWorkloadMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
func AssembleAllWorkloadMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, metricName string) (string, string) {
queryType := monitoringRequest.QueryType
paramValues := monitoringRequest.Params
......@@ -271,7 +271,7 @@ func AssembleAllWorkloadMetricRequestInfo(monitoringRequest *client.MonitoringRe
return queryType, params
}
func AssemblePodMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string, bool) {
func AssemblePodMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, metricName string) (string, string, bool) {
queryType := monitoringRequest.QueryType
paramValues := monitoringRequest.Params
......@@ -282,7 +282,7 @@ func AssemblePodMetricRequestInfo(monitoringRequest *client.MonitoringRequestPar
}
func GetMetric(queryType, params, metricName string) *FormatedMetric {
res := client.SendMonitoringRequest(queryType, params)
res := prometheus.SendMonitoringRequest(queryType, params)
formatedMetric := ReformatJson(res, metricName)
return formatedMetric
}
......@@ -319,13 +319,13 @@ func AddNodeAddressMetric(nodeMetric *FormatedMetric, nodeAddress *map[string][]
}
}
func MonitorContainer(monitoringRequest *client.MonitoringRequestParams, metricName string) *FormatedMetric {
func MonitorContainer(monitoringRequest *prometheus.MonitoringRequestParams, metricName string) *FormatedMetric {
queryType, params := AssembleContainerMetricRequestInfo(monitoringRequest, metricName)
res := GetMetric(queryType, params, metricName)
return res
}
func AssembleContainerMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
func AssembleContainerMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, metricName string) (string, string) {
queryType := monitoringRequest.QueryType
paramValues := monitoringRequest.Params
......@@ -335,7 +335,7 @@ func AssembleContainerMetricRequestInfo(monitoringRequest *client.MonitoringRequ
return queryType, params
}
func AssembleNamespaceMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
func AssembleNamespaceMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, metricName string) (string, string) {
queryType := monitoringRequest.QueryType
paramValues := monitoringRequest.Params
......@@ -345,7 +345,7 @@ func AssembleNamespaceMetricRequestInfo(monitoringRequest *client.MonitoringRequ
return queryType, params
}
func AssembleSpecificWorkspaceMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, namespaceList []string, metricName string) (string, string) {
func AssembleSpecificWorkspaceMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, namespaceList []string, metricName string) (string, string) {
nsFilter := "^(" + strings.Join(namespaceList, "|") + ")$"
......@@ -357,7 +357,7 @@ func AssembleSpecificWorkspaceMetricRequestInfo(monitoringRequest *client.Monito
return queryType, params
}
func AssembleAllWorkspaceMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, namespaceList []string, metricName string) (string, string) {
func AssembleAllWorkspaceMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, namespaceList []string, metricName string) (string, string) {
var nsFilter = "^()$"
if namespaceList != nil {
......@@ -407,7 +407,7 @@ func filterNamespace(nsFilter string, namespaceList []string) []string {
return newNSlist
}
func MonitorAllWorkspaces(monitoringRequest *client.MonitoringRequestParams) *FormatedLevelMetric {
func MonitorAllWorkspaces(monitoringRequest *prometheus.MonitoringRequestParams) *FormatedLevelMetric {
metricsFilter := monitoringRequest.MetricsFilter
if strings.Trim(metricsFilter, " ") == "" {
metricsFilter = ".*"
......@@ -470,7 +470,7 @@ func MonitorAllWorkspaces(monitoringRequest *client.MonitoringRequestParams) *Fo
}
}
func collectWorkspaceMetric(monitoringRequest *client.MonitoringRequestParams, ws string, filterMetricsName []string, wgAll *sync.WaitGroup, wsAllch chan *[]FormatedMetric) {
func collectWorkspaceMetric(monitoringRequest *prometheus.MonitoringRequestParams, ws string, filterMetricsName []string, wgAll *sync.WaitGroup, wsAllch chan *[]FormatedMetric) {
defer wgAll.Done()
var wg sync.WaitGroup
var ch = make(chan *FormatedMetric, ChannelMaxCapacity)
......@@ -511,7 +511,7 @@ func collectWorkspaceMetric(monitoringRequest *client.MonitoringRequestParams, w
wsAllch <- &metricsArray
}
func MonitorAllMetrics(monitoringRequest *client.MonitoringRequestParams, resourceType string) *FormatedLevelMetric {
func MonitorAllMetrics(monitoringRequest *prometheus.MonitoringRequestParams, resourceType string) *FormatedLevelMetric {
metricsFilter := monitoringRequest.MetricsFilter
if metricsFilter == "" {
metricsFilter = ".*"
......@@ -869,8 +869,8 @@ func getSpecificMetricItem(timestamp int64, metricName string, resource string,
}
// k8s component(controller, scheduler, etcd) status
func MonitorComponentStatus(monitoringRequest *client.MonitoringRequestParams) *[]interface{} {
componentList, err := client.K8sClient().CoreV1().ComponentStatuses().List(metaV1.ListOptions{})
func MonitorComponentStatus(monitoringRequest *prometheus.MonitoringRequestParams) *[]interface{} {
componentList, err := k8s.Client().CoreV1().ComponentStatuses().List(metaV1.ListOptions{})
if err != nil {
glog.Errorln(err.Error())
}
......@@ -900,7 +900,7 @@ func MonitorComponentStatus(monitoringRequest *client.MonitoringRequestParams) *
paramValues := monitoringRequest.Params
paramValues.Set("query", NodeStatusRule)
params := paramValues.Encode()
res := client.SendMonitoringRequest(queryType, params)
res := prometheus.SendMonitoringRequest(queryType, params)
nodeStatusMetric := ReformatJson(res, "node_status", nodeStatusDelLabel...)
nodeStatusMetric = ReformatNodeStatusField(nodeStatusMetric)
......@@ -986,7 +986,7 @@ func makeMetricItems(timestamp int64, statusMap map[string]int, resourceType str
return &metricItems
}
func AssembleClusterMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
func AssembleClusterMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, metricName string) (string, string) {
queryType := monitoringRequest.QueryType
paramValues := monitoringRequest.Params
rule := MakeClusterRule(metricName)
......@@ -995,7 +995,7 @@ func AssembleClusterMetricRequestInfo(monitoringRequest *client.MonitoringReques
return queryType, params
}
func AssembleNodeMetricRequestInfo(monitoringRequest *client.MonitoringRequestParams, metricName string) (string, string) {
func AssembleNodeMetricRequestInfo(monitoringRequest *prometheus.MonitoringRequestParams, metricName string) (string, string) {
queryType := monitoringRequest.QueryType
paramValues := monitoringRequest.Params
rule := MakeNodeRule(monitoringRequest.NodeId, monitoringRequest.NodesFilter, metricName)
......
/*
Copyright 2019 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 metrics
import (
......@@ -6,7 +23,7 @@ import (
"k8s.io/api/core/v1"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/simple/client/prometheus"
)
func GetNamespacesWithMetrics(namespaces []*v1.Namespace) []*v1.Namespace {
......@@ -17,10 +34,10 @@ func GetNamespacesWithMetrics(namespaces []*v1.Namespace) []*v1.Namespace {
nsFilter := "^(" + strings.Join(nsNameList, "|") + ")$"
var timeRelateParams = make(url.Values)
params := client.MonitoringRequestParams{
params := prometheus.MonitoringRequestParams{
NsFilter: nsFilter,
Params: timeRelateParams,
QueryType: client.DefaultQueryType,
QueryType: prometheus.DefaultQueryType,
MetricsFilter: "namespace_cpu_usage|namespace_memory_usage_wo_cache|namespace_pod_count",
}
......
......@@ -19,6 +19,7 @@ package nodes
import (
"fmt"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"math"
"strings"
"time"
......@@ -31,13 +32,11 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"kubesphere.io/kubesphere/pkg/client"
)
func DrainNode(nodename string) (err error) {
k8sclient := client.K8sClient()
k8sclient := k8s.Client()
node, err := k8sclient.CoreV1().Nodes().Get(nodename, metav1.GetOptions{})
if err != nil {
return err
......@@ -69,7 +68,7 @@ func DrainNode(nodename string) (err error) {
func drainEviction(nodename string, donech chan bool, errch chan error) {
k8sclient := client.K8sClient()
k8sclient := k8s.Client()
var options metav1.ListOptions
pods := make([]v1.Pod, 0)
options.FieldSelector = "spec.nodeName=" + nodename
......@@ -108,7 +107,7 @@ func drainEviction(nodename string, donech chan bool, errch chan error) {
//create eviction
getPodFn := func(namespace, name string) (*v1.Pod, error) {
k8sclient := client.K8sClient()
k8sclient := k8s.Client()
return k8sclient.CoreV1().Pods(namespace).Get(name, metav1.GetOptions{})
}
evicerr := evictPods(pods, 0, getPodFn)
......@@ -160,7 +159,7 @@ func containDaemonset(pod v1.Pod, daemonsetList v1beta2.DaemonSetList) bool {
func evictPod(pod v1.Pod, GracePeriodSeconds int) error {
k8sclient := client.K8sClient()
k8sclient := k8s.Client()
deleteOptions := &metav1.DeleteOptions{}
if GracePeriodSeconds >= 0 {
gracePeriodSeconds := int64(GracePeriodSeconds)
......
......@@ -78,7 +78,7 @@ func (*clusterRoleSearcher) fuzzy(fuzzy map[string]string, item *rbac.ClusterRol
func (*clusterRoleSearcher) compare(a, b *rbac.ClusterRole, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -82,7 +82,7 @@ func (*configMapSearcher) fuzzy(fuzzy map[string]string, item *v1.ConfigMap) boo
func (*configMapSearcher) compare(a, b *v1.ConfigMap, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -90,11 +90,19 @@ func (*cronJobSearcher) fuzzy(fuzzy map[string]string, item *v1beta1.CronJob) bo
func (*cronJobSearcher) compare(a, b *v1beta1.CronJob, orderBy string) bool {
switch orderBy {
case lastScheduleTime:
if a.Status.LastScheduleTime == nil {
return true
}
if b.Status.LastScheduleTime == nil {
return false
}
return a.Status.LastScheduleTime.Before(b.Status.LastScheduleTime)
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
case name:
fallthrough
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
default:
fallthrough
case name:
return strings.Compare(a.Name, b.Name) <= 0
}
}
......
......@@ -93,7 +93,7 @@ func (*daemonSetSearcher) fuzzy(fuzzy map[string]string, item *v1.DaemonSet) boo
func (*daemonSetSearcher) compare(a, b *v1.DaemonSet, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -97,7 +97,7 @@ func (*deploymentSearcher) fuzzy(fuzzy map[string]string, item *v1.Deployment) b
func (*deploymentSearcher) compare(a, b *v1.Deployment, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -83,7 +83,7 @@ func (*ingressSearcher) fuzzy(fuzzy map[string]string, item *extensions.Ingress)
func (*ingressSearcher) compare(a, b *extensions.Ingress, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -112,7 +112,7 @@ func jobUpdateTime(item *batchv1.Job) time.Time {
func (*jobSearcher) compare(a, b *batchv1.Job, orderBy string) bool {
switch orderBy {
case updateTime:
return jobUpdateTime(a).After(jobUpdateTime(b))
return jobUpdateTime(a).Before(jobUpdateTime(b))
case name:
fallthrough
default:
......
......@@ -82,7 +82,7 @@ func (*namespaceSearcher) fuzzy(fuzzy map[string]string, item *v1.Namespace) boo
func (*namespaceSearcher) compare(a, b *v1.Namespace, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -82,7 +82,7 @@ func (*nodeSearcher) fuzzy(fuzzy map[string]string, item *v1.Node) bool {
func (*nodeSearcher) compare(a, b *v1.Node, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -82,7 +82,7 @@ func (*persistentVolumeClaimSearcher) fuzzy(fuzzy map[string]string, item *v1.Pe
func (*persistentVolumeClaimSearcher) compare(a, b *v1.PersistentVolumeClaim, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -82,7 +82,7 @@ func (*podSearcher) fuzzy(fuzzy map[string]string, item *v1.Pod) bool {
func (*podSearcher) compare(a, b *v1.Pod, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -52,6 +52,7 @@ const (
label = "label"
createTime = "createTime"
updateTime = "updateTime"
lastScheduleTime = "lastScheduleTime"
displayName = "displayName"
chart = "chart"
release = "release"
......
......@@ -78,7 +78,7 @@ func (*roleSearcher) fuzzy(fuzzy map[string]string, item *rbac.Role) bool {
func (*roleSearcher) compare(a, b *rbac.Role, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -86,7 +86,7 @@ func (*secretSearcher) fuzzy(fuzzy map[string]string, item *v1.Secret) bool {
func (*secretSearcher) compare(a, b *v1.Secret, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -82,7 +82,7 @@ func (*serviceSearcher) fuzzy(fuzzy map[string]string, item *v1.Service) bool {
func (*serviceSearcher) compare(a, b *v1.Service, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -96,7 +96,7 @@ func (*statefulSetSearcher) fuzzy(fuzzy map[string]string, item *v1.StatefulSet)
func (*statefulSetSearcher) compare(a, b *v1.StatefulSet, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -78,7 +78,7 @@ func (*storageClassesSearcher) fuzzy(fuzzy map[string]string, item *v1.StorageCl
func (*storageClassesSearcher) compare(a, b *v1.StorageClass, orderBy string) bool {
switch orderBy {
case createTime:
return a.CreationTimestamp.Time.After(b.CreationTimestamp.Time)
return a.CreationTimestamp.Time.Before(b.CreationTimestamp.Time)
case name:
fallthrough
default:
......
......@@ -21,6 +21,7 @@ package routers
import (
"fmt"
"io/ioutil"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"k8s.io/apimachinery/pkg/labels"
"kubesphere.io/kubesphere/pkg/informers"
......@@ -35,7 +36,6 @@ import (
"strings"
"kubesphere.io/kubesphere/pkg/client"
"kubesphere.io/kubesphere/pkg/constants"
"kubesphere.io/kubesphere/pkg/models/iam"
)
......@@ -139,7 +139,7 @@ func LoadYamls() ([]string, error) {
// Create a ingress controller in a namespace
func CreateRouter(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
var router *corev1.Service
......@@ -214,7 +214,7 @@ func CreateRouter(namespace string, routerType corev1.ServiceType, annotations m
// DeleteRouter is used to delete ingress controller related resources in namespace
// It will not delete ClusterRole resource cause it maybe used by other controllers
func DeleteRouter(namespace string) (*corev1.Service, error) {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
var err error
var router *corev1.Service
......@@ -269,7 +269,7 @@ func DeleteRouter(namespace string) (*corev1.Service, error) {
// Update Ingress Controller Service, change type from NodePort to Loadbalancer or vice versa.
func UpdateRouter(namespace string, routerType corev1.ServiceType, annotations map[string]string) (*corev1.Service, error) {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
var router *corev1.Service
......
......@@ -19,20 +19,19 @@ package workloads
import (
"fmt"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"strings"
"time"
"github.com/golang/glog"
"k8s.io/api/batch/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"kubesphere.io/kubesphere/pkg/client"
)
const retryTimes = 3
func JobReRun(namespace, jobName string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
job, err := k8sClient.BatchV1().Jobs(namespace).Get(jobName, metav1.GetOptions{})
if err != nil {
return err
......@@ -72,7 +71,7 @@ func JobReRun(namespace, jobName string) error {
}
func deleteJob(namespace, job string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
deletePolicy := metav1.DeletePropagationBackground
err := k8sClient.BatchV1().Jobs(namespace).Delete(job, &metav1.DeleteOptions{PropagationPolicy: &deletePolicy})
return err
......
......@@ -22,6 +22,8 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"kubesphere.io/kubesphere/pkg/simple/client/k8s"
"kubesphere.io/kubesphere/pkg/simple/client/mysql"
"net/http"
"kubesphere.io/kubesphere/pkg/constants"
......@@ -49,12 +51,11 @@ import (
"sort"
"kubesphere.io/kubesphere/pkg/client"
kserr "kubesphere.io/kubesphere/pkg/errors"
)
func UnBindDevopsProject(workspace string, devops string) error {
db := client.DBClient()
db := mysql.Client()
defer db.Close()
return db.Delete(&models.WorkspaceDPBinding{Workspace: workspace, DevOpsProject: devops}).Error
}
......@@ -304,19 +305,19 @@ func Namespaces(workspaceName string) ([]*core.Namespace, error) {
}
func BindingDevopsProject(workspace string, devops string) error {
db := client.DBClient()
db := mysql.Client()
defer db.Close()
return db.Create(&models.WorkspaceDPBinding{Workspace: workspace, DevOpsProject: devops}).Error
}
func DeleteNamespace(workspace string, namespaceName string) error {
namespace, err := client.K8sClient().CoreV1().Namespaces().Get(namespaceName, meta_v1.GetOptions{})
namespace, err := k8s.Client().CoreV1().Namespaces().Get(namespaceName, meta_v1.GetOptions{})
if err != nil {
return err
}
if namespace.Labels != nil && namespace.Labels["kubesphere.io/workspace"] == workspace {
deletePolicy := meta_v1.DeletePropagationForeground
return client.K8sClient().CoreV1().Namespaces().Delete(namespaceName, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
return k8s.Client().CoreV1().Namespaces().Delete(namespaceName, &meta_v1.DeleteOptions{PropagationPolicy: &deletePolicy})
} else {
return errors.New("resource not found")
}
......@@ -376,7 +377,7 @@ func release(workspace *models.Workspace) error {
return err
}
func workspaceRoleRelease(workspace string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
deletePolicy := meta_v1.DeletePropagationForeground
for _, role := range constants.WorkSpaceRoles {
......@@ -513,7 +514,7 @@ func Detail(name string) (*models.Workspace, error) {
return nil, err
}
db := client.DBClient()
db := mysql.Client()
defer db.Close()
workspace, err := convertGroupToWorkspace(db, group)
......@@ -604,7 +605,7 @@ func fetch(names []string) ([]*models.Workspace, error) {
return nil, err
}
db := client.DBClient()
db := mysql.Client()
defer db.Close()
......@@ -622,7 +623,7 @@ func fetch(names []string) ([]*models.Workspace, error) {
func ListDevopsProjectsByUser(username string, workspace string, keyword string, orderBy string, reverse bool, limit int, offset int) (int, []models.DevopsProject, error) {
db := client.DBClient()
db := mysql.Client()
defer db.Close()
var workspaceDOPBindings []models.WorkspaceDPBinding
......@@ -738,7 +739,7 @@ func convertGroupToWorkspace(db *gorm.DB, group models.Group) (*models.Workspace
func CreateNamespace(namespace *core.Namespace) (*core.Namespace, error) {
ns, err := client.K8sClient().CoreV1().Namespaces().Create(namespace)
ns, err := k8s.Client().CoreV1().Namespaces().Create(namespace)
if err != nil {
return nil, err
......@@ -784,7 +785,7 @@ func Invite(workspaceName string, users []models.UserInvite) error {
func NamespaceExistCheck(namespaceName string) (bool, error) {
_, err := client.K8sClient().CoreV1().Namespaces().Get(namespaceName, meta_v1.GetOptions{})
_, err := k8s.Client().CoreV1().Namespaces().Get(namespaceName, meta_v1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
......@@ -887,7 +888,7 @@ func GetWorkspaceMembers(workspace string, keyword string) ([]models.User, error
}
func WorkspaceRoleInit(workspace *models.Workspace) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
admin := new(v1.ClusterRole)
admin.Name = fmt.Sprintf("system:%s:%s", workspace.Name, constants.WorkspaceAdmin)
......@@ -1086,7 +1087,7 @@ func WorkspaceRoleInit(workspace *models.Workspace) error {
}
func unbindWorkspaceRole(workspace string, users []string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
for _, name := range constants.WorkSpaceRoles {
roleBinding, err := k8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:%s", workspace, name), meta_v1.GetOptions{})
......@@ -1118,7 +1119,7 @@ func unbindWorkspaceRole(workspace string, users []string) error {
func unbindNamespacesRole(namespaces []string, users []string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
for _, namespace := range namespaces {
roleBindings, err := k8sClient.RbacV1().RoleBindings(namespace).List(meta_v1.ListOptions{})
......@@ -1166,7 +1167,7 @@ func UnbindWorkspace(workspace *models.Workspace, users []string) error {
func CreateWorkspaceRoleBinding(workspace *models.Workspace, username string, role string) error {
k8sClient := client.K8sClient()
k8sClient := k8s.Client()
for _, roleName := range constants.WorkSpaceRoles {
roleBinding, err := k8sClient.RbacV1().ClusterRoleBindings().Get(fmt.Sprintf("system:%s:%s", workspace.Name, roleName), meta_v1.GetOptions{})
......@@ -1220,7 +1221,7 @@ func CreateWorkspaceRoleBinding(workspace *models.Workspace, username string, ro
func GetDevOpsProjects(workspaceName string) ([]string, error) {
db := client.DBClient()
db := mysql.Client()
defer db.Close()
var workspaceDOPBindings []models.WorkspaceDPBinding
......@@ -1313,7 +1314,7 @@ func GetAllProjectNums() (int, error) {
}
func GetAllDevOpsProjectsNums() (int, error) {
db := client.DBClient()
db := mysql.Client()
defer db.Close()
var count int
......
......@@ -16,7 +16,7 @@
*/
package client
package k8s
import (
"flag"
......@@ -44,11 +44,11 @@ func init() {
flag.StringVar(&kubeConfigFile, "kubeconfig", fmt.Sprintf("%s/.kube/config", os.Getenv("HOME")), "path to kubeconfig file")
}
func K8sClient() *kubernetes.Clientset {
func Client() *kubernetes.Clientset {
k8sClientOnce.Do(func() {
config, err := getKubeConfig()
config, err := Config()
if err != nil {
log.Fatalln(err)
......@@ -62,7 +62,7 @@ func K8sClient() *kubernetes.Clientset {
return k8sClient
}
func getKubeConfig() (kubeConfig *rest.Config, err error) {
func Config() (kubeConfig *rest.Config, err error) {
if kubeConfigFile == "" {
if env := os.Getenv("KUBECONFIG"); env != "" {
......
/*
Copyright 2019 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 ldap
import (
......
/*
Copyright 2019 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 ldap
import (
......
......@@ -15,20 +15,18 @@
limitations under the License.
*/
package client
package ldap
import (
"flag"
"fmt"
"github.com/go-ldap/ldap"
ldapPool "kubesphere.io/kubesphere/pkg/client/ldap"
"os"
"log"
"sync"
)
var (
once sync.Once
pool ldapPool.Pool
pool Pool
ldapHost string
ManagerDN string
ManagerPassword string
......@@ -44,11 +42,11 @@ func init() {
flag.StringVar(&GroupSearchBase, "ldap-group-search-base", "ou=Groups,dc=example,dc=org", "ldap group search base")
}
func LdapClient() ldapPool.Pool {
func ldapClientPool() Pool {
once.Do(func() {
var err error
pool, err = ldapPool.NewChannelPool(8, 96, "kubesphere", func(s string) (ldap.Client, error) {
pool, err = NewChannelPool(8, 96, "kubesphere", func(s string) (ldap.Client, error) {
conn, err := ldap.Dial("tcp", ldapHost)
if err != nil {
return nil, err
......@@ -57,9 +55,25 @@ func LdapClient() ldapPool.Pool {
}, []uint16{ldap.LDAPResultTimeLimitExceeded, ldap.ErrorNetwork})
if err != nil {
fmt.Fprint(os.Stderr, err.Error())
panic(err)
log.Fatalln(err)
}
})
return pool
}
func Client() (ldap.Client, error) {
conn, err := ldapClientPool().Get()
if err != nil {
return nil, err
}
err = conn.Bind(ManagerDN, ManagerPassword)
if err != nil {
conn.Close()
return nil, err
}
return conn, nil
}
/*
Copyright 2019 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 ldap
import (
......
......@@ -16,12 +16,15 @@
*/
package client
package mysql
import (
"flag"
"log"
"os"
"os/signal"
"sync"
"syscall"
_ "github.com/go-sql-driver/mysql"
"github.com/jinzhu/gorm"
......@@ -37,7 +40,7 @@ func init() {
flag.StringVar(&dsn, "database-connection", "root@tcp(localhost:3306)/kubesphere?charset=utf8&parseTime=True", "data source name")
}
func DBClient() *gorm.DB {
func Client() *gorm.DB {
dbClientOnce.Do(func() {
var err error
dbClient, err = gorm.Open("mysql", dsn)
......@@ -45,10 +48,12 @@ func DBClient() *gorm.DB {
if err != nil {
log.Fatalln(err)
}
if err := dbClient.DB().Ping(); err != nil {
log.Fatalln(err)
}
c := make(chan os.Signal, 0)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
go func() {
<-c
dbClient.Close()
}()
})
return dbClient
......
......@@ -15,7 +15,7 @@
limitations under the License.
*/
package client
package prometheus
import (
"flag"
......
......@@ -15,7 +15,7 @@
limitations under the License.
*/
package client
package redis
import (
"flag"
......@@ -39,7 +39,7 @@ func init() {
flag.IntVar(&redisDB, "redis-db", 0, "redis db")
}
func RedisClient() *redis.Client {
func Client() *redis.Client {
redisClientOnce.Do(func() {
redisClient = redis.NewClient(&redis.Options{
......
......@@ -134,7 +134,7 @@ func (c *NamespaceController) processNextWorkItem() bool {
return nil
}
if err := c.syncHandler(namespace); err != nil {
if err := c.reconcile(namespace); err != nil {
c.workqueue.AddRateLimited(namespace)
return fmt.Errorf("error syncing '%s': %s, requeuing", namespace, err.Error())
}
......@@ -152,7 +152,7 @@ func (c *NamespaceController) processNextWorkItem() bool {
return true
}
func (c *NamespaceController) syncHandler(name string) error {
func (c *NamespaceController) reconcile(name string) error {
_, err := c.namespaceInformer.Lister().Get(name)
......@@ -162,7 +162,7 @@ func (c *NamespaceController) syncHandler(name string) error {
}
// Handler update or create event
if err := c.checkRoles(name); err != nil {
if err := c.checkAndCreateRoles(name); err != nil {
return err
}
......@@ -175,14 +175,19 @@ func (c *NamespaceController) handleObject(obj interface{}) {
}
}
func (c *NamespaceController) checkRoles(namespace string) error {
// Create default roles
func (c *NamespaceController) checkAndCreateRoles(namespace string) error {
for _, role := range defaultRoles {
_, err := c.roleInformer.Lister().Roles(namespace).Get(role.Name)
if errors.IsNotFound(err) {
r := role.DeepCopy()
r.Namespace = namespace
_, err := c.clientset.RbacV1().Roles(namespace).Create(r)
if err != nil && !errors.IsAlreadyExists(err) {
if err != nil {
if errors.IsNotFound(err) {
r := role.DeepCopy()
r.Namespace = namespace
_, err = c.clientset.RbacV1().Roles(namespace).Create(r)
if err != nil && !errors.IsAlreadyExists(err) {
return err
}
} else {
return err
}
}
......
# 1.4.0
This new release introduces:
* Add `DeferExitHandler`, similar to `RegisterExitHandler` but prepending the handler to the list of handlers (semantically like `defer`) (#848).
* Add `CallerPrettyfier` to `JSONFormatter` and `TextFormatter (#909, #911)
* Add `Entry.WithContext()` and `Entry.Context`, to set a context on entries to be used e.g. in hooks (#919).
Fixes:
* Fix wrong method calls `Logger.Print` and `Logger.Warningln` (#893).
* Update `Entry.Logf` to not do string formatting unless the log level is enabled (#903)
* Fix infinite recursion on unknown `Level.String()` (#907)
* Fix race condition in `getCaller` (#916).
# 1.3.0
This new release introduces:
* Log, Logf, Logln functions for Logger and Entry that take a Level
Fixes:
* Building prometheus node_exporter on AIX (#840)
* Race condition in TextFormatter (#468)
* Travis CI import path (#868)
* Remove coloured output on Windows (#862)
* Pointer to func as field in JSONFormatter (#870)
* Properly marshal Levels (#873)
# 1.2.0
This new release introduces:
* A new method `SetReportCaller` in the `Logger` to enable the file, line and calling function from which the trace has been issued
......
......@@ -365,6 +365,7 @@ Third party logging formatters:
* [`logstash`](https://github.com/bshuster-repo/logrus-logstash-hook). Logs fields as [Logstash](http://logstash.net) Events.
* [`prefixed`](https://github.com/x-cray/logrus-prefixed-formatter). Displays log entry source along with alternative layout.
* [`zalgo`](https://github.com/aybabtme/logzalgo). Invoking the P͉̫o̳̼̊w̖͈̰͎e̬͔̭͂r͚̼̹̲ ̫͓͉̳͈ō̠͕͖̚f̝͍̠ ͕̲̞͖͑Z̖̫̤̫ͪa͉̬͈̗l͖͎g̳̥o̰̥̅!̣͔̲̻͊̄ ̙̘̦̹̦.
* [`nested-logrus-formatter`](https://github.com/antonfisher/nested-logrus-formatter). Converts logrus fields to a nested structure.
You can define your formatter by implementing the `Formatter` interface,
requiring a `Format` method. `Format` takes an `*Entry`. `entry.Data` is a
......
......@@ -51,9 +51,9 @@ func Exit(code int) {
os.Exit(code)
}
// RegisterExitHandler adds a Logrus Exit handler, call logrus.Exit to invoke
// all handlers. The handlers will also be invoked when any Fatal log entry is
// made.
// RegisterExitHandler appends a Logrus Exit handler to the list of handlers,
// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
// any Fatal log entry is made.
//
// This method is useful when a caller wishes to use logrus to log a fatal
// message but also needs to gracefully shutdown. An example usecase could be
......@@ -62,3 +62,15 @@ func Exit(code int) {
func RegisterExitHandler(handler func()) {
handlers = append(handlers, handler)
}
// DeferExitHandler prepends a Logrus Exit handler to the list of handlers,
// call logrus.Exit to invoke all handlers. The handlers will also be invoked when
// any Fatal log entry is made.
//
// This method is useful when a caller wishes to use logrus to log a fatal
// message but also needs to gracefully shutdown. An example usecase could be
// closing database connections, or sending a alert that the application is
// closing.
func DeferExitHandler(handler func()) {
handlers = append([]func(){handler}, handlers...)
}
version: "{build}"
platform: x64
clone_folder: c:\gopath\src\github.com\sirupsen\logrus
environment:
GOPATH: c:\gopath
branches:
only:
- master
install:
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
- go version
build_script:
- go get -t
- go test
version: "{build}"
platform: x64
clone_folder: c:\gopath\src\github.com\sirupsen\logrus
environment:
GOPATH: c:\gopath
branches:
only:
- master
install:
- set PATH=%GOPATH%\bin;c:\go\bin;%PATH%
- go version
build_script:
- go get -t
- go test
......@@ -2,6 +2,7 @@ package logrus
import (
"bytes"
"context"
"fmt"
"os"
"reflect"
......@@ -69,6 +70,9 @@ type Entry struct {
// When formatter is called in entry.log(), a Buffer may be set to entry
Buffer *bytes.Buffer
// Contains the context set by the user. Useful for hook processing etc.
Context context.Context
// err may contain a field formatting error
err string
}
......@@ -97,6 +101,12 @@ func (entry *Entry) WithError(err error) *Entry {
return entry.WithField(ErrorKey, err)
}
// Add a context to the Entry.
func (entry *Entry) WithContext(ctx context.Context) *Entry {
entry.Context = ctx
return entry
}
// Add a single field to the Entry.
func (entry *Entry) WithField(key string, value interface{}) *Entry {
return entry.WithFields(Fields{key: value})
......@@ -130,12 +140,12 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
data[k] = v
}
}
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr}
return &Entry{Logger: entry.Logger, Data: data, Time: entry.Time, err: fieldErr, Context: entry.Context}
}
// Overrides the time of the Entry.
func (entry *Entry) WithTime(t time.Time) *Entry {
return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err}
return &Entry{Logger: entry.Logger, Data: entry.Data, Time: t, err: entry.err, Context: entry.Context}
}
// getPackageName reduces a fully qualified function name to the package name
......@@ -156,20 +166,23 @@ func getPackageName(f string) string {
// getCaller retrieves the name of the first non-logrus calling function
func getCaller() *runtime.Frame {
// Restrict the lookback frames to avoid runaway lookups
pcs := make([]uintptr, maximumCallerDepth)
depth := runtime.Callers(minimumCallerDepth, pcs)
frames := runtime.CallersFrames(pcs[:depth])
// cache this package's fully-qualified name
callerInitOnce.Do(func() {
logrusPackage = getPackageName(runtime.FuncForPC(pcs[0]).Name())
pcs := make([]uintptr, 2)
_ = runtime.Callers(0, pcs)
logrusPackage = getPackageName(runtime.FuncForPC(pcs[1]).Name())
// now that we have the cache, we can skip a minimum count of known-logrus functions
// XXX this is dubious, the number of frames may vary store an entry in a logger interface
// XXX this is dubious, the number of frames may vary
minimumCallerDepth = knownLogrusFrames
})
// Restrict the lookback frames to avoid runaway lookups
pcs := make([]uintptr, maximumCallerDepth)
depth := runtime.Callers(minimumCallerDepth, pcs)
frames := runtime.CallersFrames(pcs[:depth])
for f, again := frames.Next(); again; f, again = frames.Next() {
pkg := getPackageName(f.Function)
......@@ -298,7 +311,9 @@ func (entry *Entry) Panic(args ...interface{}) {
// Entry Printf family functions
func (entry *Entry) Logf(level Level, format string, args ...interface{}) {
entry.Log(level, fmt.Sprintf(format, args...))
if entry.Logger.IsLevelEnabled(level) {
entry.Log(level, fmt.Sprintf(format, args...))
}
}
func (entry *Entry) Tracef(format string, args ...interface{}) {
......
package logrus
import (
"context"
"io"
"time"
)
......@@ -55,6 +56,11 @@ func WithError(err error) *Entry {
return std.WithField(ErrorKey, err)
}
// WithContext creates an entry from the standard logger and adds a context to it.
func WithContext(ctx context.Context) *Entry {
return std.WithContext(ctx)
}
// WithField creates an entry from the standard logger and adds a field to
// it. If you want multiple fields, use `WithFields`.
//
......
......@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"runtime"
)
type fieldKey string
......@@ -42,6 +43,12 @@ type JSONFormatter struct {
// }
FieldMap FieldMap
// CallerPrettyfier can be set by the user to modify the content
// of the function and file keys in the json data when ReportCaller is
// activated. If any of the returned value is the empty string the
// corresponding key will be removed from json fields.
CallerPrettyfier func(*runtime.Frame) (function string, file string)
// PrettyPrint will indent all json logs
PrettyPrint bool
}
......@@ -82,8 +89,17 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
if entry.HasCaller() {
data[f.FieldMap.resolve(FieldKeyFunc)] = entry.Caller.Function
data[f.FieldMap.resolve(FieldKeyFile)] = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
funcVal := entry.Caller.Function
fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
if f.CallerPrettyfier != nil {
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
}
if funcVal != "" {
data[f.FieldMap.resolve(FieldKeyFunc)] = funcVal
}
if fileVal != "" {
data[f.FieldMap.resolve(FieldKeyFile)] = fileVal
}
}
var b *bytes.Buffer
......@@ -98,7 +114,7 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
encoder.SetIndent("", " ")
}
if err := encoder.Encode(data); err != nil {
return nil, fmt.Errorf("Failed to marshal fields to JSON, %v", err)
return nil, fmt.Errorf("failed to marshal fields to JSON, %v", err)
}
return b.Bytes(), nil
......
package logrus
import (
"context"
"io"
"os"
"sync"
......@@ -124,6 +125,13 @@ func (logger *Logger) WithError(err error) *Entry {
return entry.WithError(err)
}
// Add a context to the log entry.
func (logger *Logger) WithContext(ctx context.Context) *Entry {
entry := logger.newEntry()
defer logger.releaseEntry(entry)
return entry.WithContext(ctx)
}
// Overrides the time of the log entry.
func (logger *Logger) WithTime(t time.Time) *Entry {
entry := logger.newEntry()
......@@ -200,7 +208,7 @@ func (logger *Logger) Info(args ...interface{}) {
func (logger *Logger) Print(args ...interface{}) {
entry := logger.newEntry()
entry.Info(args...)
entry.Print(args...)
logger.releaseEntry(entry)
}
......@@ -256,7 +264,7 @@ func (logger *Logger) Warnln(args ...interface{}) {
}
func (logger *Logger) Warningln(args ...interface{}) {
logger.Warn(args...)
logger.Warnln(args...)
}
func (logger *Logger) Errorln(args ...interface{}) {
......
......@@ -74,7 +74,7 @@ func (level Level) MarshalText() ([]byte, error) {
return []byte("panic"), nil
}
return nil, fmt.Errorf("not a valid lorus level %q", level)
return nil, fmt.Errorf("not a valid logrus level %d", level)
}
// A constant exposing all logging levels
......
......@@ -12,18 +12,13 @@ import (
)
const (
nocolor = 0
red = 31
green = 32
yellow = 33
blue = 36
gray = 37
red = 31
yellow = 33
blue = 36
gray = 37
)
var (
baseTimestamp time.Time
emptyFieldMap FieldMap
)
var baseTimestamp time.Time
func init() {
baseTimestamp = time.Now()
......@@ -77,6 +72,12 @@ type TextFormatter struct {
// FieldKeyMsg: "@message"}}
FieldMap FieldMap
// CallerPrettyfier can be set by the user to modify the content
// of the function and file keys in the json data when ReportCaller is
// activated. If any of the returned value is the empty string the
// corresponding key will be removed from json fields.
CallerPrettyfier func(*runtime.Frame) (function string, file string)
terminalInitOnce sync.Once
}
......@@ -118,6 +119,8 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
keys = append(keys, k)
}
var funcVal, fileVal string
fixedKeys := make([]string, 0, 4+len(data))
if !f.DisableTimestamp {
fixedKeys = append(fixedKeys, f.FieldMap.resolve(FieldKeyTime))
......@@ -132,6 +135,12 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
if entry.HasCaller() {
fixedKeys = append(fixedKeys,
f.FieldMap.resolve(FieldKeyFunc), f.FieldMap.resolve(FieldKeyFile))
if f.CallerPrettyfier != nil {
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
} else {
funcVal = entry.Caller.Function
fileVal = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
}
}
if !f.DisableSorting {
......@@ -166,6 +175,7 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
if f.isColored() {
f.printColored(b, entry, keys, data, timestampFormat)
} else {
for _, key := range fixedKeys {
var value interface{}
switch {
......@@ -178,9 +188,9 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
case key == f.FieldMap.resolve(FieldKeyLogrusError):
value = entry.err
case key == f.FieldMap.resolve(FieldKeyFunc) && entry.HasCaller():
value = entry.Caller.Function
value = funcVal
case key == f.FieldMap.resolve(FieldKeyFile) && entry.HasCaller():
value = fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
value = fileVal
default:
value = data[key]
}
......@@ -217,8 +227,13 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
caller := ""
if entry.HasCaller() {
caller = fmt.Sprintf("%s:%d %s()",
entry.Caller.File, entry.Caller.Line, entry.Caller.Function)
funcVal := fmt.Sprintf("%s()", entry.Caller.Function)
fileVal := fmt.Sprintf("%s:%d", entry.Caller.File, entry.Caller.Line)
if f.CallerPrettyfier != nil {
funcVal, fileVal = f.CallerPrettyfier(entry.Caller)
}
caller = fileVal + " " + funcVal
}
if f.DisableTimestamp {
......
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
.vscode
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
*.prof
language: go
go:
- "1.8.x"
- "1.9.x"
- "1.10.x"
env:
- TRAVIS_GOARCH=amd64
- TRAVIS_GOARCH=386
before_install:
- export GOARCH=$TRAVIS_GOARCH
branches:
only:
- master
before_script:
- go get -u github.com/klauspost/asmfmt/cmd/asmfmt
script:
- diff -au <(gofmt -d .) <(printf "")
- diff -au <(asmfmt -d .) <(printf "")
- go test -v ./...
The MIT License (MIT)
Copyright (c) 2016 Andreas Auernhammer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
[![Godoc Reference](https://godoc.org/github.com/aead/chacha20?status.svg)](https://godoc.org/github.com/aead/chacha20)
[![Build Status](https://travis-ci.org/aead/chacha20.svg?branch=master)](https://travis-ci.org/aead/chacha20)
[![Go Report Card](https://goreportcard.com/badge/aead/chacha20)](https://goreportcard.com/report/aead/chacha20)
## The ChaCha20 stream cipher
ChaCha is a stream cipher family created by Daniel J. Bernstein.
The most common ChaCha variant is ChaCha20 (20 rounds). ChaCha20 is
standardized in [RFC 7539](https://tools.ietf.org/html/rfc7539 "RFC 7539").
This package provides implementations of three ChaCha versions:
- ChaCha20 with a 64 bit nonce (can en/decrypt up to 2^64 * 64 bytes for one key-nonce combination)
- ChaCha20 with a 96 bit nonce (can en/decrypt up to 2^32 * 64 bytes ~ 256 GB for one key-nonce combination)
- XChaCha20 with a 192 bit nonce (can en/decrypt up to 2^64 * 64 bytes for one key-nonce combination)
Furthermore the chacha sub package implements ChaCha20/12 and ChaCha20/8.
These versions use 12 or 8 rounds instead of 20.
But it's recommended to use ChaCha20 (with 20 rounds) - it will be fast enough for almost all purposes.
### Installation
Install in your GOPATH: `go get -u github.com/aead/chacha20`
### Requirements
All go versions >= 1.8.7 are supported.
The code may also work on Go 1.7 but this is not tested.
### Performance
#### AMD64
Hardware: Intel i7-6500U 2.50GHz x 2
System: Linux Ubuntu 16.04 - kernel: 4.4.0-62-generic
Go version: 1.8.0
```
AVX2
name speed cpb
ChaCha20_64-4 573MB/s ± 0% 4.16
ChaCha20_1K-4 2.19GB/s ± 0% 1.06
XChaCha20_64-4 261MB/s ± 0% 9.13
XChaCha20_1K-4 1.69GB/s ± 4% 1.37
XORKeyStream64-4 474MB/s ± 2% 5.02
XORKeyStream1K-4 2.09GB/s ± 1% 1.11
XChaCha20_XORKeyStream64-4 262MB/s ± 0% 9.09
XChaCha20_XORKeyStream1K-4 1.71GB/s ± 1% 1.36
SSSE3
name speed cpb
ChaCha20_64-4 583MB/s ± 0% 4.08
ChaCha20_1K-4 1.15GB/s ± 1% 2.02
XChaCha20_64-4 267MB/s ± 0% 8.92
XChaCha20_1K-4 984MB/s ± 5% 2.42
XORKeyStream64-4 492MB/s ± 1% 4.84
XORKeyStream1K-4 1.10GB/s ± 5% 2.11
XChaCha20_XORKeyStream64-4 266MB/s ± 0% 8.96
XChaCha20_XORKeyStream1K-4 1.00GB/s ± 2% 2.32
```
#### 386
Hardware: Intel i7-6500U 2.50GHz x 2
System: Linux Ubuntu 16.04 - kernel: 4.4.0-62-generic
Go version: 1.8.0
```
SSSE3
name                        speed cpb
ChaCha20_64-4               570MB/s ± 0% 4.18
ChaCha20_1K-4               650MB/s ± 0% 3.66
XChaCha20_64-4              223MB/s ± 0% 10.69
XChaCha20_1K-4              584MB/s ± 1% 4.08
XORKeyStream64-4            392MB/s ± 1% 6.08
XORKeyStream1K-4            629MB/s ± 1% 3.79
XChaCha20_XORKeyStream64-4  222MB/s ± 0% 10.73
XChaCha20_XORKeyStream1K-4  585MB/s ± 0% 4.07
SSE2
name speed cpb
ChaCha20_64-4 509MB/s ± 0% 4.68
ChaCha20_1K-4 553MB/s ± 2% 4.31
XChaCha20_64-4 201MB/s ± 0% 11.86
XChaCha20_1K-4 498MB/s ± 4% 4.78
XORKeyStream64-4 359MB/s ± 1% 6.64
XORKeyStream1K-4 545MB/s ± 0% 4.37
XChaCha20_XORKeyStream64-4 201MB/s ± 1% 11.86
XChaCha20_XORKeyStream1K-4 507MB/s ± 0% 4.70
```
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// Package chacha implements some low-level functions of the
// ChaCha cipher family.
package chacha // import "github.com/aead/chacha20/chacha"
import (
"encoding/binary"
"errors"
"math"
)
const (
// NonceSize is the size of the ChaCha20 nonce in bytes.
NonceSize = 8
// INonceSize is the size of the IETF-ChaCha20 nonce in bytes.
INonceSize = 12
// XNonceSize is the size of the XChaCha20 nonce in bytes.
XNonceSize = 24
// KeySize is the size of the key in bytes.
KeySize = 32
)
var (
useSSE2 bool
useSSSE3 bool
useAVX bool
useAVX2 bool
)
var (
errKeySize = errors.New("chacha20/chacha: bad key length")
errInvalidNonce = errors.New("chacha20/chacha: bad nonce length")
)
func setup(state *[64]byte, nonce, key []byte) (err error) {
if len(key) != KeySize {
err = errKeySize
return
}
var Nonce [16]byte
switch len(nonce) {
case NonceSize:
copy(Nonce[8:], nonce)
initialize(state, key, &Nonce)
case INonceSize:
copy(Nonce[4:], nonce)
initialize(state, key, &Nonce)
case XNonceSize:
var tmpKey [32]byte
var hNonce [16]byte
copy(hNonce[:], nonce[:16])
copy(tmpKey[:], key)
HChaCha20(&tmpKey, &hNonce, &tmpKey)
copy(Nonce[8:], nonce[16:])
initialize(state, tmpKey[:], &Nonce)
// BUG(aead): A "good" compiler will remove this (optimizations)
// But using the provided key instead of tmpKey,
// will change the key (-> probably confuses users)
for i := range tmpKey {
tmpKey[i] = 0
}
default:
err = errInvalidNonce
}
return
}
// XORKeyStream crypts bytes from src to dst using the given nonce and key.
// The length of the nonce determinds the version of ChaCha20:
// - NonceSize: ChaCha20/r with a 64 bit nonce and a 2^64 * 64 byte period.
// - INonceSize: ChaCha20/r as defined in RFC 7539 and a 2^32 * 64 byte period.
// - XNonceSize: XChaCha20/r with a 192 bit nonce and a 2^64 * 64 byte period.
// The rounds argument specifies the number of rounds performed for keystream
// generation - valid values are 8, 12 or 20. The src and dst may be the same slice
// but otherwise should not overlap. If len(dst) < len(src) this function panics.
// If the nonce is neither 64, 96 nor 192 bits long, this function panics.
func XORKeyStream(dst, src, nonce, key []byte, rounds int) {
if rounds != 20 && rounds != 12 && rounds != 8 {
panic("chacha20/chacha: bad number of rounds")
}
if len(dst) < len(src) {
panic("chacha20/chacha: dst buffer is to small")
}
if len(nonce) == INonceSize && uint64(len(src)) > (1<<38) {
panic("chacha20/chacha: src is too large")
}
var block, state [64]byte
if err := setup(&state, nonce, key); err != nil {
panic(err)
}
xorKeyStream(dst, src, &block, &state, rounds)
}
// Cipher implements ChaCha20/r (XChaCha20/r) for a given number of rounds r.
type Cipher struct {
state, block [64]byte
off int
rounds int // 20 for ChaCha20
noncesize int
}
// NewCipher returns a new *chacha.Cipher implementing the ChaCha20/r or XChaCha20/r
// (r = 8, 12 or 20) stream cipher. The nonce must be unique for one key for all time.
// The length of the nonce determinds the version of ChaCha20:
// - NonceSize: ChaCha20/r with a 64 bit nonce and a 2^64 * 64 byte period.
// - INonceSize: ChaCha20/r as defined in RFC 7539 and a 2^32 * 64 byte period.
// - XNonceSize: XChaCha20/r with a 192 bit nonce and a 2^64 * 64 byte period.
// If the nonce is neither 64, 96 nor 192 bits long, a non-nil error is returned.
func NewCipher(nonce, key []byte, rounds int) (*Cipher, error) {
if rounds != 20 && rounds != 12 && rounds != 8 {
panic("chacha20/chacha: bad number of rounds")
}
c := new(Cipher)
if err := setup(&(c.state), nonce, key); err != nil {
return nil, err
}
c.rounds = rounds
if len(nonce) == INonceSize {
c.noncesize = INonceSize
} else {
c.noncesize = NonceSize
}
return c, nil
}
// XORKeyStream crypts bytes from src to dst. Src and dst may be the same slice
// but otherwise should not overlap. If len(dst) < len(src) the function panics.
func (c *Cipher) XORKeyStream(dst, src []byte) {
if len(dst) < len(src) {
panic("chacha20/chacha: dst buffer is to small")
}
if c.off > 0 {
n := len(c.block[c.off:])
if len(src) <= n {
for i, v := range src {
dst[i] = v ^ c.block[c.off]
c.off++
}
if c.off == 64 {
c.off = 0
}
return
}
for i, v := range c.block[c.off:] {
dst[i] = src[i] ^ v
}
src = src[n:]
dst = dst[n:]
c.off = 0
}
// check for counter overflow
blocksToXOR := len(src) / 64
if len(src)%64 != 0 {
blocksToXOR++
}
var overflow bool
if c.noncesize == INonceSize {
overflow = binary.LittleEndian.Uint32(c.state[48:]) > math.MaxUint32-uint32(blocksToXOR)
} else {
overflow = binary.LittleEndian.Uint64(c.state[48:]) > math.MaxUint64-uint64(blocksToXOR)
}
if overflow {
panic("chacha20/chacha: counter overflow")
}
c.off += xorKeyStream(dst, src, &(c.block), &(c.state), c.rounds)
}
// SetCounter skips ctr * 64 byte blocks. SetCounter(0) resets the cipher.
// This function always skips the unused keystream of the current 64 byte block.
func (c *Cipher) SetCounter(ctr uint64) {
if c.noncesize == INonceSize {
binary.LittleEndian.PutUint32(c.state[48:], uint32(ctr))
} else {
binary.LittleEndian.PutUint64(c.state[48:], ctr)
}
c.off = 0
}
// HChaCha20 generates 32 pseudo-random bytes from a 128 bit nonce and a 256 bit secret key.
// It can be used as a key-derivation-function (KDF).
func HChaCha20(out *[32]byte, nonce *[16]byte, key *[32]byte) { hChaCha20(out, nonce, key) }
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// +build amd64,!gccgo,!appengine,!nacl
#include "const.s"
#include "macro.s"
#define TWO 0(SP)
#define C16 32(SP)
#define C8 64(SP)
#define STATE_0 96(SP)
#define STATE_1 128(SP)
#define STATE_2 160(SP)
#define STATE_3 192(SP)
#define TMP_0 224(SP)
#define TMP_1 256(SP)
// func xorKeyStreamAVX(dst, src []byte, block, state *[64]byte, rounds int) int
TEXT ·xorKeyStreamAVX2(SB), 4, $320-80
MOVQ dst_base+0(FP), DI
MOVQ src_base+24(FP), SI
MOVQ block+48(FP), BX
MOVQ state+56(FP), AX
MOVQ rounds+64(FP), DX
MOVQ src_len+32(FP), CX
MOVQ SP, R8
ADDQ $32, SP
ANDQ $-32, SP
VMOVDQU 0(AX), Y2
VMOVDQU 32(AX), Y3
VPERM2I128 $0x22, Y2, Y0, Y0
VPERM2I128 $0x33, Y2, Y1, Y1
VPERM2I128 $0x22, Y3, Y2, Y2
VPERM2I128 $0x33, Y3, Y3, Y3
TESTQ CX, CX
JZ done
VMOVDQU ·one_AVX2<>(SB), Y4
VPADDD Y4, Y3, Y3
VMOVDQA Y0, STATE_0
VMOVDQA Y1, STATE_1
VMOVDQA Y2, STATE_2
VMOVDQA Y3, STATE_3
VMOVDQU ·rol16_AVX2<>(SB), Y4
VMOVDQU ·rol8_AVX2<>(SB), Y5
VMOVDQU ·two_AVX2<>(SB), Y6
VMOVDQA Y4, Y14
VMOVDQA Y5, Y15
VMOVDQA Y4, C16
VMOVDQA Y5, C8
VMOVDQA Y6, TWO
CMPQ CX, $64
JBE between_0_and_64
CMPQ CX, $192
JBE between_64_and_192
CMPQ CX, $320
JBE between_192_and_320
CMPQ CX, $448
JBE between_320_and_448
at_least_512:
VMOVDQA Y0, Y4
VMOVDQA Y1, Y5
VMOVDQA Y2, Y6
VPADDQ TWO, Y3, Y7
VMOVDQA Y0, Y8
VMOVDQA Y1, Y9
VMOVDQA Y2, Y10
VPADDQ TWO, Y7, Y11
VMOVDQA Y0, Y12
VMOVDQA Y1, Y13
VMOVDQA Y2, Y14
VPADDQ TWO, Y11, Y15
MOVQ DX, R9
chacha_loop_512:
VMOVDQA Y8, TMP_0
CHACHA_QROUND_AVX(Y0, Y1, Y2, Y3, Y8, C16, C8)
CHACHA_QROUND_AVX(Y4, Y5, Y6, Y7, Y8, C16, C8)
VMOVDQA TMP_0, Y8
VMOVDQA Y0, TMP_0
CHACHA_QROUND_AVX(Y8, Y9, Y10, Y11, Y0, C16, C8)
CHACHA_QROUND_AVX(Y12, Y13, Y14, Y15, Y0, C16, C8)
CHACHA_SHUFFLE_AVX(Y1, Y2, Y3)
CHACHA_SHUFFLE_AVX(Y5, Y6, Y7)
CHACHA_SHUFFLE_AVX(Y9, Y10, Y11)
CHACHA_SHUFFLE_AVX(Y13, Y14, Y15)
CHACHA_QROUND_AVX(Y12, Y13, Y14, Y15, Y0, C16, C8)
CHACHA_QROUND_AVX(Y8, Y9, Y10, Y11, Y0, C16, C8)
VMOVDQA TMP_0, Y0
VMOVDQA Y8, TMP_0
CHACHA_QROUND_AVX(Y4, Y5, Y6, Y7, Y8, C16, C8)
CHACHA_QROUND_AVX(Y0, Y1, Y2, Y3, Y8, C16, C8)
VMOVDQA TMP_0, Y8
CHACHA_SHUFFLE_AVX(Y3, Y2, Y1)
CHACHA_SHUFFLE_AVX(Y7, Y6, Y5)
CHACHA_SHUFFLE_AVX(Y11, Y10, Y9)
CHACHA_SHUFFLE_AVX(Y15, Y14, Y13)
SUBQ $2, R9
JA chacha_loop_512
VMOVDQA Y12, TMP_0
VMOVDQA Y13, TMP_1
VPADDD STATE_0, Y0, Y0
VPADDD STATE_1, Y1, Y1
VPADDD STATE_2, Y2, Y2
VPADDD STATE_3, Y3, Y3
XOR_AVX2(DI, SI, 0, Y0, Y1, Y2, Y3, Y12, Y13)
VMOVDQA STATE_0, Y0
VMOVDQA STATE_1, Y1
VMOVDQA STATE_2, Y2
VMOVDQA STATE_3, Y3
VPADDQ TWO, Y3, Y3
VPADDD Y0, Y4, Y4
VPADDD Y1, Y5, Y5
VPADDD Y2, Y6, Y6
VPADDD Y3, Y7, Y7
XOR_AVX2(DI, SI, 128, Y4, Y5, Y6, Y7, Y12, Y13)
VPADDQ TWO, Y3, Y3
VPADDD Y0, Y8, Y8
VPADDD Y1, Y9, Y9
VPADDD Y2, Y10, Y10
VPADDD Y3, Y11, Y11
XOR_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
VPADDQ TWO, Y3, Y3
VPADDD TMP_0, Y0, Y12
VPADDD TMP_1, Y1, Y13
VPADDD Y2, Y14, Y14
VPADDD Y3, Y15, Y15
VPADDQ TWO, Y3, Y3
CMPQ CX, $512
JB less_than_512
XOR_AVX2(DI, SI, 384, Y12, Y13, Y14, Y15, Y4, Y5)
VMOVDQA Y3, STATE_3
ADDQ $512, SI
ADDQ $512, DI
SUBQ $512, CX
CMPQ CX, $448
JA at_least_512
TESTQ CX, CX
JZ done
VMOVDQA C16, Y14
VMOVDQA C8, Y15
CMPQ CX, $64
JBE between_0_and_64
CMPQ CX, $192
JBE between_64_and_192
CMPQ CX, $320
JBE between_192_and_320
JMP between_320_and_448
less_than_512:
XOR_UPPER_AVX2(DI, SI, 384, Y12, Y13, Y14, Y15, Y4, Y5)
EXTRACT_LOWER(BX, Y12, Y13, Y14, Y15, Y4)
ADDQ $448, SI
ADDQ $448, DI
SUBQ $448, CX
JMP finalize
between_320_and_448:
VMOVDQA Y0, Y4
VMOVDQA Y1, Y5
VMOVDQA Y2, Y6
VPADDQ TWO, Y3, Y7
VMOVDQA Y0, Y8
VMOVDQA Y1, Y9
VMOVDQA Y2, Y10
VPADDQ TWO, Y7, Y11
MOVQ DX, R9
chacha_loop_384:
CHACHA_QROUND_AVX(Y0, Y1, Y2, Y3, Y13, Y14, Y15)
CHACHA_QROUND_AVX(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
CHACHA_QROUND_AVX(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
CHACHA_SHUFFLE_AVX(Y1, Y2, Y3)
CHACHA_SHUFFLE_AVX(Y5, Y6, Y7)
CHACHA_SHUFFLE_AVX(Y9, Y10, Y11)
CHACHA_QROUND_AVX(Y0, Y1, Y2, Y3, Y13, Y14, Y15)
CHACHA_QROUND_AVX(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
CHACHA_QROUND_AVX(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
CHACHA_SHUFFLE_AVX(Y3, Y2, Y1)
CHACHA_SHUFFLE_AVX(Y7, Y6, Y5)
CHACHA_SHUFFLE_AVX(Y11, Y10, Y9)
SUBQ $2, R9
JA chacha_loop_384
VPADDD STATE_0, Y0, Y0
VPADDD STATE_1, Y1, Y1
VPADDD STATE_2, Y2, Y2
VPADDD STATE_3, Y3, Y3
XOR_AVX2(DI, SI, 0, Y0, Y1, Y2, Y3, Y12, Y13)
VMOVDQA STATE_0, Y0
VMOVDQA STATE_1, Y1
VMOVDQA STATE_2, Y2
VMOVDQA STATE_3, Y3
VPADDQ TWO, Y3, Y3
VPADDD Y0, Y4, Y4
VPADDD Y1, Y5, Y5
VPADDD Y2, Y6, Y6
VPADDD Y3, Y7, Y7
XOR_AVX2(DI, SI, 128, Y4, Y5, Y6, Y7, Y12, Y13)
VPADDQ TWO, Y3, Y3
VPADDD Y0, Y8, Y8
VPADDD Y1, Y9, Y9
VPADDD Y2, Y10, Y10
VPADDD Y3, Y11, Y11
VPADDQ TWO, Y3, Y3
CMPQ CX, $384
JB less_than_384
XOR_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
SUBQ $384, CX
TESTQ CX, CX
JE done
ADDQ $384, SI
ADDQ $384, DI
JMP between_0_and_64
less_than_384:
XOR_UPPER_AVX2(DI, SI, 256, Y8, Y9, Y10, Y11, Y12, Y13)
EXTRACT_LOWER(BX, Y8, Y9, Y10, Y11, Y12)
ADDQ $320, SI
ADDQ $320, DI
SUBQ $320, CX
JMP finalize
between_192_and_320:
VMOVDQA Y0, Y4
VMOVDQA Y1, Y5
VMOVDQA Y2, Y6
VMOVDQA Y3, Y7
VMOVDQA Y0, Y8
VMOVDQA Y1, Y9
VMOVDQA Y2, Y10
VPADDQ TWO, Y3, Y11
MOVQ DX, R9
chacha_loop_256:
CHACHA_QROUND_AVX(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
CHACHA_QROUND_AVX(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
CHACHA_SHUFFLE_AVX(Y5, Y6, Y7)
CHACHA_SHUFFLE_AVX(Y9, Y10, Y11)
CHACHA_QROUND_AVX(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
CHACHA_QROUND_AVX(Y8, Y9, Y10, Y11, Y13, Y14, Y15)
CHACHA_SHUFFLE_AVX(Y7, Y6, Y5)
CHACHA_SHUFFLE_AVX(Y11, Y10, Y9)
SUBQ $2, R9
JA chacha_loop_256
VPADDD Y0, Y4, Y4
VPADDD Y1, Y5, Y5
VPADDD Y2, Y6, Y6
VPADDD Y3, Y7, Y7
VPADDQ TWO, Y3, Y3
XOR_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
VPADDD Y0, Y8, Y8
VPADDD Y1, Y9, Y9
VPADDD Y2, Y10, Y10
VPADDD Y3, Y11, Y11
VPADDQ TWO, Y3, Y3
CMPQ CX, $256
JB less_than_256
XOR_AVX2(DI, SI, 128, Y8, Y9, Y10, Y11, Y12, Y13)
SUBQ $256, CX
TESTQ CX, CX
JE done
ADDQ $256, SI
ADDQ $256, DI
JMP between_0_and_64
less_than_256:
XOR_UPPER_AVX2(DI, SI, 128, Y8, Y9, Y10, Y11, Y12, Y13)
EXTRACT_LOWER(BX, Y8, Y9, Y10, Y11, Y12)
ADDQ $192, SI
ADDQ $192, DI
SUBQ $192, CX
JMP finalize
between_64_and_192:
VMOVDQA Y0, Y4
VMOVDQA Y1, Y5
VMOVDQA Y2, Y6
VMOVDQA Y3, Y7
MOVQ DX, R9
chacha_loop_128:
CHACHA_QROUND_AVX(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
CHACHA_SHUFFLE_AVX(Y5, Y6, Y7)
CHACHA_QROUND_AVX(Y4, Y5, Y6, Y7, Y13, Y14, Y15)
CHACHA_SHUFFLE_AVX(Y7, Y6, Y5)
SUBQ $2, R9
JA chacha_loop_128
VPADDD Y0, Y4, Y4
VPADDD Y1, Y5, Y5
VPADDD Y2, Y6, Y6
VPADDD Y3, Y7, Y7
VPADDQ TWO, Y3, Y3
CMPQ CX, $128
JB less_than_128
XOR_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
SUBQ $128, CX
TESTQ CX, CX
JE done
ADDQ $128, SI
ADDQ $128, DI
JMP between_0_and_64
less_than_128:
XOR_UPPER_AVX2(DI, SI, 0, Y4, Y5, Y6, Y7, Y12, Y13)
EXTRACT_LOWER(BX, Y4, Y5, Y6, Y7, Y13)
ADDQ $64, SI
ADDQ $64, DI
SUBQ $64, CX
JMP finalize
between_0_and_64:
VMOVDQA X0, X4
VMOVDQA X1, X5
VMOVDQA X2, X6
VMOVDQA X3, X7
MOVQ DX, R9
chacha_loop_64:
CHACHA_QROUND_AVX(X4, X5, X6, X7, X13, X14, X15)
CHACHA_SHUFFLE_AVX(X5, X6, X7)
CHACHA_QROUND_AVX(X4, X5, X6, X7, X13, X14, X15)
CHACHA_SHUFFLE_AVX(X7, X6, X5)
SUBQ $2, R9
JA chacha_loop_64
VPADDD X0, X4, X4
VPADDD X1, X5, X5
VPADDD X2, X6, X6
VPADDD X3, X7, X7
VMOVDQU ·one<>(SB), X0
VPADDQ X0, X3, X3
CMPQ CX, $64
JB less_than_64
XOR_AVX(DI, SI, 0, X4, X5, X6, X7, X13)
SUBQ $64, CX
JMP done
less_than_64:
VMOVDQU X4, 0(BX)
VMOVDQU X5, 16(BX)
VMOVDQU X6, 32(BX)
VMOVDQU X7, 48(BX)
finalize:
XORQ R11, R11
XORQ R12, R12
MOVQ CX, BP
xor_loop:
MOVB 0(SI), R11
MOVB 0(BX), R12
XORQ R11, R12
MOVB R12, 0(DI)
INCQ SI
INCQ BX
INCQ DI
DECQ BP
JA xor_loop
done:
VMOVDQU X3, 48(AX)
VZEROUPPER
MOVQ R8, SP
MOVQ CX, ret+72(FP)
RET
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// +build 386,!gccgo,!appengine,!nacl
package chacha
import (
"encoding/binary"
"golang.org/x/sys/cpu"
)
func init() {
useSSE2 = cpu.X86.HasSSE2
useSSSE3 = cpu.X86.HasSSSE3
useAVX = false
useAVX2 = false
}
func initialize(state *[64]byte, key []byte, nonce *[16]byte) {
binary.LittleEndian.PutUint32(state[0:], sigma[0])
binary.LittleEndian.PutUint32(state[4:], sigma[1])
binary.LittleEndian.PutUint32(state[8:], sigma[2])
binary.LittleEndian.PutUint32(state[12:], sigma[3])
copy(state[16:], key[:])
copy(state[48:], nonce[:])
}
// This function is implemented in chacha_386.s
//go:noescape
func hChaCha20SSE2(out *[32]byte, nonce *[16]byte, key *[32]byte)
// This function is implemented in chacha_386.s
//go:noescape
func hChaCha20SSSE3(out *[32]byte, nonce *[16]byte, key *[32]byte)
// This function is implemented in chacha_386.s
//go:noescape
func xorKeyStreamSSE2(dst, src []byte, block, state *[64]byte, rounds int) int
func hChaCha20(out *[32]byte, nonce *[16]byte, key *[32]byte) {
switch {
case useSSSE3:
hChaCha20SSSE3(out, nonce, key)
case useSSE2:
hChaCha20SSE2(out, nonce, key)
default:
hChaCha20Generic(out, nonce, key)
}
}
func xorKeyStream(dst, src []byte, block, state *[64]byte, rounds int) int {
if useSSE2 {
return xorKeyStreamSSE2(dst, src, block, state, rounds)
} else {
return xorKeyStreamGeneric(dst, src, block, state, rounds)
}
}
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// +build 386,!gccgo,!appengine,!nacl
#include "const.s"
#include "macro.s"
// FINALIZE xors len bytes from src and block using
// the temp. registers t0 and t1 and writes the result
// to dst.
#define FINALIZE(dst, src, block, len, t0, t1) \
XORL t0, t0; \
XORL t1, t1; \
FINALIZE_LOOP:; \
MOVB 0(src), t0; \
MOVB 0(block), t1; \
XORL t0, t1; \
MOVB t1, 0(dst); \
INCL src; \
INCL block; \
INCL dst; \
DECL len; \
JG FINALIZE_LOOP \
#define Dst DI
#define Nonce AX
#define Key BX
#define Rounds DX
// func hChaCha20SSE2(out *[32]byte, nonce *[16]byte, key *[32]byte)
TEXT ·hChaCha20SSE2(SB), 4, $0-12
MOVL out+0(FP), Dst
MOVL nonce+4(FP), Nonce
MOVL key+8(FP), Key
MOVOU ·sigma<>(SB), X0
MOVOU 0*16(Key), X1
MOVOU 1*16(Key), X2
MOVOU 0*16(Nonce), X3
MOVL $20, Rounds
chacha_loop:
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
CHACHA_SHUFFLE_SSE(X1, X2, X3)
CHACHA_QROUND_SSE2(X0, X1, X2, X3, X4)
CHACHA_SHUFFLE_SSE(X3, X2, X1)
SUBL $2, Rounds
JNZ chacha_loop
MOVOU X0, 0*16(Dst)
MOVOU X3, 1*16(Dst)
RET
// func hChaCha20SSSE3(out *[32]byte, nonce *[16]byte, key *[32]byte)
TEXT ·hChaCha20SSSE3(SB), 4, $0-12
MOVL out+0(FP), Dst
MOVL nonce+4(FP), Nonce
MOVL key+8(FP), Key
MOVOU ·sigma<>(SB), X0
MOVOU 0*16(Key), X1
MOVOU 1*16(Key), X2
MOVOU 0*16(Nonce), X3
MOVL $20, Rounds
MOVOU ·rol16<>(SB), X5
MOVOU ·rol8<>(SB), X6
chacha_loop:
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, X5, X6)
CHACHA_SHUFFLE_SSE(X1, X2, X3)
CHACHA_QROUND_SSSE3(X0, X1, X2, X3, X4, X5, X6)
CHACHA_SHUFFLE_SSE(X3, X2, X1)
SUBL $2, Rounds
JNZ chacha_loop
MOVOU X0, 0*16(Dst)
MOVOU X3, 1*16(Dst)
RET
#undef Dst
#undef Nonce
#undef Key
#undef Rounds
#define State AX
#define Dst DI
#define Src SI
#define Len DX
#define Tmp0 BX
#define Tmp1 BP
// func xorKeyStreamSSE2(dst, src []byte, block, state *[64]byte, rounds int) int
TEXT ·xorKeyStreamSSE2(SB), 4, $0-40
MOVL dst_base+0(FP), Dst
MOVL src_base+12(FP), Src
MOVL state+28(FP), State
MOVL src_len+16(FP), Len
MOVL $0, ret+36(FP) // Number of bytes written to the keystream buffer - 0 iff len mod 64 == 0
MOVOU 0*16(State), X0
MOVOU 1*16(State), X1
MOVOU 2*16(State), X2
MOVOU 3*16(State), X3
TESTL Len, Len
JZ DONE
GENERATE_KEYSTREAM:
MOVO X0, X4
MOVO X1, X5
MOVO X2, X6
MOVO X3, X7
MOVL rounds+32(FP), Tmp0
CHACHA_LOOP:
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
CHACHA_SHUFFLE_SSE(X5, X6, X7)
CHACHA_QROUND_SSE2(X4, X5, X6, X7, X0)
CHACHA_SHUFFLE_SSE(X7, X6, X5)
SUBL $2, Tmp0
JA CHACHA_LOOP
MOVOU 0*16(State), X0 // Restore X0 from state
PADDL X0, X4
PADDL X1, X5
PADDL X2, X6
PADDL X3, X7
MOVOU ·one<>(SB), X0
PADDQ X0, X3
CMPL Len, $64
JL BUFFER_KEYSTREAM
XOR_SSE(Dst, Src, 0, X4, X5, X6, X7, X0)
MOVOU 0*16(State), X0 // Restore X0 from state
ADDL $64, Src
ADDL $64, Dst
SUBL $64, Len
JZ DONE
JMP GENERATE_KEYSTREAM // There is at least one more plaintext byte
BUFFER_KEYSTREAM:
MOVL block+24(FP), State
MOVOU X4, 0(State)
MOVOU X5, 16(State)
MOVOU X6, 32(State)
MOVOU X7, 48(State)
MOVL Len, ret+36(FP) // Number of bytes written to the keystream buffer - 0 < Len < 64
FINALIZE(Dst, Src, State, Len, Tmp0, Tmp1)
DONE:
MOVL state+28(FP), State
MOVOU X3, 3*16(State)
RET
#undef State
#undef Dst
#undef Src
#undef Len
#undef Tmp0
#undef Tmp1
// Copyright (c) 2017 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// +build go1.7,amd64,!gccgo,!appengine,!nacl
package chacha
import "golang.org/x/sys/cpu"
func init() {
useSSE2 = cpu.X86.HasSSE2
useSSSE3 = cpu.X86.HasSSSE3
useAVX = cpu.X86.HasAVX
useAVX2 = cpu.X86.HasAVX2
}
// This function is implemented in chacha_amd64.s
//go:noescape
func initialize(state *[64]byte, key []byte, nonce *[16]byte)
// This function is implemented in chacha_amd64.s
//go:noescape
func hChaCha20SSE2(out *[32]byte, nonce *[16]byte, key *[32]byte)
// This function is implemented in chacha_amd64.s
//go:noescape
func hChaCha20SSSE3(out *[32]byte, nonce *[16]byte, key *[32]byte)
// This function is implemented in chachaAVX2_amd64.s
//go:noescape
func hChaCha20AVX(out *[32]byte, nonce *[16]byte, key *[32]byte)
// This function is implemented in chacha_amd64.s
//go:noescape
func xorKeyStreamSSE2(dst, src []byte, block, state *[64]byte, rounds int) int
// This function is implemented in chacha_amd64.s
//go:noescape
func xorKeyStreamSSSE3(dst, src []byte, block, state *[64]byte, rounds int) int
// This function is implemented in chacha_amd64.s
//go:noescape
func xorKeyStreamAVX(dst, src []byte, block, state *[64]byte, rounds int) int
// This function is implemented in chachaAVX2_amd64.s
//go:noescape
func xorKeyStreamAVX2(dst, src []byte, block, state *[64]byte, rounds int) int
func hChaCha20(out *[32]byte, nonce *[16]byte, key *[32]byte) {
switch {
case useAVX:
hChaCha20AVX(out, nonce, key)
case useSSSE3:
hChaCha20SSSE3(out, nonce, key)
case useSSE2:
hChaCha20SSE2(out, nonce, key)
default:
hChaCha20Generic(out, nonce, key)
}
}
func xorKeyStream(dst, src []byte, block, state *[64]byte, rounds int) int {
switch {
case useAVX2:
return xorKeyStreamAVX2(dst, src, block, state, rounds)
case useAVX:
return xorKeyStreamAVX(dst, src, block, state, rounds)
case useSSSE3:
return xorKeyStreamSSSE3(dst, src, block, state, rounds)
case useSSE2:
return xorKeyStreamSSE2(dst, src, block, state, rounds)
default:
return xorKeyStreamGeneric(dst, src, block, state, rounds)
}
}
此差异已折叠。
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
package chacha
import "encoding/binary"
var sigma = [4]uint32{0x61707865, 0x3320646e, 0x79622d32, 0x6b206574}
func xorKeyStreamGeneric(dst, src []byte, block, state *[64]byte, rounds int) int {
for len(src) >= 64 {
chachaGeneric(block, state, rounds)
for i, v := range block {
dst[i] = src[i] ^ v
}
src = src[64:]
dst = dst[64:]
}
n := len(src)
if n > 0 {
chachaGeneric(block, state, rounds)
for i, v := range src {
dst[i] = v ^ block[i]
}
}
return n
}
func chachaGeneric(dst *[64]byte, state *[64]byte, rounds int) {
v00 := binary.LittleEndian.Uint32(state[0:])
v01 := binary.LittleEndian.Uint32(state[4:])
v02 := binary.LittleEndian.Uint32(state[8:])
v03 := binary.LittleEndian.Uint32(state[12:])
v04 := binary.LittleEndian.Uint32(state[16:])
v05 := binary.LittleEndian.Uint32(state[20:])
v06 := binary.LittleEndian.Uint32(state[24:])
v07 := binary.LittleEndian.Uint32(state[28:])
v08 := binary.LittleEndian.Uint32(state[32:])
v09 := binary.LittleEndian.Uint32(state[36:])
v10 := binary.LittleEndian.Uint32(state[40:])
v11 := binary.LittleEndian.Uint32(state[44:])
v12 := binary.LittleEndian.Uint32(state[48:])
v13 := binary.LittleEndian.Uint32(state[52:])
v14 := binary.LittleEndian.Uint32(state[56:])
v15 := binary.LittleEndian.Uint32(state[60:])
s00, s01, s02, s03, s04, s05, s06, s07 := v00, v01, v02, v03, v04, v05, v06, v07
s08, s09, s10, s11, s12, s13, s14, s15 := v08, v09, v10, v11, v12, v13, v14, v15
for i := 0; i < rounds; i += 2 {
v00 += v04
v12 ^= v00
v12 = (v12 << 16) | (v12 >> 16)
v08 += v12
v04 ^= v08
v04 = (v04 << 12) | (v04 >> 20)
v00 += v04
v12 ^= v00
v12 = (v12 << 8) | (v12 >> 24)
v08 += v12
v04 ^= v08
v04 = (v04 << 7) | (v04 >> 25)
v01 += v05
v13 ^= v01
v13 = (v13 << 16) | (v13 >> 16)
v09 += v13
v05 ^= v09
v05 = (v05 << 12) | (v05 >> 20)
v01 += v05
v13 ^= v01
v13 = (v13 << 8) | (v13 >> 24)
v09 += v13
v05 ^= v09
v05 = (v05 << 7) | (v05 >> 25)
v02 += v06
v14 ^= v02
v14 = (v14 << 16) | (v14 >> 16)
v10 += v14
v06 ^= v10
v06 = (v06 << 12) | (v06 >> 20)
v02 += v06
v14 ^= v02
v14 = (v14 << 8) | (v14 >> 24)
v10 += v14
v06 ^= v10
v06 = (v06 << 7) | (v06 >> 25)
v03 += v07
v15 ^= v03
v15 = (v15 << 16) | (v15 >> 16)
v11 += v15
v07 ^= v11
v07 = (v07 << 12) | (v07 >> 20)
v03 += v07
v15 ^= v03
v15 = (v15 << 8) | (v15 >> 24)
v11 += v15
v07 ^= v11
v07 = (v07 << 7) | (v07 >> 25)
v00 += v05
v15 ^= v00
v15 = (v15 << 16) | (v15 >> 16)
v10 += v15
v05 ^= v10
v05 = (v05 << 12) | (v05 >> 20)
v00 += v05
v15 ^= v00
v15 = (v15 << 8) | (v15 >> 24)
v10 += v15
v05 ^= v10
v05 = (v05 << 7) | (v05 >> 25)
v01 += v06
v12 ^= v01
v12 = (v12 << 16) | (v12 >> 16)
v11 += v12
v06 ^= v11
v06 = (v06 << 12) | (v06 >> 20)
v01 += v06
v12 ^= v01
v12 = (v12 << 8) | (v12 >> 24)
v11 += v12
v06 ^= v11
v06 = (v06 << 7) | (v06 >> 25)
v02 += v07
v13 ^= v02
v13 = (v13 << 16) | (v13 >> 16)
v08 += v13
v07 ^= v08
v07 = (v07 << 12) | (v07 >> 20)
v02 += v07
v13 ^= v02
v13 = (v13 << 8) | (v13 >> 24)
v08 += v13
v07 ^= v08
v07 = (v07 << 7) | (v07 >> 25)
v03 += v04
v14 ^= v03
v14 = (v14 << 16) | (v14 >> 16)
v09 += v14
v04 ^= v09
v04 = (v04 << 12) | (v04 >> 20)
v03 += v04
v14 ^= v03
v14 = (v14 << 8) | (v14 >> 24)
v09 += v14
v04 ^= v09
v04 = (v04 << 7) | (v04 >> 25)
}
v00 += s00
v01 += s01
v02 += s02
v03 += s03
v04 += s04
v05 += s05
v06 += s06
v07 += s07
v08 += s08
v09 += s09
v10 += s10
v11 += s11
v12 += s12
v13 += s13
v14 += s14
v15 += s15
s12++
binary.LittleEndian.PutUint32(state[48:], s12)
if s12 == 0 { // indicates overflow
s13++
binary.LittleEndian.PutUint32(state[52:], s13)
}
binary.LittleEndian.PutUint32(dst[0:], v00)
binary.LittleEndian.PutUint32(dst[4:], v01)
binary.LittleEndian.PutUint32(dst[8:], v02)
binary.LittleEndian.PutUint32(dst[12:], v03)
binary.LittleEndian.PutUint32(dst[16:], v04)
binary.LittleEndian.PutUint32(dst[20:], v05)
binary.LittleEndian.PutUint32(dst[24:], v06)
binary.LittleEndian.PutUint32(dst[28:], v07)
binary.LittleEndian.PutUint32(dst[32:], v08)
binary.LittleEndian.PutUint32(dst[36:], v09)
binary.LittleEndian.PutUint32(dst[40:], v10)
binary.LittleEndian.PutUint32(dst[44:], v11)
binary.LittleEndian.PutUint32(dst[48:], v12)
binary.LittleEndian.PutUint32(dst[52:], v13)
binary.LittleEndian.PutUint32(dst[56:], v14)
binary.LittleEndian.PutUint32(dst[60:], v15)
}
func hChaCha20Generic(out *[32]byte, nonce *[16]byte, key *[32]byte) {
v00 := sigma[0]
v01 := sigma[1]
v02 := sigma[2]
v03 := sigma[3]
v04 := binary.LittleEndian.Uint32(key[0:])
v05 := binary.LittleEndian.Uint32(key[4:])
v06 := binary.LittleEndian.Uint32(key[8:])
v07 := binary.LittleEndian.Uint32(key[12:])
v08 := binary.LittleEndian.Uint32(key[16:])
v09 := binary.LittleEndian.Uint32(key[20:])
v10 := binary.LittleEndian.Uint32(key[24:])
v11 := binary.LittleEndian.Uint32(key[28:])
v12 := binary.LittleEndian.Uint32(nonce[0:])
v13 := binary.LittleEndian.Uint32(nonce[4:])
v14 := binary.LittleEndian.Uint32(nonce[8:])
v15 := binary.LittleEndian.Uint32(nonce[12:])
for i := 0; i < 20; i += 2 {
v00 += v04
v12 ^= v00
v12 = (v12 << 16) | (v12 >> 16)
v08 += v12
v04 ^= v08
v04 = (v04 << 12) | (v04 >> 20)
v00 += v04
v12 ^= v00
v12 = (v12 << 8) | (v12 >> 24)
v08 += v12
v04 ^= v08
v04 = (v04 << 7) | (v04 >> 25)
v01 += v05
v13 ^= v01
v13 = (v13 << 16) | (v13 >> 16)
v09 += v13
v05 ^= v09
v05 = (v05 << 12) | (v05 >> 20)
v01 += v05
v13 ^= v01
v13 = (v13 << 8) | (v13 >> 24)
v09 += v13
v05 ^= v09
v05 = (v05 << 7) | (v05 >> 25)
v02 += v06
v14 ^= v02
v14 = (v14 << 16) | (v14 >> 16)
v10 += v14
v06 ^= v10
v06 = (v06 << 12) | (v06 >> 20)
v02 += v06
v14 ^= v02
v14 = (v14 << 8) | (v14 >> 24)
v10 += v14
v06 ^= v10
v06 = (v06 << 7) | (v06 >> 25)
v03 += v07
v15 ^= v03
v15 = (v15 << 16) | (v15 >> 16)
v11 += v15
v07 ^= v11
v07 = (v07 << 12) | (v07 >> 20)
v03 += v07
v15 ^= v03
v15 = (v15 << 8) | (v15 >> 24)
v11 += v15
v07 ^= v11
v07 = (v07 << 7) | (v07 >> 25)
v00 += v05
v15 ^= v00
v15 = (v15 << 16) | (v15 >> 16)
v10 += v15
v05 ^= v10
v05 = (v05 << 12) | (v05 >> 20)
v00 += v05
v15 ^= v00
v15 = (v15 << 8) | (v15 >> 24)
v10 += v15
v05 ^= v10
v05 = (v05 << 7) | (v05 >> 25)
v01 += v06
v12 ^= v01
v12 = (v12 << 16) | (v12 >> 16)
v11 += v12
v06 ^= v11
v06 = (v06 << 12) | (v06 >> 20)
v01 += v06
v12 ^= v01
v12 = (v12 << 8) | (v12 >> 24)
v11 += v12
v06 ^= v11
v06 = (v06 << 7) | (v06 >> 25)
v02 += v07
v13 ^= v02
v13 = (v13 << 16) | (v13 >> 16)
v08 += v13
v07 ^= v08
v07 = (v07 << 12) | (v07 >> 20)
v02 += v07
v13 ^= v02
v13 = (v13 << 8) | (v13 >> 24)
v08 += v13
v07 ^= v08
v07 = (v07 << 7) | (v07 >> 25)
v03 += v04
v14 ^= v03
v14 = (v14 << 16) | (v14 >> 16)
v09 += v14
v04 ^= v09
v04 = (v04 << 12) | (v04 >> 20)
v03 += v04
v14 ^= v03
v14 = (v14 << 8) | (v14 >> 24)
v09 += v14
v04 ^= v09
v04 = (v04 << 7) | (v04 >> 25)
}
binary.LittleEndian.PutUint32(out[0:], v00)
binary.LittleEndian.PutUint32(out[4:], v01)
binary.LittleEndian.PutUint32(out[8:], v02)
binary.LittleEndian.PutUint32(out[12:], v03)
binary.LittleEndian.PutUint32(out[16:], v12)
binary.LittleEndian.PutUint32(out[20:], v13)
binary.LittleEndian.PutUint32(out[24:], v14)
binary.LittleEndian.PutUint32(out[28:], v15)
}
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// +build !amd64,!386 gccgo appengine nacl
package chacha
import "encoding/binary"
func init() {
useSSE2 = false
useSSSE3 = false
useAVX = false
useAVX2 = false
}
func initialize(state *[64]byte, key []byte, nonce *[16]byte) {
binary.LittleEndian.PutUint32(state[0:], sigma[0])
binary.LittleEndian.PutUint32(state[4:], sigma[1])
binary.LittleEndian.PutUint32(state[8:], sigma[2])
binary.LittleEndian.PutUint32(state[12:], sigma[3])
copy(state[16:], key[:])
copy(state[48:], nonce[:])
}
func xorKeyStream(dst, src []byte, block, state *[64]byte, rounds int) int {
return xorKeyStreamGeneric(dst, src, block, state, rounds)
}
func hChaCha20(out *[32]byte, nonce *[16]byte, key *[32]byte) {
hChaCha20Generic(out, nonce, key)
}
// Copyright (c) 2018 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// +build 386,!gccgo,!appengine,!nacl amd64,!gccgo,!appengine,!nacl
#include "textflag.h"
DATA ·sigma<>+0x00(SB)/4, $0x61707865
DATA ·sigma<>+0x04(SB)/4, $0x3320646e
DATA ·sigma<>+0x08(SB)/4, $0x79622d32
DATA ·sigma<>+0x0C(SB)/4, $0x6b206574
GLOBL ·sigma<>(SB), (NOPTR+RODATA), $16 // The 4 ChaCha initialization constants
// SSE2/SSE3/AVX constants
DATA ·one<>+0x00(SB)/8, $1
DATA ·one<>+0x08(SB)/8, $0
GLOBL ·one<>(SB), (NOPTR+RODATA), $16 // The constant 1 as 128 bit value
DATA ·rol16<>+0x00(SB)/8, $0x0504070601000302
DATA ·rol16<>+0x08(SB)/8, $0x0D0C0F0E09080B0A
GLOBL ·rol16<>(SB), (NOPTR+RODATA), $16 // The PSHUFB 16 bit left rotate constant
DATA ·rol8<>+0x00(SB)/8, $0x0605040702010003
DATA ·rol8<>+0x08(SB)/8, $0x0E0D0C0F0A09080B
GLOBL ·rol8<>(SB), (NOPTR+RODATA), $16 // The PSHUFB 8 bit left rotate constant
// AVX2 constants
DATA ·one_AVX2<>+0x00(SB)/8, $0
DATA ·one_AVX2<>+0x08(SB)/8, $0
DATA ·one_AVX2<>+0x10(SB)/8, $1
DATA ·one_AVX2<>+0x18(SB)/8, $0
GLOBL ·one_AVX2<>(SB), (NOPTR+RODATA), $32 // The constant 1 as 256 bit value
DATA ·two_AVX2<>+0x00(SB)/8, $2
DATA ·two_AVX2<>+0x08(SB)/8, $0
DATA ·two_AVX2<>+0x10(SB)/8, $2
DATA ·two_AVX2<>+0x18(SB)/8, $0
GLOBL ·two_AVX2<>(SB), (NOPTR+RODATA), $32
DATA ·rol16_AVX2<>+0x00(SB)/8, $0x0504070601000302
DATA ·rol16_AVX2<>+0x08(SB)/8, $0x0D0C0F0E09080B0A
DATA ·rol16_AVX2<>+0x10(SB)/8, $0x0504070601000302
DATA ·rol16_AVX2<>+0x18(SB)/8, $0x0D0C0F0E09080B0A
GLOBL ·rol16_AVX2<>(SB), (NOPTR+RODATA), $32 // The VPSHUFB 16 bit left rotate constant
DATA ·rol8_AVX2<>+0x00(SB)/8, $0x0605040702010003
DATA ·rol8_AVX2<>+0x08(SB)/8, $0x0E0D0C0F0A09080B
DATA ·rol8_AVX2<>+0x10(SB)/8, $0x0605040702010003
DATA ·rol8_AVX2<>+0x18(SB)/8, $0x0E0D0C0F0A09080B
GLOBL ·rol8_AVX2<>(SB), (NOPTR+RODATA), $32 // The VPSHUFB 8 bit left rotate constant
// Copyright (c) 2018 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// +build 386,!gccgo,!appengine,!nacl amd64,!gccgo,!appengine,!nacl
// ROTL_SSE rotates all 4 32 bit values of the XMM register v
// left by n bits using SSE2 instructions (0 <= n <= 32).
// The XMM register t is used as a temp. register.
#define ROTL_SSE(n, t, v) \
MOVO v, t; \
PSLLL $n, t; \
PSRLL $(32-n), v; \
PXOR t, v
// ROTL_AVX rotates all 4/8 32 bit values of the AVX/AVX2 register v
// left by n bits using AVX/AVX2 instructions (0 <= n <= 32).
// The AVX/AVX2 register t is used as a temp. register.
#define ROTL_AVX(n, t, v) \
VPSLLD $n, v, t; \
VPSRLD $(32-n), v, v; \
VPXOR v, t, v
// CHACHA_QROUND_SSE2 performs a ChaCha quarter-round using the
// 4 XMM registers v0, v1, v2 and v3. It uses only ROTL_SSE2 for
// rotations. The XMM register t is used as a temp. register.
#define CHACHA_QROUND_SSE2(v0, v1, v2, v3, t) \
PADDL v1, v0; \
PXOR v0, v3; \
ROTL_SSE(16, t, v3); \
PADDL v3, v2; \
PXOR v2, v1; \
ROTL_SSE(12, t, v1); \
PADDL v1, v0; \
PXOR v0, v3; \
ROTL_SSE(8, t, v3); \
PADDL v3, v2; \
PXOR v2, v1; \
ROTL_SSE(7, t, v1)
// CHACHA_QROUND_SSSE3 performs a ChaCha quarter-round using the
// 4 XMM registers v0, v1, v2 and v3. It uses PSHUFB for 8/16 bit
// rotations. The XMM register t is used as a temp. register.
//
// r16 holds the PSHUFB constant for a 16 bit left rotate.
// r8 holds the PSHUFB constant for a 8 bit left rotate.
#define CHACHA_QROUND_SSSE3(v0, v1, v2, v3, t, r16, r8) \
PADDL v1, v0; \
PXOR v0, v3; \
PSHUFB r16, v3; \
PADDL v3, v2; \
PXOR v2, v1; \
ROTL_SSE(12, t, v1); \
PADDL v1, v0; \
PXOR v0, v3; \
PSHUFB r8, v3; \
PADDL v3, v2; \
PXOR v2, v1; \
ROTL_SSE(7, t, v1)
// CHACHA_QROUND_AVX performs a ChaCha quarter-round using the
// 4 AVX/AVX2 registers v0, v1, v2 and v3. It uses VPSHUFB for 8/16 bit
// rotations. The AVX/AVX2 register t is used as a temp. register.
//
// r16 holds the VPSHUFB constant for a 16 bit left rotate.
// r8 holds the VPSHUFB constant for a 8 bit left rotate.
#define CHACHA_QROUND_AVX(v0, v1, v2, v3, t, r16, r8) \
VPADDD v0, v1, v0; \
VPXOR v3, v0, v3; \
VPSHUFB r16, v3, v3; \
VPADDD v2, v3, v2; \
VPXOR v1, v2, v1; \
ROTL_AVX(12, t, v1); \
VPADDD v0, v1, v0; \
VPXOR v3, v0, v3; \
VPSHUFB r8, v3, v3; \
VPADDD v2, v3, v2; \
VPXOR v1, v2, v1; \
ROTL_AVX(7, t, v1)
// CHACHA_SHUFFLE_SSE performs a ChaCha shuffle using the
// 3 XMM registers v1, v2 and v3. The inverse shuffle is
// performed by switching v1 and v3: CHACHA_SHUFFLE_SSE(v3, v2, v1).
#define CHACHA_SHUFFLE_SSE(v1, v2, v3) \
PSHUFL $0x39, v1, v1; \
PSHUFL $0x4E, v2, v2; \
PSHUFL $0x93, v3, v3
// CHACHA_SHUFFLE_AVX performs a ChaCha shuffle using the
// 3 AVX/AVX2 registers v1, v2 and v3. The inverse shuffle is
// performed by switching v1 and v3: CHACHA_SHUFFLE_AVX(v3, v2, v1).
#define CHACHA_SHUFFLE_AVX(v1, v2, v3) \
VPSHUFD $0x39, v1, v1; \
VPSHUFD $0x4E, v2, v2; \
VPSHUFD $0x93, v3, v3
// XOR_SSE extracts 4x16 byte vectors from src at
// off, xors all vectors with the corresponding XMM
// register (v0 - v3) and writes the result to dst
// at off.
// The XMM register t is used as a temp. register.
#define XOR_SSE(dst, src, off, v0, v1, v2, v3, t) \
MOVOU 0+off(src), t; \
PXOR v0, t; \
MOVOU t, 0+off(dst); \
MOVOU 16+off(src), t; \
PXOR v1, t; \
MOVOU t, 16+off(dst); \
MOVOU 32+off(src), t; \
PXOR v2, t; \
MOVOU t, 32+off(dst); \
MOVOU 48+off(src), t; \
PXOR v3, t; \
MOVOU t, 48+off(dst)
// XOR_AVX extracts 4x16 byte vectors from src at
// off, xors all vectors with the corresponding AVX
// register (v0 - v3) and writes the result to dst
// at off.
// The XMM register t is used as a temp. register.
#define XOR_AVX(dst, src, off, v0, v1, v2, v3, t) \
VPXOR 0+off(src), v0, t; \
VMOVDQU t, 0+off(dst); \
VPXOR 16+off(src), v1, t; \
VMOVDQU t, 16+off(dst); \
VPXOR 32+off(src), v2, t; \
VMOVDQU t, 32+off(dst); \
VPXOR 48+off(src), v3, t; \
VMOVDQU t, 48+off(dst)
#define XOR_AVX2(dst, src, off, v0, v1, v2, v3, t0, t1) \
VMOVDQU (0+off)(src), t0; \
VPERM2I128 $32, v1, v0, t1; \
VPXOR t0, t1, t0; \
VMOVDQU t0, (0+off)(dst); \
VMOVDQU (32+off)(src), t0; \
VPERM2I128 $32, v3, v2, t1; \
VPXOR t0, t1, t0; \
VMOVDQU t0, (32+off)(dst); \
VMOVDQU (64+off)(src), t0; \
VPERM2I128 $49, v1, v0, t1; \
VPXOR t0, t1, t0; \
VMOVDQU t0, (64+off)(dst); \
VMOVDQU (96+off)(src), t0; \
VPERM2I128 $49, v3, v2, t1; \
VPXOR t0, t1, t0; \
VMOVDQU t0, (96+off)(dst)
#define XOR_UPPER_AVX2(dst, src, off, v0, v1, v2, v3, t0, t1) \
VMOVDQU (0+off)(src), t0; \
VPERM2I128 $32, v1, v0, t1; \
VPXOR t0, t1, t0; \
VMOVDQU t0, (0+off)(dst); \
VMOVDQU (32+off)(src), t0; \
VPERM2I128 $32, v3, v2, t1; \
VPXOR t0, t1, t0; \
VMOVDQU t0, (32+off)(dst); \
#define EXTRACT_LOWER(dst, v0, v1, v2, v3, t0) \
VPERM2I128 $49, v1, v0, t0; \
VMOVDQU t0, 0(dst); \
VPERM2I128 $49, v3, v2, t0; \
VMOVDQU t0, 32(dst)
// Copyright (c) 2016 Andreas Auernhammer. All rights reserved.
// Use of this source code is governed by a license that can be
// found in the LICENSE file.
// Package chacha20 implements the ChaCha20 / XChaCha20 stream chipher.
// Notice that one specific key-nonce combination must be unique for all time.
//
// There are three versions of ChaCha20:
// - ChaCha20 with a 64 bit nonce (en/decrypt up to 2^64 * 64 bytes for one key-nonce combination)
// - ChaCha20 with a 96 bit nonce (en/decrypt up to 2^32 * 64 bytes (~256 GB) for one key-nonce combination)
// - XChaCha20 with a 192 bit nonce (en/decrypt up to 2^64 * 64 bytes for one key-nonce combination)
package chacha20 // import "github.com/aead/chacha20"
import (
"crypto/cipher"
"github.com/aead/chacha20/chacha"
)
// XORKeyStream crypts bytes from src to dst using the given nonce and key.
// The length of the nonce determinds the version of ChaCha20:
// - 8 bytes: ChaCha20 with a 64 bit nonce and a 2^64 * 64 byte period.
// - 12 bytes: ChaCha20 as defined in RFC 7539 and a 2^32 * 64 byte period.
// - 24 bytes: XChaCha20 with a 192 bit nonce and a 2^64 * 64 byte period.
// Src and dst may be the same slice but otherwise should not overlap.
// If len(dst) < len(src) this function panics.
// If the nonce is neither 64, 96 nor 192 bits long, this function panics.
func XORKeyStream(dst, src, nonce, key []byte) {
chacha.XORKeyStream(dst, src, nonce, key, 20)
}
// NewCipher returns a new cipher.Stream implementing a ChaCha20 version.
// The nonce must be unique for one key for all time.
// The length of the nonce determinds the version of ChaCha20:
// - 8 bytes: ChaCha20 with a 64 bit nonce and a 2^64 * 64 byte period.
// - 12 bytes: ChaCha20 as defined in RFC 7539 and a 2^32 * 64 byte period.
// - 24 bytes: XChaCha20 with a 192 bit nonce and a 2^64 * 64 byte period.
// If the nonce is neither 64, 96 nor 192 bits long, a non-nil error is returned.
func NewCipher(nonce, key []byte) (cipher.Stream, error) {
return chacha.NewCipher(nonce, key, 20)
}
The MIT License (MIT)
Copyright (c) 2016 Richard Barnes
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
文件模式从 100644 更改为 100755
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册