implement expose service, add tests, fix #140

Implements a kompose specific docker compose label "kompose.service.expose" which can be used to expose the specified services externally. The accepted values are of type string.
If the value is set to "true", the provider sets the endpoint automatically, and for any other value, the value is set as the hostname. If multiple ports are defined in a service, the first one is chosen to be the exposed.

Unit tests, functional tests, glide updates and docs have also been added in this commit for the related feature.
This commit is contained in:
Shubham Minglani 2016-11-15 15:55:43 +05:30
parent 48e3ba88cd
commit 7e378cd546
174 changed files with 10380 additions and 32848 deletions

View File

@ -30,6 +30,7 @@ import (
// install OpenShift api // install OpenShift api
_ "github.com/openshift/origin/pkg/deploy/api/install" _ "github.com/openshift/origin/pkg/deploy/api/install"
_ "github.com/openshift/origin/pkg/image/api/install" _ "github.com/openshift/origin/pkg/image/api/install"
_ "github.com/openshift/origin/pkg/route/api/install"
"github.com/kubernetes-incubator/kompose/pkg/kobject" "github.com/kubernetes-incubator/kompose/pkg/kobject"
"github.com/kubernetes-incubator/kompose/pkg/loader" "github.com/kubernetes-incubator/kompose/pkg/loader"

View File

@ -281,19 +281,13 @@ WARN[0000] Unsupported key dockerfile - ignoring
## Labels ## Labels
`kompose` supports Kompose-specific labels within the `docker-compose.yml` file in order to explicitly imply a service type upon conversion. `kompose` supports Kompose-specific labels within the `docker-compose.yml` file in order to explicitly define a service's behavior upon conversion.
The currently supported options are:
| Key | Value |
|----------------------|-------------------------------------|
| kompose.service.type | nodeport / clusterip / loadbalancer |
- kompose.service.type defines the type of service to be created.
For example: For example:
```yaml ```yaml
---
version: "2" version: "2"
services: services:
nginx: nginx:
@ -307,6 +301,37 @@ services:
kompose.service.type: nodeport kompose.service.type: nodeport
``` ```
- kompose.service.expose defines if the service needs to be made accessible from outside the cluster or not. If the value is set to "true", the provider sets the endpoint automatically, and for any other value, the value is set as the hostname. If multiple ports are defined in a service, the first one is chosen to be the exposed.
- For the Kubernetes provider, an ingress resource is created and it is assumed that an ingress controller has already been configured.
- For the OpenShift provider, a route is created.
For example:
```yaml
version: "2"
services:
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
labels:
kompose.service.expose: "counter.example.com"
redis:
image: redis:3.0
ports:
- "6379"
```
The currently supported options are:
| Key | Value |
|----------------------|-------------------------------------|
| kompose.service.type | nodeport / clusterip / loadbalancer |
| kompose.service.expose| true / hostname |
## Restart ## Restart
If you want to create normal pods without controllers you can use `restart` construct of docker-compose to define that. Follow table below to see what heppens on the `restart` value. If you want to create normal pods without controllers you can use `restart` construct of docker-compose to define that. Follow table below to see what heppens on the `restart` value.

16
glide.lock generated
View File

@ -1,5 +1,5 @@
hash: 3caf221b3b3a35894b12799f8a5047107b1d5c9237bfea1706af24ea525f97e6 hash: a89b753597fba20c97e0ad6a0e3c840e0d2f98d6ac670f7c602c7327c35fe203
updated: 2016-12-16T16:41:13.456006508+05:30 updated: 2016-12-20T19:27:36.281252123+05:30
imports: imports:
- name: cloud.google.com/go - name: cloud.google.com/go
version: 3b1ae45394a234c385be014e9a488f2bb6eef821 version: 3b1ae45394a234c385be014e9a488f2bb6eef821
@ -210,7 +210,7 @@ imports:
- name: github.com/evanphx/json-patch - name: github.com/evanphx/json-patch
version: 465937c80b3c07a7c7ad20cc934898646a91c1de version: 465937c80b3c07a7c7ad20cc934898646a91c1de
- name: github.com/fatih/structs - name: github.com/fatih/structs
version: dc3312cb1a4513a366c4c9e622ad55c32df12ed3 version: be738c8546f55b34e60125afa50ed73a9a9c460e
- name: github.com/flynn/go-shlex - name: github.com/flynn/go-shlex
version: 3f9db97f856818214da2e1057f8ad84803971cff version: 3f9db97f856818214da2e1057f8ad84803971cff
- name: github.com/fsouza/go-dockerclient - name: github.com/fsouza/go-dockerclient
@ -371,6 +371,8 @@ imports:
- pkg/quota/api - pkg/quota/api
- pkg/quota/util - pkg/quota/util
- pkg/route/api - pkg/route/api
- pkg/route/api/install
- pkg/route/api/v1
- pkg/sdn/api - pkg/sdn/api
- pkg/security/api - pkg/security/api
- pkg/template/api - pkg/template/api
@ -396,7 +398,7 @@ imports:
- name: github.com/prometheus/procfs - name: github.com/prometheus/procfs
version: 454a56f35412459b5e684fd5ec0f9211b94f002a version: 454a56f35412459b5e684fd5ec0f9211b94f002a
- name: github.com/Sirupsen/logrus - name: github.com/Sirupsen/logrus
version: 881bee4e20a5d11a6a88a5667c6f292072ac1963 version: 4b6ea7319e214d98c938f12692336f7ca9348d6b
- name: github.com/spf13/cobra - name: github.com/spf13/cobra
version: 7c674d9e72017ed25f6d2b5e497a1368086b6a6f version: 7c674d9e72017ed25f6d2b5e497a1368086b6a6f
- name: github.com/spf13/pflag - name: github.com/spf13/pflag
@ -406,13 +408,13 @@ imports:
subpackages: subpackages:
- codec - codec
- name: github.com/urfave/cli - name: github.com/urfave/cli
version: 0bdeddeeb0f650497d603c4ad7b20cfe685682f6 version: 71f57d300dd6a780ac1856c005c4b518cfd498ec
- name: github.com/xeipuuv/gojsonpointer - name: github.com/xeipuuv/gojsonpointer
version: e0fe6f68307607d540ed8eac07a342c33fa1b54a version: e0fe6f68307607d540ed8eac07a342c33fa1b54a
- name: github.com/xeipuuv/gojsonreference - name: github.com/xeipuuv/gojsonreference
version: e02fc20de94c78484cd5ffb007f8af96be030a45 version: e02fc20de94c78484cd5ffb007f8af96be030a45
- name: github.com/xeipuuv/gojsonschema - name: github.com/xeipuuv/gojsonschema
version: 59f99ebfe5f712a0055e321231fc3be94e4e00b2 version: ac452913faa25c08bb78810d3e6f88b8a39f8f25
- name: golang.org/x/net - name: golang.org/x/net
version: e90d6d0afc4c315a0d87a568ae68577cc15149a0 version: e90d6d0afc4c315a0d87a568ae68577cc15149a0
subpackages: subpackages:
@ -436,7 +438,7 @@ imports:
- jws - jws
- jwt - jwt
- name: golang.org/x/sys - name: golang.org/x/sys
version: d75a52659825e75fff6158388dddc6a5b04f9ba5 version: 833a04a10549a95dc34458c195cbad61bbb6cb4d
subpackages: subpackages:
- unix - unix
- name: google.golang.org/appengine - name: google.golang.org/appengine

View File

@ -25,6 +25,8 @@ import:
- pkg/deploy/api/install - pkg/deploy/api/install
- pkg/image/api - pkg/image/api
- pkg/image/api/install - pkg/image/api/install
- pkg/route/api
- pkg/route/api/install
# OpenShift uses Kubernetes fork to carry some patches # OpenShift uses Kubernetes fork to carry some patches
# Kubernetes will be in the same version as what OpenShift is using (from OpenShifts Godeps.json) # Kubernetes will be in the same version as what OpenShift is using (from OpenShifts Godeps.json)

View File

@ -68,6 +68,7 @@ type ServiceConfig struct {
VolumesFrom []string `compose:"volumes_from",bundle:""` VolumesFrom []string `compose:"volumes_from",bundle:""`
ServiceType string `compose:"kompose.service.type",bundle:""` ServiceType string `compose:"kompose.service.type",bundle:""`
Build string `compose:"build",bundle:""` Build string `compose:"build",bundle:""`
ExposeService string `compose:"kompose.service.expose",bundle:""`
} }
// EnvVar holds the environment variable struct of a container // EnvVar holds the environment variable struct of a container

View File

@ -302,6 +302,8 @@ func (c *Compose) LoadFile(file string) kobject.KomposeObject {
switch key { switch key {
case "kompose.service.type": case "kompose.service.type":
serviceConfig.ServiceType = handleServiceType(value) serviceConfig.ServiceType = handleServiceType(value)
case "kompose.service.expose":
serviceConfig.ExposeService = strings.ToLower(value)
} }
} }

View File

@ -39,6 +39,7 @@ import (
deployapi "github.com/openshift/origin/pkg/deploy/api" deployapi "github.com/openshift/origin/pkg/deploy/api"
imageapi "github.com/openshift/origin/pkg/image/api" imageapi "github.com/openshift/origin/pkg/image/api"
routeapi "github.com/openshift/origin/pkg/route/api"
) )
/** /**
@ -201,7 +202,6 @@ func PrintList(objects []runtime.Object, opt kobject.ConvertOptions) error {
if err != nil { if err != nil {
return err return err
} }
switch t := v.(type) { switch t := v.(type) {
case *api.ReplicationController: case *api.ReplicationController:
file = transformer.Print(t.Name, dirName, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f) file = transformer.Print(t.Name, dirName, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f)
@ -219,6 +219,10 @@ func PrintList(objects []runtime.Object, opt kobject.ConvertOptions) error {
file = transformer.Print(t.Name, dirName, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f) file = transformer.Print(t.Name, dirName, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f)
case *api.Pod: case *api.Pod:
file = transformer.Print(t.Name, dirName, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f) file = transformer.Print(t.Name, dirName, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f)
case *routeapi.Route:
file = transformer.Print(t.Name, dirName, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f)
case *extensions.Ingress:
file = transformer.Print(t.Name, dirName, strings.ToLower(t.Kind), data, opt.ToStdout, opt.GenerateYaml, f)
} }
files = append(files, file) files = append(files, file)
} }

View File

@ -201,6 +201,45 @@ func (k *Kubernetes) InitDS(name string, service kobject.ServiceConfig) *extensi
return ds return ds
} }
func (k *Kubernetes) initIngress(name string, service kobject.ServiceConfig, port int32) *extensions.Ingress {
ingress := &extensions.Ingress{
TypeMeta: unversioned.TypeMeta{
Kind: "Ingress",
APIVersion: "extensions/v1beta1",
},
ObjectMeta: api.ObjectMeta{
Name: name,
},
Spec: extensions.IngressSpec{
Rules: []extensions.IngressRule{
{
IngressRuleValue: extensions.IngressRuleValue{
HTTP: &extensions.HTTPIngressRuleValue{
Paths: []extensions.HTTPIngressPath{
{
Backend: extensions.IngressBackend{
ServiceName: name,
ServicePort: intstr.IntOrString{
IntVal: port,
},
},
},
},
},
},
},
},
},
}
if service.ExposeService != "true" {
ingress.Spec.Rules[0].Host = service.ExposeService
}
return ingress
}
// Initialize PersistentVolumeClaim // Initialize PersistentVolumeClaim
func (k *Kubernetes) CreatePVC(name string, mode string) *api.PersistentVolumeClaim { func (k *Kubernetes) CreatePVC(name string, mode string) *api.PersistentVolumeClaim {
size, err := resource.ParseQuantity("100Mi") size, err := resource.ParseQuantity("100Mi")
@ -429,6 +468,10 @@ func (k *Kubernetes) Transform(komposeObject kobject.KomposeObject, opt kobject.
if k.PortsExist(name, service) { if k.PortsExist(name, service) {
svc := k.CreateService(name, service, objects) svc := k.CreateService(name, service, objects)
objects = append(objects, svc) objects = append(objects, svc)
if service.ExposeService != "" {
objects = append(objects, k.initIngress(name, service, svc.Spec.Ports[0].Port))
}
} }
} }
@ -527,6 +570,12 @@ func (k *Kubernetes) Deploy(komposeObject kobject.KomposeObject, opt kobject.Con
return err return err
} }
logrus.Infof("Successfully created PersistentVolumeClaim: %s", t.Name) logrus.Infof("Successfully created PersistentVolumeClaim: %s", t.Name)
case *extensions.Ingress:
_, err := client.Ingress(namespace).Create(t)
if err != nil {
return err
}
logrus.Infof("Successfully created Ingress: %s", t.Name)
} }
} }
@ -585,8 +634,21 @@ func (k *Kubernetes) Undeploy(komposeObject kobject.KomposeObject, opt kobject.C
} else { } else {
logrus.Infof("Successfully deleted PersistentVolumeClaim: %s", t.Name) logrus.Infof("Successfully deleted PersistentVolumeClaim: %s", t.Name)
} }
case *extensions.Ingress:
// delete ingress
ingDeleteOptions := &api.DeleteOptions{
TypeMeta: unversioned.TypeMeta{
Kind: "Ingress",
APIVersion: "extensions/v1beta1",
},
}
err = client.Ingress(namespace).Delete(t.Name, ingDeleteOptions)
if err != nil {
return err
} else {
logrus.Infof("Successfully deleted Ingress: %s", t.Name)
}
} }
} }
return nil return nil
} }

View File

@ -197,6 +197,62 @@ func checkMeta(config kobject.ServiceConfig, meta api.ObjectMeta, expectedName s
return nil return nil
} }
func TestKomposeConvertIngress(t *testing.T) {
testCases := map[string]struct {
komposeObject kobject.KomposeObject
opt kobject.ConvertOptions
labelValue string
}{
"Convert to Ingress: label set to true": {newKomposeObject(), kobject.ConvertOptions{CreateD: true}, "true"},
"Convert to Ingress: label set to example.com": {newKomposeObject(), kobject.ConvertOptions{CreateD: true}, "example.com"},
}
for name, test := range testCases {
var expectedHost string
t.Log("Test case:", name)
k := Kubernetes{}
appName := "app"
// Setting value for ExposeService in ServiceConfig
config := test.komposeObject.ServiceConfigs[appName]
config.ExposeService = test.labelValue
test.komposeObject.ServiceConfigs[appName] = config
switch test.labelValue {
case "true":
expectedHost = ""
default:
expectedHost = test.labelValue
}
// Run Transform
objs := k.Transform(test.komposeObject, test.opt)
// Check results
for _, obj := range objs {
if ing, ok := obj.(*extensions.Ingress); ok {
if ing.ObjectMeta.Name != appName {
t.Errorf("Expected ObjectMeta.Name to be %s, got %s instead", appName, ing.ObjectMeta.Name)
}
if ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServiceName != appName {
t.Errorf("Expected Backend.ServiceName to be %s, got %s instead", appName, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServiceName)
}
if ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServicePort.IntVal != config.Port[0].HostPort {
t.Errorf("Expected Backend.ServicePort to be %d, got %v instead", config.Port[0].HostPort, ing.Spec.Rules[0].IngressRuleValue.HTTP.Paths[0].Backend.ServicePort.IntVal)
}
if ing.Spec.Rules[0].Host != expectedHost {
t.Errorf("Expected Rules[0].Host to be %s, got %s instead", expectedHost, ing.Spec.Rules[0].Host)
}
}
}
}
}
func TestKomposeConvert(t *testing.T) { func TestKomposeConvert(t *testing.T) {
replicas := 3 replicas := 3
testCases := map[string]struct { testCases := map[string]struct {

View File

@ -38,7 +38,9 @@ import (
deployapi "github.com/openshift/origin/pkg/deploy/api" deployapi "github.com/openshift/origin/pkg/deploy/api"
deploymentconfigreaper "github.com/openshift/origin/pkg/deploy/cmd" deploymentconfigreaper "github.com/openshift/origin/pkg/deploy/cmd"
imageapi "github.com/openshift/origin/pkg/image/api" imageapi "github.com/openshift/origin/pkg/image/api"
routeapi "github.com/openshift/origin/pkg/route/api"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/util/intstr"
) )
type OpenShift struct { type OpenShift struct {
@ -156,6 +158,34 @@ func (o *OpenShift) initDeploymentConfig(name string, service kobject.ServiceCon
return dc return dc
} }
func (o *OpenShift) initRoute(name string, service kobject.ServiceConfig, port int32) *routeapi.Route {
route := &routeapi.Route{
TypeMeta: unversioned.TypeMeta{
Kind: "Route",
APIVersion: "v1",
},
ObjectMeta: api.ObjectMeta{
Name: name,
},
Spec: routeapi.RouteSpec{
Port: &routeapi.RoutePort{
TargetPort: intstr.IntOrString{
IntVal: port,
},
},
To: routeapi.RouteTargetReference{
Kind: "Service",
Name: name,
},
},
}
if service.ExposeService != "true" {
route.Spec.Host = service.ExposeService
}
return route
}
// Transform maps komposeObject to openshift objects // Transform maps komposeObject to openshift objects
// returns objects that are already sorted in the way that Services are first // returns objects that are already sorted in the way that Services are first
func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object { func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.ConvertOptions) []runtime.Object {
@ -186,6 +216,10 @@ func (o *OpenShift) Transform(komposeObject kobject.KomposeObject, opt kobject.C
if o.PortsExist(name, service) { if o.PortsExist(name, service) {
svc := o.CreateService(name, service, objects) svc := o.CreateService(name, service, objects)
objects = append(objects, svc) objects = append(objects, svc)
if service.ExposeService != "" {
objects = append(objects, o.initRoute(name, service, svc.Spec.Ports[0].Port))
}
} }
} }
o.UpdateKubernetesObjects(name, service, &objects) o.UpdateKubernetesObjects(name, service, &objects)
@ -257,6 +291,12 @@ func (o *OpenShift) Deploy(komposeObject kobject.KomposeObject, opt kobject.Conv
return err return err
} }
logrus.Infof("Successfully created PersistentVolumeClaim: %s", t.Name) logrus.Infof("Successfully created PersistentVolumeClaim: %s", t.Name)
case *routeapi.Route:
_, err := oclient.Routes(namespace).Create(t)
if err != nil {
return err
}
logrus.Infof("Successfully created Route: %s", t.Name)
} }
} }
@ -323,6 +363,14 @@ func (o *OpenShift) Undeploy(komposeObject kobject.KomposeObject, opt kobject.Co
} else { } else {
logrus.Infof("Successfully deleted PersistentVolumeClaim: %s", t.Name) logrus.Infof("Successfully deleted PersistentVolumeClaim: %s", t.Name)
} }
case *routeapi.Route:
// delete route
err = oclient.Routes(namespace).Delete(t.Name)
if err != nil {
return err
} else {
logrus.Infof("Successfully deleted Route: %s", t.Name)
}
} }
} }
return nil return nil

View File

@ -61,3 +61,34 @@ func TestInitDeploymentConfig(t *testing.T) {
t.Errorf("Expected myfoobarname for name, actual %s", spec.Spec.Triggers[1].ImageChangeParams.ContainerNames[0]) t.Errorf("Expected myfoobarname for name, actual %s", spec.Spec.Triggers[1].ImageChangeParams.ContainerNames[0])
} }
} }
func TestKomposeConvertRoute(t *testing.T) {
o := OpenShift{}
name := "app"
sc := newServiceConfig()
sc.ExposeService = "true"
var port int32 = 5555
route := o.initRoute(name, sc, port)
if route.ObjectMeta.Name != name {
t.Errorf("Expected %s for name, actual %s", name, route.ObjectMeta.Name)
}
if route.Spec.To.Name != name {
t.Errorf("Expected %s for name, actual %s", name, route.Spec.To.Name)
}
if route.Spec.Port.TargetPort.IntVal != port {
t.Errorf("Expected %d for port, actual %d", port, route.Spec.Port.TargetPort.IntVal)
}
if route.Spec.Host != "" {
t.Errorf("Expected Spec.Host to not be set, got %s instead", route.Spec.Host)
}
sc.ExposeService = "example.com"
route = o.initRoute(name, sc, port)
if route.Spec.Host != sc.ExposeService {
t.Errorf("Expected %s for Spec.Host, actual %s", sc.ExposeService, route.Spec.Host)
}
}

View File

@ -119,6 +119,28 @@ convert::expect_success "kompose --file $KOMPOSE_ROOT/script/test/fixtures/keyon
unset $(cat $KOMPOSE_ROOT/script/test/fixtures/keyonly-envs/envs | cut -d'=' -f1) unset $(cat $KOMPOSE_ROOT/script/test/fixtures/keyonly-envs/envs | cut -d'=' -f1)
# Test related to kompose.expose.service label in docker compose file to ensure that services are exposed properly
#kubernetes tests
# when kompose.service.expose="True"
convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-true.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/kubernetes-expose-true.json"
# when kompose.expose.service="<hostname>"
convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-hostname.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/kubernetes-expose-hostname.json"
# when kompose.service.expose="True" and multiple ports in docker compose file (first port should be selected)
convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-true-multiple-ports.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/kubernetes-expose-true-multiple-ports.json"
# when kompose.service.expose="<hostname>" and multiple ports in docker compose file (first port should be selected)
convert::expect_success "kompose -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-hostname-multiple-ports.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/kubernetes-expose-hostname-multiple-ports.json"
#openshift tests
# when kompose.service.expose="True"
convert::expect_success "kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-true.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/openshift-expose-true.json"
# when kompose.expose.service="<hostname>"
convert::expect_success "kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-hostname.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/openshift-expose-hostname.json"
# when kompose.service.expose="True" and multiple ports in docker compose file (first port should be selected)
convert::expect_success "kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-true-multiple-ports.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/openshift-expose-true-multiple-ports.json"
# when kompose.service.expose="<hostname>" and multiple ports in docker compose file (first port should be selected)
convert::expect_success "kompose --provider openshift -f $KOMPOSE_ROOT/script/test/fixtures/expose-service/compose-files/docker-compose-expose-hostname-multiple-ports.yml convert --stdout" "$KOMPOSE_ROOT/script/test/fixtures/expose-service/provider-files/openshift-expose-hostname-multiple-ports.json"
###### ######
# Test the output file behavior of kompose convert # Test the output file behavior of kompose convert
# Default behavior without -o # Default behavior without -o

View File

@ -0,0 +1,13 @@
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
- "4000:4000"
links:
- redis
labels:
kompose.service.expose: "batman.example.com"
redis:
image: redis:3.0
ports:
- "6379"

View File

@ -0,0 +1,12 @@
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
labels:
kompose.service.expose: "batman.example.com"
redis:
image: redis:3.0
ports:
- "6379"

View File

@ -0,0 +1,13 @@
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
- "4000:4000"
links:
- redis
labels:
kompose.service.expose: "True"
redis:
image: redis:3.0
ports:
- "6379"

View File

@ -0,0 +1,12 @@
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
labels:
kompose.service.expose: "True"
redis:
image: redis:3.0
ports:
- "6379"

View File

@ -0,0 +1,179 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"protocol": "TCP",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "batman.example.com"
}
},
"spec": {
"ports": [
{
"name": "5000",
"protocol": "TCP",
"port": 5000,
"targetPort": 5000
},
{
"name": "4000",
"protocol": "TCP",
"port": 4000,
"targetPort": 4000
}
],
"selector": {
"service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "redis",
"creationTimestamp": null
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": "redis:3.0",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"annotations": {
"kompose.service.expose": "batman.example.com"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": "tuna/docker-counter23",
"ports": [
{
"containerPort": 5000,
"protocol": "TCP"
},
{
"containerPort": 4000,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Ingress",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"rules": [
{
"host": "batman.example.com",
"http": {
"paths": [
{
"backend": {
"serviceName": "web",
"servicePort": 5000
}
}
]
}
}
]
},
"status": {
"loadBalancer": {}
}
}
]
}

View File

@ -0,0 +1,169 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "batman.example.com"
}
},
"spec": {
"ports": [
{
"name": "5000",
"protocol": "TCP",
"port": 5000,
"targetPort": 5000
}
],
"selector": {
"service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"protocol": "TCP",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"annotations": {
"kompose.service.expose": "batman.example.com"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": "tuna/docker-counter23",
"ports": [
{
"containerPort": 5000,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Ingress",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"rules": [
{
"host": "batman.example.com",
"http": {
"paths": [
{
"backend": {
"serviceName": "web",
"servicePort": 5000
}
}
]
}
}
]
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "redis",
"creationTimestamp": null
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": "redis:3.0",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
}
]
}

View File

@ -0,0 +1,178 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"protocol": "TCP",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "True"
}
},
"spec": {
"ports": [
{
"name": "5000",
"protocol": "TCP",
"port": 5000,
"targetPort": 5000
},
{
"name": "4000",
"protocol": "TCP",
"port": 4000,
"targetPort": 4000
}
],
"selector": {
"service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "redis",
"creationTimestamp": null
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": "redis:3.0",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"annotations": {
"kompose.service.expose": "True"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": "tuna/docker-counter23",
"ports": [
{
"containerPort": 5000,
"protocol": "TCP"
},
{
"containerPort": 4000,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Ingress",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"rules": [
{
"http": {
"paths": [
{
"backend": {
"serviceName": "web",
"servicePort": 5000
}
}
]
}
}
]
},
"status": {
"loadBalancer": {}
}
}
]
}

View File

@ -0,0 +1,168 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"protocol": "TCP",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "True"
}
},
"spec": {
"ports": [
{
"name": "5000",
"protocol": "TCP",
"port": 5000,
"targetPort": 5000
}
],
"selector": {
"service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "redis",
"creationTimestamp": null
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": "redis:3.0",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Deployment",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"annotations": {
"kompose.service.expose": "True"
}
},
"spec": {
"replicas": 1,
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": "tuna/docker-counter23",
"ports": [
{
"containerPort": 5000,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
},
"strategy": {}
},
"status": {}
},
{
"kind": "Ingress",
"apiVersion": "extensions/v1beta1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"rules": [
{
"http": {
"paths": [
{
"backend": {
"serviceName": "web",
"servicePort": 5000
}
}
]
}
}
]
},
"status": {
"loadBalancer": {}
}
}
]
}

View File

@ -0,0 +1,277 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "batman.example.com"
}
},
"spec": {
"ports": [
{
"name": "5000",
"protocol": "TCP",
"port": 5000,
"targetPort": 5000
},
{
"name": "4000",
"protocol": "TCP",
"port": 4000,
"targetPort": 4000
}
],
"selector": {
"service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"protocol": "TCP",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "batman.example.com"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"web"
],
"from": {
"kind": "ImageStreamTag",
"name": "web:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"service": "web"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": " ",
"ports": [
{
"containerPort": 5000,
"protocol": "TCP"
},
{
"containerPort": 4000,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "tuna/docker-counter23"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "Route",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"host": "batman.example.com",
"to": {
"kind": "Service",
"name": "web",
"weight": null
},
"port": {
"targetPort": 5000
}
},
"status": {
"ingress": null
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"redis"
],
"from": {
"kind": "ImageStreamTag",
"name": "redis:3.0"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"service": "redis"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": " ",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null
},
"spec": {
"tags": [
{
"name": "3.0",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "redis:3.0"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
}
]
}

View File

@ -0,0 +1,267 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"protocol": "TCP",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "batman.example.com"
}
},
"spec": {
"ports": [
{
"name": "5000",
"protocol": "TCP",
"port": 5000,
"targetPort": 5000
}
],
"selector": {
"service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"redis"
],
"from": {
"kind": "ImageStreamTag",
"name": "redis:3.0"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"service": "redis"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": " ",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null
},
"spec": {
"tags": [
{
"name": "3.0",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "redis:3.0"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "batman.example.com"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"web"
],
"from": {
"kind": "ImageStreamTag",
"name": "web:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"service": "web"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": " ",
"ports": [
{
"containerPort": 5000,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "tuna/docker-counter23"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "Route",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"host": "batman.example.com",
"to": {
"kind": "Service",
"name": "web",
"weight": null
},
"port": {
"targetPort": 5000
}
},
"status": {
"ingress": null
}
}
]
}

View File

@ -0,0 +1,277 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"protocol": "TCP",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "True"
}
},
"spec": {
"ports": [
{
"name": "5000",
"protocol": "TCP",
"port": 5000,
"targetPort": 5000
},
{
"name": "4000",
"protocol": "TCP",
"port": 4000,
"targetPort": 4000
}
],
"selector": {
"service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"redis"
],
"from": {
"kind": "ImageStreamTag",
"name": "redis:3.0"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"service": "redis"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": " ",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null
},
"spec": {
"tags": [
{
"name": "3.0",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "redis:3.0"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "True"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"web"
],
"from": {
"kind": "ImageStreamTag",
"name": "web:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"service": "web"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": " ",
"ports": [
{
"containerPort": 5000,
"protocol": "TCP"
},
{
"containerPort": 4000,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "tuna/docker-counter23"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "Route",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"host": "",
"to": {
"kind": "Service",
"name": "web",
"weight": null
},
"port": {
"targetPort": 5000
}
},
"status": {
"ingress": null
}
}
]
}

View File

@ -0,0 +1,267 @@
{
"kind": "List",
"apiVersion": "v1",
"metadata": {},
"items": [
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"ports": [
{
"name": "6379",
"protocol": "TCP",
"port": 6379,
"targetPort": 6379
}
],
"selector": {
"service": "redis"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "Service",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "True"
}
},
"spec": {
"ports": [
{
"name": "5000",
"protocol": "TCP",
"port": 5000,
"targetPort": 5000
}
],
"selector": {
"service": "web"
}
},
"status": {
"loadBalancer": {}
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"redis"
],
"from": {
"kind": "ImageStreamTag",
"name": "redis:3.0"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"service": "redis"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "redis"
}
},
"spec": {
"containers": [
{
"name": "redis",
"image": " ",
"ports": [
{
"containerPort": 6379,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "redis",
"creationTimestamp": null
},
"spec": {
"tags": [
{
"name": "3.0",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "redis:3.0"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "DeploymentConfig",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null,
"labels": {
"service": "web"
},
"annotations": {
"kompose.service.expose": "True"
}
},
"spec": {
"strategy": {
"resources": {}
},
"triggers": [
{
"type": "ConfigChange"
},
{
"type": "ImageChange",
"imageChangeParams": {
"automatic": true,
"containerNames": [
"web"
],
"from": {
"kind": "ImageStreamTag",
"name": "web:latest"
}
}
}
],
"replicas": 1,
"test": false,
"selector": {
"service": "web"
},
"template": {
"metadata": {
"creationTimestamp": null,
"labels": {
"service": "web"
}
},
"spec": {
"containers": [
{
"name": "web",
"image": " ",
"ports": [
{
"containerPort": 5000,
"protocol": "TCP"
}
],
"resources": {}
}
],
"restartPolicy": "Always"
}
}
},
"status": {}
},
{
"kind": "ImageStream",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"tags": [
{
"name": "latest",
"annotations": null,
"from": {
"kind": "DockerImage",
"name": "tuna/docker-counter23"
},
"generation": null,
"importPolicy": {}
}
]
},
"status": {
"dockerImageRepository": ""
}
},
{
"kind": "Route",
"apiVersion": "v1",
"metadata": {
"name": "web",
"creationTimestamp": null
},
"spec": {
"host": "",
"to": {
"kind": "Service",
"name": "web",
"weight": null
},
"port": {
"targetPort": 5000
}
},
"status": {
"ingress": null
}
}
]
}

View File

@ -1,64 +0,0 @@
package logrus
// The following code was sourced and modified from the
// https://bitbucket.org/tebeka/atexit package governed by the following license:
//
// Copyright (c) 2012 Miki Tebeka <miki.tebeka@gmail.com>.
//
// 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.
import (
"fmt"
"os"
)
var handlers = []func(){}
func runHandler(handler func()) {
defer func() {
if err := recover(); err != nil {
fmt.Fprintln(os.Stderr, "Error: Logrus exit handler error:", err)
}
}()
handler()
}
func runHandlers() {
for _, handler := range handlers {
runHandler(handler)
}
}
// Exit runs all the Logrus atexit handlers and then terminates the program using os.Exit(code)
func Exit(code int) {
runHandlers()
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.
//
// 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 RegisterExitHandler(handler func()) {
handlers = append(handlers, handler)
}

View File

@ -3,21 +3,11 @@ package logrus
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io"
"os" "os"
"sync"
"time" "time"
) )
var bufferPool *sync.Pool
func init() {
bufferPool = &sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
}
// Defines the key when adding errors using WithError. // Defines the key when adding errors using WithError.
var ErrorKey = "error" var ErrorKey = "error"
@ -39,9 +29,6 @@ type Entry struct {
// Message passed to Debug, Info, Warn, Error, Fatal or Panic // Message passed to Debug, Info, Warn, Error, Fatal or Panic
Message string Message string
// When formatter is called in entry.log(), an Buffer may be set to entry
Buffer *bytes.Buffer
} }
func NewEntry(logger *Logger) *Entry { func NewEntry(logger *Logger) *Entry {
@ -52,15 +39,21 @@ func NewEntry(logger *Logger) *Entry {
} }
} }
// Returns a reader for the entry, which is a proxy to the formatter.
func (entry *Entry) Reader() (*bytes.Buffer, error) {
serialized, err := entry.Logger.Formatter.Format(entry)
return bytes.NewBuffer(serialized), err
}
// Returns the string representation from the reader and ultimately the // Returns the string representation from the reader and ultimately the
// formatter. // formatter.
func (entry *Entry) String() (string, error) { func (entry *Entry) String() (string, error) {
serialized, err := entry.Logger.Formatter.Format(entry) reader, err := entry.Reader()
if err != nil { if err != nil {
return "", err return "", err
} }
str := string(serialized)
return str, nil return reader.String(), err
} }
// Add an error as single field (using the key defined in ErrorKey) to the Entry. // Add an error as single field (using the key defined in ErrorKey) to the Entry.
@ -88,7 +81,6 @@ func (entry *Entry) WithFields(fields Fields) *Entry {
// This function is not declared with a pointer value because otherwise // This function is not declared with a pointer value because otherwise
// race conditions will occur when using multiple goroutines // race conditions will occur when using multiple goroutines
func (entry Entry) log(level Level, msg string) { func (entry Entry) log(level Level, msg string) {
var buffer *bytes.Buffer
entry.Time = time.Now() entry.Time = time.Now()
entry.Level = level entry.Level = level
entry.Message = msg entry.Message = msg
@ -98,23 +90,20 @@ func (entry Entry) log(level Level, msg string) {
fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err) fmt.Fprintf(os.Stderr, "Failed to fire hook: %v\n", err)
entry.Logger.mu.Unlock() entry.Logger.mu.Unlock()
} }
buffer = bufferPool.Get().(*bytes.Buffer)
buffer.Reset() reader, err := entry.Reader()
defer bufferPool.Put(buffer)
entry.Buffer = buffer
serialized, err := entry.Logger.Formatter.Format(&entry)
entry.Buffer = nil
if err != nil { if err != nil {
entry.Logger.mu.Lock() entry.Logger.mu.Lock()
fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err) fmt.Fprintf(os.Stderr, "Failed to obtain reader, %v\n", err)
entry.Logger.mu.Unlock() entry.Logger.mu.Unlock()
} else { }
entry.Logger.mu.Lock()
_, err = entry.Logger.Out.Write(serialized) entry.Logger.mu.Lock()
if err != nil { defer entry.Logger.mu.Unlock()
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
} _, err = io.Copy(entry.Logger.Out, reader)
entry.Logger.mu.Unlock() if err != nil {
fmt.Fprintf(os.Stderr, "Failed to write to log, %v\n", err)
} }
// To avoid Entry#log() returning a value that only would make sense for // To avoid Entry#log() returning a value that only would make sense for
@ -161,7 +150,7 @@ func (entry *Entry) Fatal(args ...interface{}) {
if entry.Logger.Level >= FatalLevel { if entry.Logger.Level >= FatalLevel {
entry.log(FatalLevel, fmt.Sprint(args...)) entry.log(FatalLevel, fmt.Sprint(args...))
} }
Exit(1) os.Exit(1)
} }
func (entry *Entry) Panic(args ...interface{}) { func (entry *Entry) Panic(args ...interface{}) {
@ -209,7 +198,7 @@ func (entry *Entry) Fatalf(format string, args ...interface{}) {
if entry.Logger.Level >= FatalLevel { if entry.Logger.Level >= FatalLevel {
entry.Fatal(fmt.Sprintf(format, args...)) entry.Fatal(fmt.Sprintf(format, args...))
} }
Exit(1) os.Exit(1)
} }
func (entry *Entry) Panicf(format string, args ...interface{}) { func (entry *Entry) Panicf(format string, args ...interface{}) {
@ -256,7 +245,7 @@ func (entry *Entry) Fatalln(args ...interface{}) {
if entry.Logger.Level >= FatalLevel { if entry.Logger.Level >= FatalLevel {
entry.Fatal(entry.sprintlnn(args...)) entry.Fatal(entry.sprintlnn(args...))
} }
Exit(1) os.Exit(1)
} }
func (entry *Entry) Panicln(args ...interface{}) { func (entry *Entry) Panicln(args ...interface{}) {

View File

@ -31,15 +31,18 @@ type Formatter interface {
// It's not exported because it's still using Data in an opinionated way. It's to // It's not exported because it's still using Data in an opinionated way. It's to
// avoid code duplication between the two default formatters. // avoid code duplication between the two default formatters.
func prefixFieldClashes(data Fields) { func prefixFieldClashes(data Fields) {
if t, ok := data["time"]; ok { _, ok := data["time"]
data["fields.time"] = t if ok {
data["fields.time"] = data["time"]
} }
if m, ok := data["msg"]; ok { _, ok = data["msg"]
data["fields.msg"] = m if ok {
data["fields.msg"] = data["msg"]
} }
if l, ok := data["level"]; ok { _, ok = data["level"]
data["fields.level"] = l if ok {
data["fields.level"] = data["level"]
} }
} }

View File

@ -5,40 +5,9 @@ import (
"fmt" "fmt"
) )
type fieldKey string
type FieldMap map[fieldKey]string
const (
FieldKeyMsg = "msg"
FieldKeyLevel = "level"
FieldKeyTime = "time"
)
func (f FieldMap) resolve(key fieldKey) string {
if k, ok := f[key]; ok {
return k
}
return string(key)
}
type JSONFormatter struct { type JSONFormatter struct {
// TimestampFormat sets the format used for marshaling timestamps. // TimestampFormat sets the format used for marshaling timestamps.
TimestampFormat string TimestampFormat string
// DisableTimestamp allows disabling automatic timestamps in output
DisableTimestamp bool
// FieldMap allows users to customize the names of keys for various fields.
// As an example:
// formatter := &JSONFormatter{
// FieldMap: FieldMap{
// FieldKeyTime: "@timestamp",
// FieldKeyLevel: "@level",
// FieldKeyLevel: "@message",
// },
// }
FieldMap FieldMap
} }
func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) { func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
@ -60,11 +29,9 @@ func (f *JSONFormatter) Format(entry *Entry) ([]byte, error) {
timestampFormat = DefaultTimestampFormat timestampFormat = DefaultTimestampFormat
} }
if !f.DisableTimestamp { data["time"] = entry.Time.Format(timestampFormat)
data[f.FieldMap.resolve(FieldKeyTime)] = entry.Time.Format(timestampFormat) data["msg"] = entry.Message
} data["level"] = entry.Level.String()
data[f.FieldMap.resolve(FieldKeyMsg)] = entry.Message
data[f.FieldMap.resolve(FieldKeyLevel)] = entry.Level.String()
serialized, err := json.Marshal(data) serialized, err := json.Marshal(data)
if err != nil { if err != nil {

View File

@ -26,31 +26,8 @@ type Logger struct {
// to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be // to) `logrus.Info`, which allows Info(), Warn(), Error() and Fatal() to be
// logged. `logrus.Debug` is useful in // logged. `logrus.Debug` is useful in
Level Level Level Level
// Used to sync writing to the log. Locking is enabled by Default // Used to sync writing to the log.
mu MutexWrap mu sync.Mutex
// Reusable empty entry
entryPool sync.Pool
}
type MutexWrap struct {
lock sync.Mutex
disabled bool
}
func (mw *MutexWrap) Lock() {
if !mw.disabled {
mw.lock.Lock()
}
}
func (mw *MutexWrap) Unlock() {
if !mw.disabled {
mw.lock.Unlock()
}
}
func (mw *MutexWrap) Disable() {
mw.disabled = true
} }
// Creates a new logger. Configuration should be set by changing `Formatter`, // Creates a new logger. Configuration should be set by changing `Formatter`,
@ -74,235 +51,162 @@ func New() *Logger {
} }
} }
func (logger *Logger) newEntry() *Entry { // Adds a field to the log entry, note that you it doesn't log until you call
entry, ok := logger.entryPool.Get().(*Entry)
if ok {
return entry
}
return NewEntry(logger)
}
func (logger *Logger) releaseEntry(entry *Entry) {
logger.entryPool.Put(entry)
}
// Adds a field to the log entry, note that it doesn't log until you call
// Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry. // Debug, Print, Info, Warn, Fatal or Panic. It only creates a log entry.
// If you want multiple fields, use `WithFields`. // If you want multiple fields, use `WithFields`.
func (logger *Logger) WithField(key string, value interface{}) *Entry { func (logger *Logger) WithField(key string, value interface{}) *Entry {
entry := logger.newEntry() return NewEntry(logger).WithField(key, value)
defer logger.releaseEntry(entry)
return entry.WithField(key, value)
} }
// Adds a struct of fields to the log entry. All it does is call `WithField` for // Adds a struct of fields to the log entry. All it does is call `WithField` for
// each `Field`. // each `Field`.
func (logger *Logger) WithFields(fields Fields) *Entry { func (logger *Logger) WithFields(fields Fields) *Entry {
entry := logger.newEntry() return NewEntry(logger).WithFields(fields)
defer logger.releaseEntry(entry)
return entry.WithFields(fields)
} }
// Add an error as single field to the log entry. All it does is call // Add an error as single field to the log entry. All it does is call
// `WithError` for the given `error`. // `WithError` for the given `error`.
func (logger *Logger) WithError(err error) *Entry { func (logger *Logger) WithError(err error) *Entry {
entry := logger.newEntry() return NewEntry(logger).WithError(err)
defer logger.releaseEntry(entry)
return entry.WithError(err)
} }
func (logger *Logger) Debugf(format string, args ...interface{}) { func (logger *Logger) Debugf(format string, args ...interface{}) {
if logger.Level >= DebugLevel { if logger.Level >= DebugLevel {
entry := logger.newEntry() NewEntry(logger).Debugf(format, args...)
entry.Debugf(format, args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Infof(format string, args ...interface{}) { func (logger *Logger) Infof(format string, args ...interface{}) {
if logger.Level >= InfoLevel { if logger.Level >= InfoLevel {
entry := logger.newEntry() NewEntry(logger).Infof(format, args...)
entry.Infof(format, args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Printf(format string, args ...interface{}) { func (logger *Logger) Printf(format string, args ...interface{}) {
entry := logger.newEntry() NewEntry(logger).Printf(format, args...)
entry.Printf(format, args...)
logger.releaseEntry(entry)
} }
func (logger *Logger) Warnf(format string, args ...interface{}) { func (logger *Logger) Warnf(format string, args ...interface{}) {
if logger.Level >= WarnLevel { if logger.Level >= WarnLevel {
entry := logger.newEntry() NewEntry(logger).Warnf(format, args...)
entry.Warnf(format, args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Warningf(format string, args ...interface{}) { func (logger *Logger) Warningf(format string, args ...interface{}) {
if logger.Level >= WarnLevel { if logger.Level >= WarnLevel {
entry := logger.newEntry() NewEntry(logger).Warnf(format, args...)
entry.Warnf(format, args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Errorf(format string, args ...interface{}) { func (logger *Logger) Errorf(format string, args ...interface{}) {
if logger.Level >= ErrorLevel { if logger.Level >= ErrorLevel {
entry := logger.newEntry() NewEntry(logger).Errorf(format, args...)
entry.Errorf(format, args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Fatalf(format string, args ...interface{}) { func (logger *Logger) Fatalf(format string, args ...interface{}) {
if logger.Level >= FatalLevel { if logger.Level >= FatalLevel {
entry := logger.newEntry() NewEntry(logger).Fatalf(format, args...)
entry.Fatalf(format, args...)
logger.releaseEntry(entry)
} }
Exit(1) os.Exit(1)
} }
func (logger *Logger) Panicf(format string, args ...interface{}) { func (logger *Logger) Panicf(format string, args ...interface{}) {
if logger.Level >= PanicLevel { if logger.Level >= PanicLevel {
entry := logger.newEntry() NewEntry(logger).Panicf(format, args...)
entry.Panicf(format, args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Debug(args ...interface{}) { func (logger *Logger) Debug(args ...interface{}) {
if logger.Level >= DebugLevel { if logger.Level >= DebugLevel {
entry := logger.newEntry() NewEntry(logger).Debug(args...)
entry.Debug(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Info(args ...interface{}) { func (logger *Logger) Info(args ...interface{}) {
if logger.Level >= InfoLevel { if logger.Level >= InfoLevel {
entry := logger.newEntry() NewEntry(logger).Info(args...)
entry.Info(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Print(args ...interface{}) { func (logger *Logger) Print(args ...interface{}) {
entry := logger.newEntry() NewEntry(logger).Info(args...)
entry.Info(args...)
logger.releaseEntry(entry)
} }
func (logger *Logger) Warn(args ...interface{}) { func (logger *Logger) Warn(args ...interface{}) {
if logger.Level >= WarnLevel { if logger.Level >= WarnLevel {
entry := logger.newEntry() NewEntry(logger).Warn(args...)
entry.Warn(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Warning(args ...interface{}) { func (logger *Logger) Warning(args ...interface{}) {
if logger.Level >= WarnLevel { if logger.Level >= WarnLevel {
entry := logger.newEntry() NewEntry(logger).Warn(args...)
entry.Warn(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Error(args ...interface{}) { func (logger *Logger) Error(args ...interface{}) {
if logger.Level >= ErrorLevel { if logger.Level >= ErrorLevel {
entry := logger.newEntry() NewEntry(logger).Error(args...)
entry.Error(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Fatal(args ...interface{}) { func (logger *Logger) Fatal(args ...interface{}) {
if logger.Level >= FatalLevel { if logger.Level >= FatalLevel {
entry := logger.newEntry() NewEntry(logger).Fatal(args...)
entry.Fatal(args...)
logger.releaseEntry(entry)
} }
Exit(1) os.Exit(1)
} }
func (logger *Logger) Panic(args ...interface{}) { func (logger *Logger) Panic(args ...interface{}) {
if logger.Level >= PanicLevel { if logger.Level >= PanicLevel {
entry := logger.newEntry() NewEntry(logger).Panic(args...)
entry.Panic(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Debugln(args ...interface{}) { func (logger *Logger) Debugln(args ...interface{}) {
if logger.Level >= DebugLevel { if logger.Level >= DebugLevel {
entry := logger.newEntry() NewEntry(logger).Debugln(args...)
entry.Debugln(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Infoln(args ...interface{}) { func (logger *Logger) Infoln(args ...interface{}) {
if logger.Level >= InfoLevel { if logger.Level >= InfoLevel {
entry := logger.newEntry() NewEntry(logger).Infoln(args...)
entry.Infoln(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Println(args ...interface{}) { func (logger *Logger) Println(args ...interface{}) {
entry := logger.newEntry() NewEntry(logger).Println(args...)
entry.Println(args...)
logger.releaseEntry(entry)
} }
func (logger *Logger) Warnln(args ...interface{}) { func (logger *Logger) Warnln(args ...interface{}) {
if logger.Level >= WarnLevel { if logger.Level >= WarnLevel {
entry := logger.newEntry() NewEntry(logger).Warnln(args...)
entry.Warnln(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Warningln(args ...interface{}) { func (logger *Logger) Warningln(args ...interface{}) {
if logger.Level >= WarnLevel { if logger.Level >= WarnLevel {
entry := logger.newEntry() NewEntry(logger).Warnln(args...)
entry.Warnln(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Errorln(args ...interface{}) { func (logger *Logger) Errorln(args ...interface{}) {
if logger.Level >= ErrorLevel { if logger.Level >= ErrorLevel {
entry := logger.newEntry() NewEntry(logger).Errorln(args...)
entry.Errorln(args...)
logger.releaseEntry(entry)
} }
} }
func (logger *Logger) Fatalln(args ...interface{}) { func (logger *Logger) Fatalln(args ...interface{}) {
if logger.Level >= FatalLevel { if logger.Level >= FatalLevel {
entry := logger.newEntry() NewEntry(logger).Fatalln(args...)
entry.Fatalln(args...)
logger.releaseEntry(entry)
} }
Exit(1) os.Exit(1)
} }
func (logger *Logger) Panicln(args ...interface{}) { func (logger *Logger) Panicln(args ...interface{}) {
if logger.Level >= PanicLevel { if logger.Level >= PanicLevel {
entry := logger.newEntry() NewEntry(logger).Panicln(args...)
entry.Panicln(args...)
logger.releaseEntry(entry)
} }
} }
//When file is opened with appending mode, it's safe to
//write concurrently to a file (within 4k message on Linux).
//In these cases user can choose to disable the lock.
func (logger *Logger) SetNoLock() {
logger.mu.Disable()
}

View File

@ -1,8 +0,0 @@
// +build appengine
package logrus
// IsTerminal returns true if stderr's file descriptor is a terminal.
func IsTerminal() bool {
return true
}

View File

@ -1,5 +1,4 @@
// +build darwin freebsd openbsd netbsd dragonfly // +build darwin freebsd openbsd netbsd dragonfly
// +build !appengine
package logrus package logrus

View File

@ -3,8 +3,6 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build !appengine
package logrus package logrus
import "syscall" import "syscall"

View File

@ -4,7 +4,6 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux darwin freebsd openbsd netbsd dragonfly // +build linux darwin freebsd openbsd netbsd dragonfly
// +build !appengine
package logrus package logrus

View File

@ -1,4 +1,4 @@
// +build solaris,!appengine // +build solaris
package logrus package logrus

View File

@ -3,7 +3,7 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build windows,!appengine // +build windows
package logrus package logrus

View File

@ -57,7 +57,6 @@ type TextFormatter struct {
} }
func (f *TextFormatter) Format(entry *Entry) ([]byte, error) { func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
var b *bytes.Buffer
var keys []string = make([]string, 0, len(entry.Data)) var keys []string = make([]string, 0, len(entry.Data))
for k := range entry.Data { for k := range entry.Data {
keys = append(keys, k) keys = append(keys, k)
@ -66,11 +65,8 @@ func (f *TextFormatter) Format(entry *Entry) ([]byte, error) {
if !f.DisableSorting { if !f.DisableSorting {
sort.Strings(keys) sort.Strings(keys)
} }
if entry.Buffer != nil {
b = entry.Buffer b := &bytes.Buffer{}
} else {
b = &bytes.Buffer{}
}
prefixFieldClashes(entry.Data) prefixFieldClashes(entry.Data)
@ -122,8 +118,7 @@ func (f *TextFormatter) printColored(b *bytes.Buffer, entry *Entry, keys []strin
} }
for _, k := range keys { for _, k := range keys {
v := entry.Data[k] v := entry.Data[k]
fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=", levelColor, k) fmt.Fprintf(b, " \x1b[%dm%s\x1b[0m=%+v", levelColor, k, v)
f.appendValue(b, v)
} }
} }
@ -133,36 +128,34 @@ func needsQuoting(text string) bool {
(ch >= 'A' && ch <= 'Z') || (ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') || (ch >= '0' && ch <= '9') ||
ch == '-' || ch == '.') { ch == '-' || ch == '.') {
return true return false
} }
} }
return false return true
} }
func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) { func (f *TextFormatter) appendKeyValue(b *bytes.Buffer, key string, value interface{}) {
b.WriteString(key) b.WriteString(key)
b.WriteByte('=') b.WriteByte('=')
f.appendValue(b, value)
b.WriteByte(' ')
}
func (f *TextFormatter) appendValue(b *bytes.Buffer, value interface{}) {
switch value := value.(type) { switch value := value.(type) {
case string: case string:
if !needsQuoting(value) { if needsQuoting(value) {
b.WriteString(value) b.WriteString(value)
} else { } else {
fmt.Fprintf(b, "%q", value) fmt.Fprintf(b, "%q", value)
} }
case error: case error:
errmsg := value.Error() errmsg := value.Error()
if !needsQuoting(errmsg) { if needsQuoting(errmsg) {
b.WriteString(errmsg) b.WriteString(errmsg)
} else { } else {
fmt.Fprintf(b, "%q", errmsg) fmt.Fprintf(b, "%q", value)
} }
default: default:
fmt.Fprint(b, value) fmt.Fprint(b, value)
} }
b.WriteByte(' ')
} }

View File

@ -7,40 +7,18 @@ import (
) )
func (logger *Logger) Writer() *io.PipeWriter { func (logger *Logger) Writer() *io.PipeWriter {
return logger.WriterLevel(InfoLevel)
}
func (logger *Logger) WriterLevel(level Level) *io.PipeWriter {
reader, writer := io.Pipe() reader, writer := io.Pipe()
var printFunc func(args ...interface{}) go logger.writerScanner(reader)
switch level {
case DebugLevel:
printFunc = logger.Debug
case InfoLevel:
printFunc = logger.Info
case WarnLevel:
printFunc = logger.Warn
case ErrorLevel:
printFunc = logger.Error
case FatalLevel:
printFunc = logger.Fatal
case PanicLevel:
printFunc = logger.Panic
default:
printFunc = logger.Print
}
go logger.writerScanner(reader, printFunc)
runtime.SetFinalizer(writer, writerFinalizer) runtime.SetFinalizer(writer, writerFinalizer)
return writer return writer
} }
func (logger *Logger) writerScanner(reader *io.PipeReader, printFunc func(args ...interface{})) { func (logger *Logger) writerScanner(reader *io.PipeReader) {
scanner := bufio.NewScanner(reader) scanner := bufio.NewScanner(reader)
for scanner.Scan() { for scanner.Scan() {
printFunc(scanner.Text()) logger.Print(scanner.Text())
} }
if err := scanner.Err(); err != nil { if err := scanner.Err(); err != nil {
logger.Errorf("Error while reading from Writer: %s", err) logger.Errorf("Error while reading from Writer: %s", err)

View File

@ -431,7 +431,7 @@ func strctVal(s interface{}) reflect.Value {
v := reflect.ValueOf(s) v := reflect.ValueOf(s)
// if pointer get the underlying element≤ // if pointer get the underlying element≤
for v.Kind() == reflect.Ptr { if v.Kind() == reflect.Ptr {
v = v.Elem() v = v.Elem()
} }
@ -558,10 +558,7 @@ func (s *Struct) nested(val reflect.Value) interface{} {
// TODO(arslan): should this be optional? // TODO(arslan): should this be optional?
// do not iterate of non struct types, just pass the value. Ie: []int, // do not iterate of non struct types, just pass the value. Ie: []int,
// []string, co... We only iterate further if it's a struct. // []string, co... We only iterate further if it's a struct.
// i.e []foo or []*foo if val.Type().Elem().Kind() != reflect.Struct {
if val.Type().Elem().Kind() != reflect.Struct &&
!(val.Type().Elem().Kind() == reflect.Ptr &&
val.Type().Elem().Elem().Kind() == reflect.Struct) {
finalVal = val.Interface() finalVal = val.Interface()
break break
} }

View File

@ -0,0 +1,109 @@
package install
import (
"fmt"
"github.com/golang/glog"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/meta"
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/apimachinery"
"k8s.io/kubernetes/pkg/apimachinery/registered"
"k8s.io/kubernetes/pkg/runtime"
"k8s.io/kubernetes/pkg/util/sets"
"github.com/openshift/origin/pkg/route/api"
"github.com/openshift/origin/pkg/route/api/v1"
)
const importPrefix = "github.com/openshift/origin/pkg/route/api"
var accessor = meta.NewAccessor()
// availableVersions lists all known external versions for this group from most preferred to least preferred
var availableVersions = []unversioned.GroupVersion{v1.SchemeGroupVersion}
func init() {
registered.RegisterVersions(availableVersions)
externalVersions := []unversioned.GroupVersion{}
for _, v := range availableVersions {
if registered.IsAllowedVersion(v) {
externalVersions = append(externalVersions, v)
}
}
if len(externalVersions) == 0 {
glog.Infof("No version is registered for group %v", api.GroupName)
return
}
if err := registered.EnableVersions(externalVersions...); err != nil {
panic(err)
}
if err := enableVersions(externalVersions); err != nil {
panic(err)
}
}
// TODO: enableVersions should be centralized rather than spread in each API
// group.
// We can combine registered.RegisterVersions, registered.EnableVersions and
// registered.RegisterGroup once we have moved enableVersions there.
func enableVersions(externalVersions []unversioned.GroupVersion) error {
addVersionsToScheme(externalVersions...)
preferredExternalVersion := externalVersions[0]
groupMeta := apimachinery.GroupMeta{
GroupVersion: preferredExternalVersion,
GroupVersions: externalVersions,
RESTMapper: newRESTMapper(externalVersions),
SelfLinker: runtime.SelfLinker(accessor),
InterfacesFor: interfacesFor,
}
if err := registered.RegisterGroup(groupMeta); err != nil {
return err
}
kapi.RegisterRESTMapper(groupMeta.RESTMapper)
return nil
}
func addVersionsToScheme(externalVersions ...unversioned.GroupVersion) {
// add the internal version to Scheme
api.AddToScheme(kapi.Scheme)
// add the enabled external versions to Scheme
for _, v := range externalVersions {
if !registered.IsEnabledVersion(v) {
glog.Errorf("Version %s is not enabled, so it will not be added to the Scheme.", v)
continue
}
switch v {
case v1.SchemeGroupVersion:
v1.AddToScheme(kapi.Scheme)
default:
glog.Errorf("Version %s is not known, so it will not be added to the Scheme.", v)
continue
}
}
}
func newRESTMapper(externalVersions []unversioned.GroupVersion) meta.RESTMapper {
rootScoped := sets.NewString()
ignoredKinds := sets.NewString()
return kapi.NewDefaultRESTMapper(externalVersions, interfacesFor, importPrefix, ignoredKinds, rootScoped)
}
func interfacesFor(version unversioned.GroupVersion) (*meta.VersionInterfaces, error) {
switch version {
case v1.SchemeGroupVersion:
return &meta.VersionInterfaces{
ObjectConvertor: kapi.Scheme,
MetadataAccessor: accessor,
}, nil
default:
g, _ := registered.Group(api.GroupName)
return nil, fmt.Errorf("unsupported storage version: %s (valid: %v)", version, g.GroupVersions)
}
}

View File

@ -0,0 +1,14 @@
package v1
import (
"k8s.io/kubernetes/pkg/runtime"
oapi "github.com/openshift/origin/pkg/api"
routeapi "github.com/openshift/origin/pkg/route/api"
)
func addConversionFuncs(scheme *runtime.Scheme) error {
return scheme.AddFieldLabelConversionFunc("v1", "Route",
oapi.GetFieldLabelConversionFunc(routeapi.RouteToSelectableFields(&routeapi.Route{}), nil),
)
}

View File

@ -0,0 +1,48 @@
package v1
import "k8s.io/kubernetes/pkg/runtime"
func SetDefaults_RouteSpec(obj *RouteSpec) {
if len(obj.WildcardPolicy) == 0 {
obj.WildcardPolicy = WildcardPolicyNone
}
}
func SetDefaults_RouteTargetReference(obj *RouteTargetReference) {
if len(obj.Kind) == 0 {
obj.Kind = "Service"
}
if obj.Weight == nil {
obj.Weight = new(int32)
*obj.Weight = 100
}
}
func SetDefaults_TLSConfig(obj *TLSConfig) {
if len(obj.Termination) == 0 && len(obj.DestinationCACertificate) == 0 {
obj.Termination = TLSTerminationEdge
}
switch obj.Termination {
case TLSTerminationType("Reencrypt"):
obj.Termination = TLSTerminationReencrypt
case TLSTerminationType("Edge"):
obj.Termination = TLSTerminationEdge
case TLSTerminationType("Passthrough"):
obj.Termination = TLSTerminationPassthrough
}
}
func SetDefaults_RouteIngress(obj *RouteIngress) {
if len(obj.WildcardPolicy) == 0 {
obj.WildcardPolicy = WildcardPolicyNone
}
}
func addDefaultingFuncs(scheme *runtime.Scheme) error {
return scheme.AddDefaultingFuncs(
SetDefaults_RouteSpec,
SetDefaults_RouteTargetReference,
SetDefaults_TLSConfig,
SetDefaults_RouteIngress,
)
}

View File

@ -0,0 +1,5 @@
// +k8s:deepcopy-gen=package,register
// +k8s:conversion-gen=github.com/openshift/origin/pkg/route/api
// Package v1 is the v1 version of the API.
package v1

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,28 @@
package v1
import (
"k8s.io/kubernetes/pkg/api/unversioned"
"k8s.io/kubernetes/pkg/runtime"
)
const GroupName = ""
// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = unversioned.GroupVersion{Group: GroupName, Version: "v1"}
var (
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes, addConversionFuncs, addDefaultingFuncs)
AddToScheme = SchemeBuilder.AddToScheme
)
// Adds the list of known types to api.Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Route{},
&RouteList{},
)
return nil
}
func (obj *Route) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }
func (obj *RouteList) GetObjectKind() unversioned.ObjectKind { return &obj.TypeMeta }

View File

@ -0,0 +1,120 @@
package v1
// This file contains methods that can be used by the go-restful package to generate Swagger
// documentation for the object types found in 'types.go' This file is automatically generated
// by hack/update-generated-swagger-descriptions.sh and should be run after a full build of OpenShift.
// ==== DO NOT EDIT THIS FILE MANUALLY ====
var map_Route = map[string]string{
"": "A route allows developers to expose services through an HTTP(S) aware load balancing and proxy layer via a public DNS entry. The route may further specify TLS options and a certificate, or specify a public CNAME that the router should also accept for HTTP and HTTPS traffic. An administrator typically configures their router to be visible outside the cluster firewall, and may also add additional security, caching, or traffic controls on the service content. Routers usually talk directly to the service endpoints.\n\nOnce a route is created, the `host` field may not be changed. Generally, routers use the oldest route with a given host when resolving conflicts.\n\nRouters are subject to additional customization and may support additional controls via the annotations field.\n\nBecause administrators may configure multiple routers, the route status field is used to return information to clients about the names and states of the route under each router. If a client chooses a duplicate name, for instance, the route status conditions are used to indicate the route cannot be chosen.",
"metadata": "Standard object metadata.",
"spec": "spec is the desired state of the route",
"status": "status is the current state of the route",
}
func (Route) SwaggerDoc() map[string]string {
return map_Route
}
var map_RouteIngress = map[string]string{
"": "RouteIngress holds information about the places where a route is exposed.",
"host": "Host is the host string under which the route is exposed; this value is required",
"routerName": "Name is a name chosen by the router to identify itself; this value is required",
"conditions": "Conditions is the state of the route, may be empty.",
"wildcardPolicy": "Wildcard policy is the wildcard policy that was allowed where this route is exposed.",
}
func (RouteIngress) SwaggerDoc() map[string]string {
return map_RouteIngress
}
var map_RouteIngressCondition = map[string]string{
"": "RouteIngressCondition contains details for the current condition of this route on a particular router.",
"type": "Type is the type of the condition. Currently only Ready.",
"status": "Status is the status of the condition. Can be True, False, Unknown.",
"reason": "(brief) reason for the condition's last transition, and is usually a machine and human readable constant",
"message": "Human readable message indicating details about last transition.",
"lastTransitionTime": "RFC 3339 date and time when this condition last transitioned",
}
func (RouteIngressCondition) SwaggerDoc() map[string]string {
return map_RouteIngressCondition
}
var map_RouteList = map[string]string{
"": "RouteList is a collection of Routes.",
"metadata": "Standard object metadata.",
"items": "items is a list of routes",
}
func (RouteList) SwaggerDoc() map[string]string {
return map_RouteList
}
var map_RoutePort = map[string]string{
"": "RoutePort defines a port mapping from a router to an endpoint in the service endpoints.",
"targetPort": "The target port on pods selected by the service this route points to. If this is a string, it will be looked up as a named port in the target endpoints port list. Required",
}
func (RoutePort) SwaggerDoc() map[string]string {
return map_RoutePort
}
var map_RouteSpec = map[string]string{
"": "RouteSpec describes the hostname or path the route exposes, any security information, and one or more backends the route points to. Weights on each backend can define the balance of traffic sent to each backend - if all weights are zero the route will be considered to have no backends and return a standard 503 response.\n\nThe `tls` field is optional and allows specific certificates or behavior for the route. Routers typically configure a default certificate on a wildcard domain to terminate routes without explicit certificates, but custom hostnames usually must choose passthrough (send traffic directly to the backend via the TLS Server-Name- Indication field) or provide a certificate.",
"host": "host is an alias/DNS that points to the service. Optional. If not specified a route name will typically be automatically chosen. Must follow DNS952 subdomain conventions.",
"path": "Path that the router watches for, to route traffic for to the service. Optional",
"to": "to is an object the route should use as the primary backend. Only the Service kind is allowed, and it will be defaulted to Service. If the weight field is set to zero, no traffic will be sent to this service.",
"alternateBackends": "alternateBackends is an extension of the 'to' field. If more than one service needs to be pointed to, then use this field. Use the weight field in RouteTargetReference object to specify relative preference. If the weight field is zero, the backend is ignored.",
"port": "If specified, the port to be used by the router. Most routers will use all endpoints exposed by the service by default - set this value to instruct routers which port to use.",
"tls": "The tls field provides the ability to configure certificates and termination for the route.",
"wildcardPolicy": "Wildcard policy if any for the route. Currently only 'Subdomain' or 'None' is allowed.",
}
func (RouteSpec) SwaggerDoc() map[string]string {
return map_RouteSpec
}
var map_RouteStatus = map[string]string{
"": "RouteStatus provides relevant info about the status of a route, including which routers acknowledge it.",
"ingress": "ingress describes the places where the route may be exposed. The list of ingress points may contain duplicate Host or RouterName values. Routes are considered live once they are `Ready`",
}
func (RouteStatus) SwaggerDoc() map[string]string {
return map_RouteStatus
}
var map_RouteTargetReference = map[string]string{
"": "RouteTargetReference specifies the target that resolve into endpoints. Only the 'Service' kind is allowed. Use 'weight' field to emphasize one over others.",
"kind": "The kind of target that the route is referring to. Currently, only 'Service' is allowed",
"name": "name of the service/target that is being referred to. e.g. name of the service",
"weight": "weight as an integer between 1 and 256 that specifies the target's relative weight against other target reference objects",
}
func (RouteTargetReference) SwaggerDoc() map[string]string {
return map_RouteTargetReference
}
var map_RouterShard = map[string]string{
"": "RouterShard has information of a routing shard and is used to generate host names and routing table entries when a routing shard is allocated for a specific route. Caveat: This is WIP and will likely undergo modifications when sharding\n support is added.",
"shardName": "shardName uniquely identifies a router shard in the \"set\" of routers used for routing traffic to the services.",
"dnsSuffix": "dnsSuffix for the shard ala: shard-1.v3.openshift.com",
}
func (RouterShard) SwaggerDoc() map[string]string {
return map_RouterShard
}
var map_TLSConfig = map[string]string{
"": "TLSConfig defines config used to secure a route and provide termination",
"termination": "termination indicates termination type.",
"certificate": "certificate provides certificate contents",
"key": "key provides key file contents",
"caCertificate": "caCertificate provides the cert authority certificate contents",
"destinationCACertificate": "destinationCACertificate provides the contents of the ca certificate of the final destination. When using reencrypt termination this file should be provided in order to have routers use it for health checks on the secure connection",
"insecureEdgeTerminationPolicy": "insecureEdgeTerminationPolicy indicates the desired behavior for insecure connections to a route. While each router may make its own decisions on which ports to expose, this is normally port 80.\n\n* Allow - traffic is sent to the server on the insecure port (default) * Disable - no traffic is allowed on the insecure port. * Redirect - clients are redirected to the secure port.",
}
func (TLSConfig) SwaggerDoc() map[string]string {
return map_TLSConfig
}

View File

@ -0,0 +1,232 @@
package v1
import (
"k8s.io/kubernetes/pkg/api/unversioned"
kapi "k8s.io/kubernetes/pkg/api/v1"
"k8s.io/kubernetes/pkg/util/intstr"
)
// +genclient=true
// A route allows developers to expose services through an HTTP(S) aware load balancing and proxy
// layer via a public DNS entry. The route may further specify TLS options and a certificate, or
// specify a public CNAME that the router should also accept for HTTP and HTTPS traffic. An
// administrator typically configures their router to be visible outside the cluster firewall, and
// may also add additional security, caching, or traffic controls on the service content. Routers
// usually talk directly to the service endpoints.
//
// Once a route is created, the `host` field may not be changed. Generally, routers use the oldest
// route with a given host when resolving conflicts.
//
// Routers are subject to additional customization and may support additional controls via the
// annotations field.
//
// Because administrators may configure multiple routers, the route status field is used to
// return information to clients about the names and states of the route under each router.
// If a client chooses a duplicate name, for instance, the route status conditions are used
// to indicate the route cannot be chosen.
type Route struct {
unversioned.TypeMeta `json:",inline"`
// Standard object metadata.
kapi.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// spec is the desired state of the route
Spec RouteSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
// status is the current state of the route
Status RouteStatus `json:"status" protobuf:"bytes,3,opt,name=status"`
}
// RouteList is a collection of Routes.
type RouteList struct {
unversioned.TypeMeta `json:",inline"`
// Standard object metadata.
unversioned.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
// items is a list of routes
Items []Route `json:"items" protobuf:"bytes,2,rep,name=items"`
}
// RouteSpec describes the hostname or path the route exposes, any security information,
// and one or more backends the route points to. Weights on each backend can define
// the balance of traffic sent to each backend - if all weights are zero the route will
// be considered to have no backends and return a standard 503 response.
//
// The `tls` field is optional and allows specific certificates or behavior for the
// route. Routers typically configure a default certificate on a wildcard domain to
// terminate routes without explicit certificates, but custom hostnames usually must
// choose passthrough (send traffic directly to the backend via the TLS Server-Name-
// Indication field) or provide a certificate.
type RouteSpec struct {
// host is an alias/DNS that points to the service. Optional.
// If not specified a route name will typically be automatically
// chosen.
// Must follow DNS952 subdomain conventions.
Host string `json:"host" protobuf:"bytes,1,opt,name=host"`
// Path that the router watches for, to route traffic for to the service. Optional
Path string `json:"path,omitempty" protobuf:"bytes,2,opt,name=path"`
// to is an object the route should use as the primary backend. Only the Service kind
// is allowed, and it will be defaulted to Service. If the weight field is set to zero,
// no traffic will be sent to this service.
To RouteTargetReference `json:"to" protobuf:"bytes,3,opt,name=to"`
// alternateBackends is an extension of the 'to' field. If more than one service needs to be
// pointed to, then use this field. Use the weight field in RouteTargetReference object
// to specify relative preference. If the weight field is zero, the backend is ignored.
AlternateBackends []RouteTargetReference `json:"alternateBackends,omitempty" protobuf:"bytes,4,rep,name=alternateBackends"`
// If specified, the port to be used by the router. Most routers will use all
// endpoints exposed by the service by default - set this value to instruct routers
// which port to use.
Port *RoutePort `json:"port,omitempty" protobuf:"bytes,5,opt,name=port"`
// The tls field provides the ability to configure certificates and termination for the route.
TLS *TLSConfig `json:"tls,omitempty" protobuf:"bytes,6,opt,name=tls"`
// Wildcard policy if any for the route.
// Currently only 'Subdomain' or 'None' is allowed.
WildcardPolicy WildcardPolicyType `json:"wildcardPolicy,omitempty" protobuf:"bytes,7,opt,name=wildcardPolicy"`
}
// RouteTargetReference specifies the target that resolve into endpoints. Only the 'Service'
// kind is allowed. Use 'weight' field to emphasize one over others.
type RouteTargetReference struct {
// The kind of target that the route is referring to. Currently, only 'Service' is allowed
Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"`
// name of the service/target that is being referred to. e.g. name of the service
Name string `json:"name" protobuf:"bytes,2,opt,name=name"`
// weight as an integer between 1 and 256 that specifies the target's relative weight
// against other target reference objects
Weight *int32 `json:"weight" protobuf:"varint,3,opt,name=weight"`
}
// RoutePort defines a port mapping from a router to an endpoint in the service endpoints.
type RoutePort struct {
// The target port on pods selected by the service this route points to.
// If this is a string, it will be looked up as a named port in the target
// endpoints port list. Required
TargetPort intstr.IntOrString `json:"targetPort" protobuf:"bytes,1,opt,name=targetPort"`
}
// RouteStatus provides relevant info about the status of a route, including which routers
// acknowledge it.
type RouteStatus struct {
// ingress describes the places where the route may be exposed. The list of
// ingress points may contain duplicate Host or RouterName values. Routes
// are considered live once they are `Ready`
Ingress []RouteIngress `json:"ingress" protobuf:"bytes,1,rep,name=ingress"`
}
// RouteIngress holds information about the places where a route is exposed.
type RouteIngress struct {
// Host is the host string under which the route is exposed; this value is required
Host string `json:"host,omitempty" protobuf:"bytes,1,opt,name=host"`
// Name is a name chosen by the router to identify itself; this value is required
RouterName string `json:"routerName,omitempty" protobuf:"bytes,2,opt,name=routerName"`
// Conditions is the state of the route, may be empty.
Conditions []RouteIngressCondition `json:"conditions,omitempty" protobuf:"bytes,3,rep,name=conditions"`
// Wildcard policy is the wildcard policy that was allowed where this route is exposed.
WildcardPolicy WildcardPolicyType `json:"wildcardPolicy,omitempty" protobuf:"bytes,4,opt,name=wildcardPolicy"`
}
// RouteIngressConditionType is a valid value for RouteCondition
type RouteIngressConditionType string
// These are valid conditions of pod.
const (
// RouteAdmitted means the route is able to service requests for the provided Host
RouteAdmitted RouteIngressConditionType = "Admitted"
// TODO: add other route condition types
)
// RouteIngressCondition contains details for the current condition of this route on a particular
// router.
type RouteIngressCondition struct {
// Type is the type of the condition.
// Currently only Ready.
Type RouteIngressConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=RouteIngressConditionType"`
// Status is the status of the condition.
// Can be True, False, Unknown.
Status kapi.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/kubernetes/pkg/api/v1.ConditionStatus"`
// (brief) reason for the condition's last transition, and is usually a machine and human
// readable constant
Reason string `json:"reason,omitempty" protobuf:"bytes,3,opt,name=reason"`
// Human readable message indicating details about last transition.
Message string `json:"message,omitempty" protobuf:"bytes,4,opt,name=message"`
// RFC 3339 date and time when this condition last transitioned
LastTransitionTime *unversioned.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,5,opt,name=lastTransitionTime"`
}
// RouterShard has information of a routing shard and is used to
// generate host names and routing table entries when a routing shard is
// allocated for a specific route.
// Caveat: This is WIP and will likely undergo modifications when sharding
// support is added.
type RouterShard struct {
// shardName uniquely identifies a router shard in the "set" of
// routers used for routing traffic to the services.
ShardName string `json:"shardName" protobuf:"bytes,1,opt,name=shardName"`
// dnsSuffix for the shard ala: shard-1.v3.openshift.com
DNSSuffix string `json:"dnsSuffix" protobuf:"bytes,2,opt,name=dnsSuffix"`
}
// TLSConfig defines config used to secure a route and provide termination
type TLSConfig struct {
// termination indicates termination type.
Termination TLSTerminationType `json:"termination" protobuf:"bytes,1,opt,name=termination,casttype=TLSTerminationType"`
// certificate provides certificate contents
Certificate string `json:"certificate,omitempty" protobuf:"bytes,2,opt,name=certificate"`
// key provides key file contents
Key string `json:"key,omitempty" protobuf:"bytes,3,opt,name=key"`
// caCertificate provides the cert authority certificate contents
CACertificate string `json:"caCertificate,omitempty" protobuf:"bytes,4,opt,name=caCertificate"`
// destinationCACertificate provides the contents of the ca certificate of the final destination. When using reencrypt
// termination this file should be provided in order to have routers use it for health checks on the secure connection
DestinationCACertificate string `json:"destinationCACertificate,omitempty" protobuf:"bytes,5,opt,name=destinationCACertificate"`
// insecureEdgeTerminationPolicy indicates the desired behavior for insecure connections to a route. While
// each router may make its own decisions on which ports to expose, this is normally port 80.
//
// * Allow - traffic is sent to the server on the insecure port (default)
// * Disable - no traffic is allowed on the insecure port.
// * Redirect - clients are redirected to the secure port.
InsecureEdgeTerminationPolicy InsecureEdgeTerminationPolicyType `json:"insecureEdgeTerminationPolicy,omitempty" protobuf:"bytes,6,opt,name=insecureEdgeTerminationPolicy,casttype=InsecureEdgeTerminationPolicyType"`
}
// TLSTerminationType dictates where the secure communication will stop
// TODO: Reconsider this type in v2
type TLSTerminationType string
// InsecureEdgeTerminationPolicyType dictates the behavior of insecure
// connections to an edge-terminated route.
type InsecureEdgeTerminationPolicyType string
const (
// TLSTerminationEdge terminate encryption at the edge router.
TLSTerminationEdge TLSTerminationType = "edge"
// TLSTerminationPassthrough terminate encryption at the destination, the destination is responsible for decrypting traffic
TLSTerminationPassthrough TLSTerminationType = "passthrough"
// TLSTerminationReencrypt terminate encryption at the edge router and re-encrypt it with a new certificate supplied by the destination
TLSTerminationReencrypt TLSTerminationType = "reencrypt"
)
// WildcardPolicyType indicates the type of wildcard support needed by routes.
type WildcardPolicyType string
const (
// WildcardPolicyNone indicates no wildcard support is needed.
WildcardPolicyNone WildcardPolicyType = "None"
// WildcardPolicySubdomain indicates the host needs wildcard support for the subdomain.
// Example: For host = "www.acme.test", indicates that the router
// should support requests for *.acme.test
// Note that this will not match acme.test only *.acme.test
WildcardPolicySubdomain WildcardPolicyType = "Subdomain"
)

View File

@ -0,0 +1,424 @@
// +build !ignore_autogenerated_openshift
// This file was autogenerated by conversion-gen. Do not edit it manually!
package v1
import (
api "github.com/openshift/origin/pkg/route/api"
pkg_api "k8s.io/kubernetes/pkg/api"
api_v1 "k8s.io/kubernetes/pkg/api/v1"
conversion "k8s.io/kubernetes/pkg/conversion"
runtime "k8s.io/kubernetes/pkg/runtime"
)
func init() {
SchemeBuilder.Register(RegisterConversions)
}
// RegisterConversions adds conversion functions to the given scheme.
// Public to allow building arbitrary schemes.
func RegisterConversions(scheme *runtime.Scheme) error {
return scheme.AddGeneratedConversionFuncs(
Convert_v1_Route_To_api_Route,
Convert_api_Route_To_v1_Route,
Convert_v1_RouteIngress_To_api_RouteIngress,
Convert_api_RouteIngress_To_v1_RouteIngress,
Convert_v1_RouteIngressCondition_To_api_RouteIngressCondition,
Convert_api_RouteIngressCondition_To_v1_RouteIngressCondition,
Convert_v1_RouteList_To_api_RouteList,
Convert_api_RouteList_To_v1_RouteList,
Convert_v1_RoutePort_To_api_RoutePort,
Convert_api_RoutePort_To_v1_RoutePort,
Convert_v1_RouteSpec_To_api_RouteSpec,
Convert_api_RouteSpec_To_v1_RouteSpec,
Convert_v1_RouteStatus_To_api_RouteStatus,
Convert_api_RouteStatus_To_v1_RouteStatus,
Convert_v1_RouteTargetReference_To_api_RouteTargetReference,
Convert_api_RouteTargetReference_To_v1_RouteTargetReference,
Convert_v1_RouterShard_To_api_RouterShard,
Convert_api_RouterShard_To_v1_RouterShard,
Convert_v1_TLSConfig_To_api_TLSConfig,
Convert_api_TLSConfig_To_v1_TLSConfig,
)
}
func autoConvert_v1_Route_To_api_Route(in *Route, out *api.Route, s conversion.Scope) error {
if err := pkg_api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := api_v1.Convert_v1_ObjectMeta_To_api_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
return err
}
if err := Convert_v1_RouteSpec_To_api_RouteSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_v1_RouteStatus_To_api_RouteStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
func Convert_v1_Route_To_api_Route(in *Route, out *api.Route, s conversion.Scope) error {
return autoConvert_v1_Route_To_api_Route(in, out, s)
}
func autoConvert_api_Route_To_v1_Route(in *api.Route, out *Route, s conversion.Scope) error {
if err := pkg_api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := api_v1.Convert_api_ObjectMeta_To_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, s); err != nil {
return err
}
if err := Convert_api_RouteSpec_To_v1_RouteSpec(&in.Spec, &out.Spec, s); err != nil {
return err
}
if err := Convert_api_RouteStatus_To_v1_RouteStatus(&in.Status, &out.Status, s); err != nil {
return err
}
return nil
}
func Convert_api_Route_To_v1_Route(in *api.Route, out *Route, s conversion.Scope) error {
return autoConvert_api_Route_To_v1_Route(in, out, s)
}
func autoConvert_v1_RouteIngress_To_api_RouteIngress(in *RouteIngress, out *api.RouteIngress, s conversion.Scope) error {
SetDefaults_RouteIngress(in)
out.Host = in.Host
out.RouterName = in.RouterName
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]api.RouteIngressCondition, len(*in))
for i := range *in {
if err := Convert_v1_RouteIngressCondition_To_api_RouteIngressCondition(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Conditions = nil
}
out.WildcardPolicy = api.WildcardPolicyType(in.WildcardPolicy)
return nil
}
func Convert_v1_RouteIngress_To_api_RouteIngress(in *RouteIngress, out *api.RouteIngress, s conversion.Scope) error {
return autoConvert_v1_RouteIngress_To_api_RouteIngress(in, out, s)
}
func autoConvert_api_RouteIngress_To_v1_RouteIngress(in *api.RouteIngress, out *RouteIngress, s conversion.Scope) error {
out.Host = in.Host
out.RouterName = in.RouterName
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]RouteIngressCondition, len(*in))
for i := range *in {
if err := Convert_api_RouteIngressCondition_To_v1_RouteIngressCondition(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Conditions = nil
}
out.WildcardPolicy = WildcardPolicyType(in.WildcardPolicy)
return nil
}
func Convert_api_RouteIngress_To_v1_RouteIngress(in *api.RouteIngress, out *RouteIngress, s conversion.Scope) error {
return autoConvert_api_RouteIngress_To_v1_RouteIngress(in, out, s)
}
func autoConvert_v1_RouteIngressCondition_To_api_RouteIngressCondition(in *RouteIngressCondition, out *api.RouteIngressCondition, s conversion.Scope) error {
out.Type = api.RouteIngressConditionType(in.Type)
out.Status = pkg_api.ConditionStatus(in.Status)
out.Reason = in.Reason
out.Message = in.Message
out.LastTransitionTime = in.LastTransitionTime
return nil
}
func Convert_v1_RouteIngressCondition_To_api_RouteIngressCondition(in *RouteIngressCondition, out *api.RouteIngressCondition, s conversion.Scope) error {
return autoConvert_v1_RouteIngressCondition_To_api_RouteIngressCondition(in, out, s)
}
func autoConvert_api_RouteIngressCondition_To_v1_RouteIngressCondition(in *api.RouteIngressCondition, out *RouteIngressCondition, s conversion.Scope) error {
out.Type = RouteIngressConditionType(in.Type)
out.Status = api_v1.ConditionStatus(in.Status)
out.Reason = in.Reason
out.Message = in.Message
out.LastTransitionTime = in.LastTransitionTime
return nil
}
func Convert_api_RouteIngressCondition_To_v1_RouteIngressCondition(in *api.RouteIngressCondition, out *RouteIngressCondition, s conversion.Scope) error {
return autoConvert_api_RouteIngressCondition_To_v1_RouteIngressCondition(in, out, s)
}
func autoConvert_v1_RouteList_To_api_RouteList(in *RouteList, out *api.RouteList, s conversion.Scope) error {
if err := pkg_api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := pkg_api.Convert_unversioned_ListMeta_To_unversioned_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
return err
}
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]api.Route, len(*in))
for i := range *in {
if err := Convert_v1_Route_To_api_Route(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func Convert_v1_RouteList_To_api_RouteList(in *RouteList, out *api.RouteList, s conversion.Scope) error {
return autoConvert_v1_RouteList_To_api_RouteList(in, out, s)
}
func autoConvert_api_RouteList_To_v1_RouteList(in *api.RouteList, out *RouteList, s conversion.Scope) error {
if err := pkg_api.Convert_unversioned_TypeMeta_To_unversioned_TypeMeta(&in.TypeMeta, &out.TypeMeta, s); err != nil {
return err
}
if err := pkg_api.Convert_unversioned_ListMeta_To_unversioned_ListMeta(&in.ListMeta, &out.ListMeta, s); err != nil {
return err
}
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Route, len(*in))
for i := range *in {
if err := Convert_api_Route_To_v1_Route(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
func Convert_api_RouteList_To_v1_RouteList(in *api.RouteList, out *RouteList, s conversion.Scope) error {
return autoConvert_api_RouteList_To_v1_RouteList(in, out, s)
}
func autoConvert_v1_RoutePort_To_api_RoutePort(in *RoutePort, out *api.RoutePort, s conversion.Scope) error {
if err := pkg_api.Convert_intstr_IntOrString_To_intstr_IntOrString(&in.TargetPort, &out.TargetPort, s); err != nil {
return err
}
return nil
}
func Convert_v1_RoutePort_To_api_RoutePort(in *RoutePort, out *api.RoutePort, s conversion.Scope) error {
return autoConvert_v1_RoutePort_To_api_RoutePort(in, out, s)
}
func autoConvert_api_RoutePort_To_v1_RoutePort(in *api.RoutePort, out *RoutePort, s conversion.Scope) error {
if err := pkg_api.Convert_intstr_IntOrString_To_intstr_IntOrString(&in.TargetPort, &out.TargetPort, s); err != nil {
return err
}
return nil
}
func Convert_api_RoutePort_To_v1_RoutePort(in *api.RoutePort, out *RoutePort, s conversion.Scope) error {
return autoConvert_api_RoutePort_To_v1_RoutePort(in, out, s)
}
func autoConvert_v1_RouteSpec_To_api_RouteSpec(in *RouteSpec, out *api.RouteSpec, s conversion.Scope) error {
SetDefaults_RouteSpec(in)
out.Host = in.Host
out.Path = in.Path
if err := Convert_v1_RouteTargetReference_To_api_RouteTargetReference(&in.To, &out.To, s); err != nil {
return err
}
if in.AlternateBackends != nil {
in, out := &in.AlternateBackends, &out.AlternateBackends
*out = make([]api.RouteTargetReference, len(*in))
for i := range *in {
if err := Convert_v1_RouteTargetReference_To_api_RouteTargetReference(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.AlternateBackends = nil
}
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(api.RoutePort)
if err := Convert_v1_RoutePort_To_api_RoutePort(*in, *out, s); err != nil {
return err
}
} else {
out.Port = nil
}
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(api.TLSConfig)
if err := Convert_v1_TLSConfig_To_api_TLSConfig(*in, *out, s); err != nil {
return err
}
} else {
out.TLS = nil
}
out.WildcardPolicy = api.WildcardPolicyType(in.WildcardPolicy)
return nil
}
func Convert_v1_RouteSpec_To_api_RouteSpec(in *RouteSpec, out *api.RouteSpec, s conversion.Scope) error {
return autoConvert_v1_RouteSpec_To_api_RouteSpec(in, out, s)
}
func autoConvert_api_RouteSpec_To_v1_RouteSpec(in *api.RouteSpec, out *RouteSpec, s conversion.Scope) error {
out.Host = in.Host
out.Path = in.Path
if err := Convert_api_RouteTargetReference_To_v1_RouteTargetReference(&in.To, &out.To, s); err != nil {
return err
}
if in.AlternateBackends != nil {
in, out := &in.AlternateBackends, &out.AlternateBackends
*out = make([]RouteTargetReference, len(*in))
for i := range *in {
if err := Convert_api_RouteTargetReference_To_v1_RouteTargetReference(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.AlternateBackends = nil
}
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(RoutePort)
if err := Convert_api_RoutePort_To_v1_RoutePort(*in, *out, s); err != nil {
return err
}
} else {
out.Port = nil
}
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(TLSConfig)
if err := Convert_api_TLSConfig_To_v1_TLSConfig(*in, *out, s); err != nil {
return err
}
} else {
out.TLS = nil
}
out.WildcardPolicy = WildcardPolicyType(in.WildcardPolicy)
return nil
}
func Convert_api_RouteSpec_To_v1_RouteSpec(in *api.RouteSpec, out *RouteSpec, s conversion.Scope) error {
return autoConvert_api_RouteSpec_To_v1_RouteSpec(in, out, s)
}
func autoConvert_v1_RouteStatus_To_api_RouteStatus(in *RouteStatus, out *api.RouteStatus, s conversion.Scope) error {
if in.Ingress != nil {
in, out := &in.Ingress, &out.Ingress
*out = make([]api.RouteIngress, len(*in))
for i := range *in {
if err := Convert_v1_RouteIngress_To_api_RouteIngress(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Ingress = nil
}
return nil
}
func Convert_v1_RouteStatus_To_api_RouteStatus(in *RouteStatus, out *api.RouteStatus, s conversion.Scope) error {
return autoConvert_v1_RouteStatus_To_api_RouteStatus(in, out, s)
}
func autoConvert_api_RouteStatus_To_v1_RouteStatus(in *api.RouteStatus, out *RouteStatus, s conversion.Scope) error {
if in.Ingress != nil {
in, out := &in.Ingress, &out.Ingress
*out = make([]RouteIngress, len(*in))
for i := range *in {
if err := Convert_api_RouteIngress_To_v1_RouteIngress(&(*in)[i], &(*out)[i], s); err != nil {
return err
}
}
} else {
out.Ingress = nil
}
return nil
}
func Convert_api_RouteStatus_To_v1_RouteStatus(in *api.RouteStatus, out *RouteStatus, s conversion.Scope) error {
return autoConvert_api_RouteStatus_To_v1_RouteStatus(in, out, s)
}
func autoConvert_v1_RouteTargetReference_To_api_RouteTargetReference(in *RouteTargetReference, out *api.RouteTargetReference, s conversion.Scope) error {
SetDefaults_RouteTargetReference(in)
out.Kind = in.Kind
out.Name = in.Name
out.Weight = in.Weight
return nil
}
func Convert_v1_RouteTargetReference_To_api_RouteTargetReference(in *RouteTargetReference, out *api.RouteTargetReference, s conversion.Scope) error {
return autoConvert_v1_RouteTargetReference_To_api_RouteTargetReference(in, out, s)
}
func autoConvert_api_RouteTargetReference_To_v1_RouteTargetReference(in *api.RouteTargetReference, out *RouteTargetReference, s conversion.Scope) error {
out.Kind = in.Kind
out.Name = in.Name
out.Weight = in.Weight
return nil
}
func Convert_api_RouteTargetReference_To_v1_RouteTargetReference(in *api.RouteTargetReference, out *RouteTargetReference, s conversion.Scope) error {
return autoConvert_api_RouteTargetReference_To_v1_RouteTargetReference(in, out, s)
}
func autoConvert_v1_RouterShard_To_api_RouterShard(in *RouterShard, out *api.RouterShard, s conversion.Scope) error {
out.ShardName = in.ShardName
out.DNSSuffix = in.DNSSuffix
return nil
}
func Convert_v1_RouterShard_To_api_RouterShard(in *RouterShard, out *api.RouterShard, s conversion.Scope) error {
return autoConvert_v1_RouterShard_To_api_RouterShard(in, out, s)
}
func autoConvert_api_RouterShard_To_v1_RouterShard(in *api.RouterShard, out *RouterShard, s conversion.Scope) error {
out.ShardName = in.ShardName
out.DNSSuffix = in.DNSSuffix
return nil
}
func Convert_api_RouterShard_To_v1_RouterShard(in *api.RouterShard, out *RouterShard, s conversion.Scope) error {
return autoConvert_api_RouterShard_To_v1_RouterShard(in, out, s)
}
func autoConvert_v1_TLSConfig_To_api_TLSConfig(in *TLSConfig, out *api.TLSConfig, s conversion.Scope) error {
SetDefaults_TLSConfig(in)
out.Termination = api.TLSTerminationType(in.Termination)
out.Certificate = in.Certificate
out.Key = in.Key
out.CACertificate = in.CACertificate
out.DestinationCACertificate = in.DestinationCACertificate
out.InsecureEdgeTerminationPolicy = api.InsecureEdgeTerminationPolicyType(in.InsecureEdgeTerminationPolicy)
return nil
}
func Convert_v1_TLSConfig_To_api_TLSConfig(in *TLSConfig, out *api.TLSConfig, s conversion.Scope) error {
return autoConvert_v1_TLSConfig_To_api_TLSConfig(in, out, s)
}
func autoConvert_api_TLSConfig_To_v1_TLSConfig(in *api.TLSConfig, out *TLSConfig, s conversion.Scope) error {
out.Termination = TLSTerminationType(in.Termination)
out.Certificate = in.Certificate
out.Key = in.Key
out.CACertificate = in.CACertificate
out.DestinationCACertificate = in.DestinationCACertificate
out.InsecureEdgeTerminationPolicy = InsecureEdgeTerminationPolicyType(in.InsecureEdgeTerminationPolicy)
return nil
}
func Convert_api_TLSConfig_To_v1_TLSConfig(in *api.TLSConfig, out *TLSConfig, s conversion.Scope) error {
return autoConvert_api_TLSConfig_To_v1_TLSConfig(in, out, s)
}

View File

@ -0,0 +1,222 @@
// +build !ignore_autogenerated_openshift
// This file was autogenerated by deepcopy-gen. Do not edit it manually!
package v1
import (
unversioned "k8s.io/kubernetes/pkg/api/unversioned"
api_v1 "k8s.io/kubernetes/pkg/api/v1"
conversion "k8s.io/kubernetes/pkg/conversion"
runtime "k8s.io/kubernetes/pkg/runtime"
reflect "reflect"
)
func init() {
SchemeBuilder.Register(RegisterDeepCopies)
}
// RegisterDeepCopies adds deep-copy functions to the given scheme. Public
// to allow building arbitrary schemes.
func RegisterDeepCopies(scheme *runtime.Scheme) error {
return scheme.AddGeneratedDeepCopyFuncs(
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_Route, InType: reflect.TypeOf(&Route{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_RouteIngress, InType: reflect.TypeOf(&RouteIngress{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_RouteIngressCondition, InType: reflect.TypeOf(&RouteIngressCondition{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_RouteList, InType: reflect.TypeOf(&RouteList{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_RoutePort, InType: reflect.TypeOf(&RoutePort{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_RouteSpec, InType: reflect.TypeOf(&RouteSpec{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_RouteStatus, InType: reflect.TypeOf(&RouteStatus{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_RouteTargetReference, InType: reflect.TypeOf(&RouteTargetReference{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_RouterShard, InType: reflect.TypeOf(&RouterShard{})},
conversion.GeneratedDeepCopyFunc{Fn: DeepCopy_v1_TLSConfig, InType: reflect.TypeOf(&TLSConfig{})},
)
}
func DeepCopy_v1_Route(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*Route)
out := out.(*Route)
out.TypeMeta = in.TypeMeta
if err := api_v1.DeepCopy_v1_ObjectMeta(&in.ObjectMeta, &out.ObjectMeta, c); err != nil {
return err
}
if err := DeepCopy_v1_RouteSpec(&in.Spec, &out.Spec, c); err != nil {
return err
}
if err := DeepCopy_v1_RouteStatus(&in.Status, &out.Status, c); err != nil {
return err
}
return nil
}
}
func DeepCopy_v1_RouteIngress(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RouteIngress)
out := out.(*RouteIngress)
out.Host = in.Host
out.RouterName = in.RouterName
if in.Conditions != nil {
in, out := &in.Conditions, &out.Conditions
*out = make([]RouteIngressCondition, len(*in))
for i := range *in {
if err := DeepCopy_v1_RouteIngressCondition(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.Conditions = nil
}
out.WildcardPolicy = in.WildcardPolicy
return nil
}
}
func DeepCopy_v1_RouteIngressCondition(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RouteIngressCondition)
out := out.(*RouteIngressCondition)
out.Type = in.Type
out.Status = in.Status
out.Reason = in.Reason
out.Message = in.Message
if in.LastTransitionTime != nil {
in, out := &in.LastTransitionTime, &out.LastTransitionTime
*out = new(unversioned.Time)
**out = (*in).DeepCopy()
} else {
out.LastTransitionTime = nil
}
return nil
}
}
func DeepCopy_v1_RouteList(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RouteList)
out := out.(*RouteList)
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Route, len(*in))
for i := range *in {
if err := DeepCopy_v1_Route(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.Items = nil
}
return nil
}
}
func DeepCopy_v1_RoutePort(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RoutePort)
out := out.(*RoutePort)
out.TargetPort = in.TargetPort
return nil
}
}
func DeepCopy_v1_RouteSpec(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RouteSpec)
out := out.(*RouteSpec)
out.Host = in.Host
out.Path = in.Path
if err := DeepCopy_v1_RouteTargetReference(&in.To, &out.To, c); err != nil {
return err
}
if in.AlternateBackends != nil {
in, out := &in.AlternateBackends, &out.AlternateBackends
*out = make([]RouteTargetReference, len(*in))
for i := range *in {
if err := DeepCopy_v1_RouteTargetReference(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.AlternateBackends = nil
}
if in.Port != nil {
in, out := &in.Port, &out.Port
*out = new(RoutePort)
**out = **in
} else {
out.Port = nil
}
if in.TLS != nil {
in, out := &in.TLS, &out.TLS
*out = new(TLSConfig)
**out = **in
} else {
out.TLS = nil
}
out.WildcardPolicy = in.WildcardPolicy
return nil
}
}
func DeepCopy_v1_RouteStatus(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RouteStatus)
out := out.(*RouteStatus)
if in.Ingress != nil {
in, out := &in.Ingress, &out.Ingress
*out = make([]RouteIngress, len(*in))
for i := range *in {
if err := DeepCopy_v1_RouteIngress(&(*in)[i], &(*out)[i], c); err != nil {
return err
}
}
} else {
out.Ingress = nil
}
return nil
}
}
func DeepCopy_v1_RouteTargetReference(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RouteTargetReference)
out := out.(*RouteTargetReference)
out.Kind = in.Kind
out.Name = in.Name
if in.Weight != nil {
in, out := &in.Weight, &out.Weight
*out = new(int32)
**out = **in
} else {
out.Weight = nil
}
return nil
}
}
func DeepCopy_v1_RouterShard(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*RouterShard)
out := out.(*RouterShard)
out.ShardName = in.ShardName
out.DNSSuffix = in.DNSSuffix
return nil
}
}
func DeepCopy_v1_TLSConfig(in interface{}, out interface{}, c *conversion.Cloner) error {
{
in := in.(*TLSConfig)
out := out.(*TLSConfig)
out.Termination = in.Termination
out.Certificate = in.Certificate
out.Key = in.Key
out.CACertificate = in.CACertificate
out.DestinationCACertificate = in.DestinationCACertificate
out.InsecureEdgeTerminationPolicy = in.InsecureEdgeTerminationPolicy
return nil
}
}

28
vendor/github.com/urfave/cli/LICENSE generated vendored
View File

@ -1,21 +1,21 @@
MIT License Copyright (C) 2013 Jeremy Saenz
All Rights Reserved.
Copyright (c) 2016 Jeremy Saenz & Contributors MIT LICENSE
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy of
of this software and associated documentation files (the "Software"), to deal this software and associated documentation files (the "Software"), to deal in
in the Software without restriction, including without limitation the rights the Software without restriction, including without limitation the rights to
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
copies of the Software, and to permit persons to whom the Software is the Software, and to permit persons to whom the Software is furnished to do so,
furnished to do so, subject to the following conditions: subject to the following conditions:
The above copyright notice and this permission notice shall be included in all The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software. copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SOFTWARE.

241
vendor/github.com/urfave/cli/app.go generated vendored
View File

@ -10,18 +10,6 @@ import (
"time" "time"
) )
var (
changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md"
appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL)
contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you."
errInvalidActionType = NewExitError("ERROR invalid Action type. "+
fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+
fmt.Sprintf("See %s", appActionDeprecationURL), 2)
)
// App is the main structure of a cli application. It is recommended that // App is the main structure of a cli application. It is recommended that
// an app be created with the cli.NewApp() function // an app be created with the cli.NewApp() function
type App struct { type App struct {
@ -37,8 +25,6 @@ type App struct {
ArgsUsage string ArgsUsage string
// Version of the program // Version of the program
Version string Version string
// Description of the program
Description string
// List of commands to execute // List of commands to execute
Commands []Command Commands []Command
// List of flags to parse // List of flags to parse
@ -49,26 +35,24 @@ type App struct {
HideHelp bool HideHelp bool
// Boolean to hide built-in version flag and the VERSION section of help // Boolean to hide built-in version flag and the VERSION section of help
HideVersion bool HideVersion bool
// Populate on app startup, only gettable through method Categories() // Populate on app startup, only gettable throught method Categories()
categories CommandCategories categories CommandCategories
// An action to execute when the bash-completion flag is set // An action to execute when the bash-completion flag is set
BashComplete BashCompleteFunc BashComplete func(context *Context)
// An action to execute before any subcommands are run, but after the context is ready // An action to execute before any subcommands are run, but after the context is ready
// If a non-nil error is returned, no subcommands are run // If a non-nil error is returned, no subcommands are run
Before BeforeFunc Before func(context *Context) error
// An action to execute after any subcommands are run, but after the subcommand has finished // An action to execute after any subcommands are run, but after the subcommand has finished
// It is run even if Action() panics // It is run even if Action() panics
After AfterFunc After func(context *Context) error
// The action to execute when no subcommands are specified // The action to execute when no subcommands are specified
// Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}` Action func(context *Context)
// *Note*: support for the deprecated `Action` signature will be removed in a future version
Action interface{}
// Execute this function if the proper command cannot be found // Execute this function if the proper command cannot be found
CommandNotFound CommandNotFoundFunc CommandNotFound func(context *Context, command string)
// Execute this function if an usage error occurs // Execute this function, if an usage error occurs. This is useful for displaying customized usage error messages.
OnUsageError OnUsageErrorFunc // This function is able to replace the original error messages.
// If this function is not set, the "Incorrect usage" is displayed and the execution is interrupted.
OnUsageError func(context *Context, err error, isSubcommand bool) error
// Compilation date // Compilation date
Compiled time.Time Compiled time.Time
// List of all authors who contributed // List of all authors who contributed
@ -81,12 +65,6 @@ type App struct {
Email string Email string
// Writer writer to write output to // Writer writer to write output to
Writer io.Writer Writer io.Writer
// ErrWriter writes error output
ErrWriter io.Writer
// Other custom info
Metadata map[string]interface{}
didSetup bool
} }
// Tries to find out when this binary was compiled. // Tries to find out when this binary was compiled.
@ -99,8 +77,7 @@ func compileTime() time.Time {
return info.ModTime() return info.ModTime()
} }
// NewApp creates a new cli Application with some reasonable defaults for Name, // Creates a new cli Application with some reasonable defaults for Name, Usage, Version and Action.
// Usage, Version and Action.
func NewApp() *App { func NewApp() *App {
return &App{ return &App{
Name: filepath.Base(os.Args[0]), Name: filepath.Base(os.Args[0]),
@ -115,16 +92,8 @@ func NewApp() *App {
} }
} }
// Setup runs initialization code to ensure all data structures are ready for // Entry point to the cli app. Parses the arguments slice and routes to the proper flag/args combination
// `Run` or inspection prior to `Run`. It is internally called by `Run`, but func (a *App) Run(arguments []string) (err error) {
// will return early if setup has already happened.
func (a *App) Setup() {
if a.didSetup {
return
}
a.didSetup = true
if a.Author != "" || a.Email != "" { if a.Author != "" || a.Email != "" {
a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email}) a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
} }
@ -138,6 +107,13 @@ func (a *App) Setup() {
} }
a.Commands = newCmds a.Commands = newCmds
a.categories = CommandCategories{}
for _, command := range a.Commands {
a.categories = a.categories.AddCommand(command.Category, command)
}
sort.Sort(a.categories)
// append help to commands
if a.Command(helpCommand.Name) == nil && !a.HideHelp { if a.Command(helpCommand.Name) == nil && !a.HideHelp {
a.Commands = append(a.Commands, helpCommand) a.Commands = append(a.Commands, helpCommand)
if (HelpFlag != BoolFlag{}) { if (HelpFlag != BoolFlag{}) {
@ -145,44 +121,17 @@ func (a *App) Setup() {
} }
} }
//append version/help flags
if a.EnableBashCompletion {
a.appendFlag(BashCompletionFlag)
}
if !a.HideVersion { if !a.HideVersion {
a.appendFlag(VersionFlag) a.appendFlag(VersionFlag)
} }
a.categories = CommandCategories{}
for _, command := range a.Commands {
a.categories = a.categories.AddCommand(command.Category, command)
}
sort.Sort(a.categories)
if a.Metadata == nil {
a.Metadata = make(map[string]interface{})
}
if a.Writer == nil {
a.Writer = os.Stdout
}
}
// Run is the entry point to the cli app. Parses the arguments slice and routes
// to the proper flag/args combination
func (a *App) Run(arguments []string) (err error) {
a.Setup()
// handle the completion flag separately from the flagset since
// completion could be attempted after a flag, but before its value was put
// on the command line. this causes the flagset to interpret the completion
// flag name as the value of the flag before it which is undesirable
// note that we can only do this because the shell autocomplete function
// always appends the completion flag at the end of the command
shellComplete, arguments := checkShellCompleteFlag(a, arguments)
// parse flags // parse flags
set, err := flagSet(a.Name, a.Flags) set := flagSet(a.Name, a.Flags)
if err != nil {
return err
}
set.SetOutput(ioutil.Discard) set.SetOutput(ioutil.Discard)
err = set.Parse(arguments[1:]) err = set.Parse(arguments[1:])
nerr := normalizeFlags(a.Flags, set) nerr := normalizeFlags(a.Flags, set)
@ -192,7 +141,6 @@ func (a *App) Run(arguments []string) (err error) {
ShowAppHelp(context) ShowAppHelp(context)
return nerr return nerr
} }
context.shellComplete = shellComplete
if checkCompletions(context) { if checkCompletions(context) {
return nil return nil
@ -201,12 +149,12 @@ func (a *App) Run(arguments []string) (err error) {
if err != nil { if err != nil {
if a.OnUsageError != nil { if a.OnUsageError != nil {
err := a.OnUsageError(context, err, false) err := a.OnUsageError(context, err, false)
HandleExitCoder(err) return err
} else {
fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
ShowAppHelp(context)
return err return err
} }
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
ShowAppHelp(context)
return err
} }
if !a.HideHelp && checkHelp(context) { if !a.HideHelp && checkHelp(context) {
@ -232,12 +180,10 @@ func (a *App) Run(arguments []string) (err error) {
} }
if a.Before != nil { if a.Before != nil {
beforeErr := a.Before(context) err = a.Before(context)
if beforeErr != nil { if err != nil {
fmt.Fprintf(a.Writer, "%v\n\n", beforeErr) fmt.Fprintf(a.Writer, "%v\n\n", err)
ShowAppHelp(context) ShowAppHelp(context)
HandleExitCoder(beforeErr)
err = beforeErr
return err return err
} }
} }
@ -251,31 +197,20 @@ func (a *App) Run(arguments []string) (err error) {
} }
} }
if a.Action == nil {
a.Action = helpCommand.Action
}
// Run default Action // Run default Action
err = HandleAction(a.Action, context) a.Action(context)
return nil
HandleExitCoder(err)
return err
} }
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned // Another entry point to the cli app, takes care of passing arguments and error handling
//
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
// to cli.App.Run. This will cause the application to exit with the given eror
// code in the cli.ExitCoder
func (a *App) RunAndExitOnError() { func (a *App) RunAndExitOnError() {
if err := a.Run(os.Args); err != nil { if err := a.Run(os.Args); err != nil {
fmt.Fprintln(a.errWriter(), err) fmt.Fprintln(os.Stderr, err)
OsExiter(1) os.Exit(1)
} }
} }
// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to // Invokes the subcommand given the context, parses ctx.Args() to generate command-specific flags
// generate command-specific flags
func (a *App) RunAsSubcommand(ctx *Context) (err error) { func (a *App) RunAsSubcommand(ctx *Context) (err error) {
// append help to commands // append help to commands
if len(a.Commands) > 0 { if len(a.Commands) > 0 {
@ -296,12 +231,13 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
} }
a.Commands = newCmds a.Commands = newCmds
// parse flags // append flags
set, err := flagSet(a.Name, a.Flags) if a.EnableBashCompletion {
if err != nil { a.appendFlag(BashCompletionFlag)
return err
} }
// parse flags
set := flagSet(a.Name, a.Flags)
set.SetOutput(ioutil.Discard) set.SetOutput(ioutil.Discard)
err = set.Parse(ctx.Args().Tail()) err = set.Parse(ctx.Args().Tail())
nerr := normalizeFlags(a.Flags, set) nerr := normalizeFlags(a.Flags, set)
@ -325,12 +261,12 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
if err != nil { if err != nil {
if a.OnUsageError != nil { if a.OnUsageError != nil {
err = a.OnUsageError(context, err, true) err = a.OnUsageError(context, err, true)
HandleExitCoder(err) return err
} else {
fmt.Fprintf(a.Writer, "%s\n\n", "Incorrect Usage.")
ShowSubcommandHelp(context)
return err return err
} }
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
ShowSubcommandHelp(context)
return err
} }
if len(a.Commands) > 0 { if len(a.Commands) > 0 {
@ -347,7 +283,6 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
defer func() { defer func() {
afterErr := a.After(context) afterErr := a.After(context)
if afterErr != nil { if afterErr != nil {
HandleExitCoder(err)
if err != nil { if err != nil {
err = NewMultiError(err, afterErr) err = NewMultiError(err, afterErr)
} else { } else {
@ -358,10 +293,8 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
} }
if a.Before != nil { if a.Before != nil {
beforeErr := a.Before(context) err := a.Before(context)
if beforeErr != nil { if err != nil {
HandleExitCoder(beforeErr)
err = beforeErr
return err return err
} }
} }
@ -376,13 +309,12 @@ func (a *App) RunAsSubcommand(ctx *Context) (err error) {
} }
// Run default Action // Run default Action
err = HandleAction(a.Action, context) a.Action(context)
HandleExitCoder(err) return nil
return err
} }
// Command returns the named command on App. Returns nil if the command does not exist // Returns the named command on App. Returns nil if the command does not exist
func (a *App) Command(name string) *Command { func (a *App) Command(name string) *Command {
for _, c := range a.Commands { for _, c := range a.Commands {
if c.HasName(name) { if c.HasName(name) {
@ -393,46 +325,11 @@ func (a *App) Command(name string) *Command {
return nil return nil
} }
// Categories returns a slice containing all the categories with the commands they contain // Returnes the array containing all the categories with the commands they contain
func (a *App) Categories() CommandCategories { func (a *App) Categories() CommandCategories {
return a.categories return a.categories
} }
// VisibleCategories returns a slice of categories and commands that are
// Hidden=false
func (a *App) VisibleCategories() []*CommandCategory {
ret := []*CommandCategory{}
for _, category := range a.categories {
if visible := func() *CommandCategory {
for _, command := range category.Commands {
if !command.Hidden {
return category
}
}
return nil
}(); visible != nil {
ret = append(ret, visible)
}
}
return ret
}
// VisibleCommands returns a slice of the Commands with Hidden=false
func (a *App) VisibleCommands() []Command {
ret := []Command{}
for _, command := range a.Commands {
if !command.Hidden {
ret = append(ret, command)
}
}
return ret
}
// VisibleFlags returns a slice of the Flags with Hidden=false
func (a *App) VisibleFlags() []Flag {
return visibleFlags(a.Flags)
}
func (a *App) hasFlag(flag Flag) bool { func (a *App) hasFlag(flag Flag) bool {
for _, f := range a.Flags { for _, f := range a.Flags {
if flag == f { if flag == f {
@ -443,16 +340,6 @@ func (a *App) hasFlag(flag Flag) bool {
return false return false
} }
func (a *App) errWriter() io.Writer {
// When the app ErrWriter is nil use the package level one.
if a.ErrWriter == nil {
return ErrWriter
}
return a.ErrWriter
}
func (a *App) appendFlag(flag Flag) { func (a *App) appendFlag(flag Flag) {
if !a.hasFlag(flag) { if !a.hasFlag(flag) {
a.Flags = append(a.Flags, flag) a.Flags = append(a.Flags, flag)
@ -469,24 +356,8 @@ type Author struct {
func (a Author) String() string { func (a Author) String() string {
e := "" e := ""
if a.Email != "" { if a.Email != "" {
e = " <" + a.Email + ">" e = "<" + a.Email + "> "
} }
return fmt.Sprintf("%v%v", a.Name, e) return fmt.Sprintf("%v %v", a.Name, e)
}
// HandleAction attempts to figure out which Action signature was used. If
// it's an ActionFunc or a func with the legacy signature for Action, the func
// is run!
func HandleAction(action interface{}, context *Context) (err error) {
if a, ok := action.(ActionFunc); ok {
return a(context)
} else if a, ok := action.(func(*Context) error); ok {
return a(context)
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
a(context)
return nil
} else {
return errInvalidActionType
}
} }

View File

@ -1,9 +1,7 @@
package cli package cli
// CommandCategories is a slice of *CommandCategory.
type CommandCategories []*CommandCategory type CommandCategories []*CommandCategory
// CommandCategory is a category containing commands.
type CommandCategory struct { type CommandCategory struct {
Name string Name string
Commands Commands Commands Commands
@ -21,7 +19,6 @@ func (c CommandCategories) Swap(i, j int) {
c[i], c[j] = c[j], c[i] c[i], c[j] = c[j], c[i]
} }
// AddCommand adds a command to a category.
func (c CommandCategories) AddCommand(category string, command Command) CommandCategories { func (c CommandCategories) AddCommand(category string, command Command) CommandCategories {
for _, commandCategory := range c { for _, commandCategory := range c {
if commandCategory.Name == category { if commandCategory.Name == category {
@ -31,14 +28,3 @@ func (c CommandCategories) AddCommand(category string, command Command) CommandC
} }
return append(c, &CommandCategory{Name: category, Commands: []Command{command}}) return append(c, &CommandCategory{Name: category, Commands: []Command{command}})
} }
// VisibleCommands returns a slice of the Commands with Hidden=false
func (c *CommandCategory) VisibleCommands() []Command {
ret := []Command{}
for _, command := range c.Commands {
if !command.Hidden {
ret = append(ret, command)
}
}
return ret
}

23
vendor/github.com/urfave/cli/cli.go generated vendored
View File

@ -10,7 +10,7 @@
// app := cli.NewApp() // app := cli.NewApp()
// app.Name = "greet" // app.Name = "greet"
// app.Usage = "say a greeting" // app.Usage = "say a greeting"
// app.Action = func(c *cli.Context) error { // app.Action = func(c *cli.Context) {
// println("Greetings") // println("Greetings")
// } // }
// //
@ -18,4 +18,23 @@
// } // }
package cli package cli
//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go import (
"strings"
)
type MultiError struct {
Errors []error
}
func NewMultiError(err ...error) MultiError {
return MultiError{Errors: err}
}
func (m MultiError) Error() string {
errs := make([]string, len(m.Errors))
for i, err := range m.Errors {
errs[i] = err.Error()
}
return strings.Join(errs, "\n")
}

View File

@ -26,42 +26,34 @@ type Command struct {
// The category the command is part of // The category the command is part of
Category string Category string
// The function to call when checking for bash command completions // The function to call when checking for bash command completions
BashComplete BashCompleteFunc BashComplete func(context *Context)
// An action to execute before any sub-subcommands are run, but after the context is ready // An action to execute before any sub-subcommands are run, but after the context is ready
// If a non-nil error is returned, no sub-subcommands are run // If a non-nil error is returned, no sub-subcommands are run
Before BeforeFunc Before func(context *Context) error
// An action to execute after any subcommands are run, but after the subcommand has finished // An action to execute after any subcommands are run, but before the subcommand has finished
// It is run even if Action() panics // It is run even if Action() panics
After AfterFunc After func(context *Context) error
// The function to call when this command is invoked // The function to call when this command is invoked
Action interface{} Action func(context *Context)
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind // Execute this function, if an usage error occurs. This is useful for displaying customized usage error messages.
// of deprecation period has passed, maybe? // This function is able to replace the original error messages.
// If this function is not set, the "Incorrect usage" is displayed and the execution is interrupted.
// Execute this function if a usage error occurs. OnUsageError func(context *Context, err error) error
OnUsageError OnUsageErrorFunc
// List of child commands // List of child commands
Subcommands Commands Subcommands Commands
// List of flags to parse // List of flags to parse
Flags []Flag Flags []Flag
// Treat all flags as normal arguments if true // Treat all flags as normal arguments if true
SkipFlagParsing bool SkipFlagParsing bool
// Skip argument reordering which attempts to move flags before arguments,
// but only works if all flags appear after all arguments. This behavior was
// removed n version 2 since it only works under specific conditions so we
// backport here by exposing it as an option for compatibility.
SkipArgReorder bool
// Boolean to hide built-in help command // Boolean to hide built-in help command
HideHelp bool HideHelp bool
// Boolean to hide this command from help or completion
Hidden bool
// Full name of command for help, defaults to full command name, including parent commands. // Full name of command for help, defaults to full command name, including parent commands.
HelpName string HelpName string
commandNamePath []string commandNamePath []string
} }
// FullName returns the full name of the command. // Returns the full name of the command.
// For subcommands this ensures that parent commands are part of the command path // For subcommands this ensures that parent commands are part of the command path
func (c Command) FullName() string { func (c Command) FullName() string {
if c.commandNamePath == nil { if c.commandNamePath == nil {
@ -70,10 +62,9 @@ func (c Command) FullName() string {
return strings.Join(c.commandNamePath, " ") return strings.Join(c.commandNamePath, " ")
} }
// Commands is a slice of Command
type Commands []Command type Commands []Command
// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags // Invokes the command given the context, parses ctx.Args() to generate command-specific flags
func (c Command) Run(ctx *Context) (err error) { func (c Command) Run(ctx *Context) (err error) {
if len(c.Subcommands) > 0 { if len(c.Subcommands) > 0 {
return c.startApp(ctx) return c.startApp(ctx)
@ -87,15 +78,14 @@ func (c Command) Run(ctx *Context) (err error) {
) )
} }
set, err := flagSet(c.Name, c.Flags) if ctx.App.EnableBashCompletion {
if err != nil { c.Flags = append(c.Flags, BashCompletionFlag)
return err
} }
set := flagSet(c.Name, c.Flags)
set.SetOutput(ioutil.Discard) set.SetOutput(ioutil.Discard)
if c.SkipFlagParsing { if !c.SkipFlagParsing {
err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
} else if !c.SkipArgReorder {
firstFlagIndex := -1 firstFlagIndex := -1
terminatorIndex := -1 terminatorIndex := -1
for index, arg := range ctx.Args() { for index, arg := range ctx.Args() {
@ -128,7 +118,21 @@ func (c Command) Run(ctx *Context) (err error) {
err = set.Parse(ctx.Args().Tail()) err = set.Parse(ctx.Args().Tail())
} }
} else { } else {
err = set.Parse(ctx.Args().Tail()) if c.SkipFlagParsing {
err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
}
}
if err != nil {
if c.OnUsageError != nil {
err := c.OnUsageError(ctx, err)
return err
} else {
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage.")
fmt.Fprintln(ctx.App.Writer)
ShowCommandHelp(ctx, c.Name)
return err
}
} }
nerr := normalizeFlags(c.Flags, set) nerr := normalizeFlags(c.Flags, set)
@ -138,24 +142,12 @@ func (c Command) Run(ctx *Context) (err error) {
ShowCommandHelp(ctx, c.Name) ShowCommandHelp(ctx, c.Name)
return nerr return nerr
} }
context := NewContext(ctx.App, set, ctx) context := NewContext(ctx.App, set, ctx)
if checkCommandCompletions(context, c.Name) { if checkCommandCompletions(context, c.Name) {
return nil return nil
} }
if err != nil {
if c.OnUsageError != nil {
err := c.OnUsageError(ctx, err, false)
HandleExitCoder(err)
return err
}
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage:", err.Error())
fmt.Fprintln(ctx.App.Writer)
ShowCommandHelp(ctx, c.Name)
return err
}
if checkCommandHelp(context, c.Name) { if checkCommandHelp(context, c.Name) {
return nil return nil
} }
@ -164,7 +156,6 @@ func (c Command) Run(ctx *Context) (err error) {
defer func() { defer func() {
afterErr := c.After(context) afterErr := c.After(context)
if afterErr != nil { if afterErr != nil {
HandleExitCoder(err)
if err != nil { if err != nil {
err = NewMultiError(err, afterErr) err = NewMultiError(err, afterErr)
} else { } else {
@ -175,30 +166,20 @@ func (c Command) Run(ctx *Context) (err error) {
} }
if c.Before != nil { if c.Before != nil {
err = c.Before(context) err := c.Before(context)
if err != nil { if err != nil {
fmt.Fprintln(ctx.App.Writer, err) fmt.Fprintln(ctx.App.Writer, err)
fmt.Fprintln(ctx.App.Writer) fmt.Fprintln(ctx.App.Writer)
ShowCommandHelp(ctx, c.Name) ShowCommandHelp(ctx, c.Name)
HandleExitCoder(err)
return err return err
} }
} }
if c.Action == nil {
c.Action = helpSubcommand.Action
}
context.Command = c context.Command = c
err = HandleAction(c.Action, context) c.Action(context)
return nil
if err != nil {
HandleExitCoder(err)
}
return err
} }
// Names returns the names including short names and aliases.
func (c Command) Names() []string { func (c Command) Names() []string {
names := []string{c.Name} names := []string{c.Name}
@ -209,7 +190,7 @@ func (c Command) Names() []string {
return append(names, c.Aliases...) return append(names, c.Aliases...)
} }
// HasName returns true if Command.Name or Command.ShortName matches given name // Returns true if Command.Name or Command.ShortName matches given name
func (c Command) HasName(name string) bool { func (c Command) HasName(name string) bool {
for _, n := range c.Names() { for _, n := range c.Names() {
if n == name { if n == name {
@ -221,7 +202,7 @@ func (c Command) HasName(name string) bool {
func (c Command) startApp(ctx *Context) error { func (c Command) startApp(ctx *Context) error {
app := NewApp() app := NewApp()
app.Metadata = ctx.App.Metadata
// set the name and usage // set the name and usage
app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name) app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
if c.HelpName == "" { if c.HelpName == "" {
@ -279,8 +260,3 @@ func (c Command) startApp(ctx *Context) error {
return app.RunAsSubcommand(ctx) return app.RunAsSubcommand(ctx)
} }
// VisibleFlags returns a slice of the Flags with Hidden=false
func (c Command) VisibleFlags() []Flag {
return visibleFlags(c.Flags)
}

View File

@ -3,9 +3,9 @@ package cli
import ( import (
"errors" "errors"
"flag" "flag"
"reflect" "strconv"
"strings" "strings"
"syscall" "time"
) )
// Context is a type that is passed through to // Context is a type that is passed through to
@ -13,119 +13,154 @@ import (
// can be used to retrieve context-specific Args and // can be used to retrieve context-specific Args and
// parsed command-line options. // parsed command-line options.
type Context struct { type Context struct {
App *App App *App
Command Command Command Command
shellComplete bool flagSet *flag.FlagSet
flagSet *flag.FlagSet setFlags map[string]bool
setFlags map[string]bool globalSetFlags map[string]bool
parentContext *Context parentContext *Context
} }
// NewContext creates a new context. For use in when invoking an App or Command action. // Creates a new context. For use in when invoking an App or Command action.
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context { func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
c := &Context{App: app, flagSet: set, parentContext: parentCtx} return &Context{App: app, flagSet: set, parentContext: parentCtx}
}
if parentCtx != nil { // Looks up the value of a local int flag, returns 0 if no int flag exists
c.shellComplete = parentCtx.shellComplete func (c *Context) Int(name string) int {
return lookupInt(name, c.flagSet)
}
// Looks up the value of a local time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) Duration(name string) time.Duration {
return lookupDuration(name, c.flagSet)
}
// Looks up the value of a local float64 flag, returns 0 if no float64 flag exists
func (c *Context) Float64(name string) float64 {
return lookupFloat64(name, c.flagSet)
}
// Looks up the value of a local bool flag, returns false if no bool flag exists
func (c *Context) Bool(name string) bool {
return lookupBool(name, c.flagSet)
}
// Looks up the value of a local boolT flag, returns false if no bool flag exists
func (c *Context) BoolT(name string) bool {
return lookupBoolT(name, c.flagSet)
}
// Looks up the value of a local string flag, returns "" if no string flag exists
func (c *Context) String(name string) string {
return lookupString(name, c.flagSet)
}
// Looks up the value of a local string slice flag, returns nil if no string slice flag exists
func (c *Context) StringSlice(name string) []string {
return lookupStringSlice(name, c.flagSet)
}
// Looks up the value of a local int slice flag, returns nil if no int slice flag exists
func (c *Context) IntSlice(name string) []int {
return lookupIntSlice(name, c.flagSet)
}
// Looks up the value of a local generic flag, returns nil if no generic flag exists
func (c *Context) Generic(name string) interface{} {
return lookupGeneric(name, c.flagSet)
}
// Looks up the value of a global int flag, returns 0 if no int flag exists
func (c *Context) GlobalInt(name string) int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt(name, fs)
} }
return 0
return c
} }
// NumFlags returns the number of flags set // Looks up the value of a global time.Duration flag, returns 0 if no time.Duration flag exists
func (c *Context) NumFlags() int { func (c *Context) GlobalDuration(name string) time.Duration {
return c.flagSet.NFlag() if fs := lookupGlobalFlagSet(name, c); fs != nil {
} return lookupDuration(name, fs)
// Set sets a context flag to a value.
func (c *Context) Set(name, value string) error {
return c.flagSet.Set(name, value)
}
// GlobalSet sets a context flag to a value on the global flagset
func (c *Context) GlobalSet(name, value string) error {
return globalContext(c).flagSet.Set(name, value)
}
// IsSet determines if the flag was actually set
func (c *Context) IsSet(name string) bool {
if c.setFlags == nil {
c.setFlags = make(map[string]bool)
c.flagSet.Visit(func(f *flag.Flag) {
c.setFlags[f.Name] = true
})
c.flagSet.VisitAll(func(f *flag.Flag) {
if _, ok := c.setFlags[f.Name]; ok {
return
}
c.setFlags[f.Name] = false
})
// XXX hack to support IsSet for flags with EnvVar
//
// There isn't an easy way to do this with the current implementation since
// whether a flag was set via an environment variable is very difficult to
// determine here. Instead, we intend to introduce a backwards incompatible
// change in version 2 to add `IsSet` to the Flag interface to push the
// responsibility closer to where the information required to determine
// whether a flag is set by non-standard means such as environment
// variables is avaliable.
//
// See https://github.com/urfave/cli/issues/294 for additional discussion
flags := c.Command.Flags
if c.Command.Name == "" { // cannot == Command{} since it contains slice types
if c.App != nil {
flags = c.App.Flags
}
}
for _, f := range flags {
eachName(f.GetName(), func(name string) {
if isSet, ok := c.setFlags[name]; isSet || !ok {
return
}
val := reflect.ValueOf(f)
if val.Kind() == reflect.Ptr {
val = val.Elem()
}
envVarValue := val.FieldByName("EnvVar")
if !envVarValue.IsValid() {
return
}
eachName(envVarValue.String(), func(envVar string) {
envVar = strings.TrimSpace(envVar)
if _, ok := syscall.Getenv(envVar); ok {
c.setFlags[name] = true
return
}
})
})
}
} }
return 0
return c.setFlags[name]
} }
// GlobalIsSet determines if the global flag was actually set // Looks up the value of a global bool flag, returns false if no bool flag exists
func (c *Context) GlobalIsSet(name string) bool { func (c *Context) GlobalBool(name string) bool {
ctx := c if fs := lookupGlobalFlagSet(name, c); fs != nil {
if ctx.parentContext != nil { return lookupBool(name, fs)
ctx = ctx.parentContext
}
for ; ctx != nil; ctx = ctx.parentContext {
if ctx.IsSet(name) {
return true
}
} }
return false return false
} }
// FlagNames returns a slice of flag names used in this context. // Looks up the value of a global string flag, returns "" if no string flag exists
func (c *Context) GlobalString(name string) string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupString(name, fs)
}
return ""
}
// Looks up the value of a global string slice flag, returns nil if no string slice flag exists
func (c *Context) GlobalStringSlice(name string) []string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupStringSlice(name, fs)
}
return nil
}
// Looks up the value of a global int slice flag, returns nil if no int slice flag exists
func (c *Context) GlobalIntSlice(name string) []int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupIntSlice(name, fs)
}
return nil
}
// Looks up the value of a global generic flag, returns nil if no generic flag exists
func (c *Context) GlobalGeneric(name string) interface{} {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupGeneric(name, fs)
}
return nil
}
// Returns the number of flags set
func (c *Context) NumFlags() int {
return c.flagSet.NFlag()
}
// Determines if the flag was actually set
func (c *Context) IsSet(name string) bool {
if c.setFlags == nil {
c.setFlags = make(map[string]bool)
c.flagSet.Visit(func(f *flag.Flag) {
c.setFlags[f.Name] = true
})
}
return c.setFlags[name] == true
}
// Determines if the global flag was actually set
func (c *Context) GlobalIsSet(name string) bool {
if c.globalSetFlags == nil {
c.globalSetFlags = make(map[string]bool)
ctx := c
if ctx.parentContext != nil {
ctx = ctx.parentContext
}
for ; ctx != nil && c.globalSetFlags[name] == false; ctx = ctx.parentContext {
ctx.flagSet.Visit(func(f *flag.Flag) {
c.globalSetFlags[f.Name] = true
})
}
}
return c.globalSetFlags[name]
}
// Returns a slice of flag names used in this context.
func (c *Context) FlagNames() (names []string) { func (c *Context) FlagNames() (names []string) {
for _, flag := range c.Command.Flags { for _, flag := range c.Command.Flags {
name := strings.Split(flag.GetName(), ",")[0] name := strings.Split(flag.GetName(), ",")[0]
@ -137,7 +172,7 @@ func (c *Context) FlagNames() (names []string) {
return return
} }
// GlobalFlagNames returns a slice of global flag names used by the app. // Returns a slice of global flag names used by the app.
func (c *Context) GlobalFlagNames() (names []string) { func (c *Context) GlobalFlagNames() (names []string) {
for _, flag := range c.App.Flags { for _, flag := range c.App.Flags {
name := strings.Split(flag.GetName(), ",")[0] name := strings.Split(flag.GetName(), ",")[0]
@ -149,31 +184,25 @@ func (c *Context) GlobalFlagNames() (names []string) {
return return
} }
// Parent returns the parent context, if any // Returns the parent context, if any
func (c *Context) Parent() *Context { func (c *Context) Parent() *Context {
return c.parentContext return c.parentContext
} }
// value returns the value of the flag coressponding to `name`
func (c *Context) value(name string) interface{} {
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
}
// Args contains apps console arguments
type Args []string type Args []string
// Args returns the command line arguments associated with the context. // Returns the command line arguments associated with the context.
func (c *Context) Args() Args { func (c *Context) Args() Args {
args := Args(c.flagSet.Args()) args := Args(c.flagSet.Args())
return args return args
} }
// NArg returns the number of the command line arguments. // Returns the number of the command line arguments.
func (c *Context) NArg() int { func (c *Context) NArg() int {
return len(c.Args()) return len(c.Args())
} }
// Get returns the nth argument, or else a blank string // Returns the nth argument, or else a blank string
func (a Args) Get(n int) string { func (a Args) Get(n int) string {
if len(a) > n { if len(a) > n {
return a[n] return a[n]
@ -181,12 +210,12 @@ func (a Args) Get(n int) string {
return "" return ""
} }
// First returns the first argument, or else a blank string // Returns the first argument, or else a blank string
func (a Args) First() string { func (a Args) First() string {
return a.Get(0) return a.Get(0)
} }
// Tail returns the rest of the arguments (not the first one) // Return the rest of the arguments (not the first one)
// or else an empty string slice // or else an empty string slice
func (a Args) Tail() []string { func (a Args) Tail() []string {
if len(a) >= 2 { if len(a) >= 2 {
@ -195,12 +224,12 @@ func (a Args) Tail() []string {
return []string{} return []string{}
} }
// Present checks if there are any arguments present // Checks if there are any arguments present
func (a Args) Present() bool { func (a Args) Present() bool {
return len(a) != 0 return len(a) != 0
} }
// Swap swaps arguments at the given indexes // Swaps arguments at the given indexes
func (a Args) Swap(from, to int) error { func (a Args) Swap(from, to int) error {
if from >= len(a) || to >= len(a) { if from >= len(a) || to >= len(a) {
return errors.New("index out of range") return errors.New("index out of range")
@ -209,19 +238,6 @@ func (a Args) Swap(from, to int) error {
return nil return nil
} }
func globalContext(ctx *Context) *Context {
if ctx == nil {
return nil
}
for {
if ctx.parentContext == nil {
return ctx
}
ctx = ctx.parentContext
}
}
func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet { func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
if ctx.parentContext != nil { if ctx.parentContext != nil {
ctx = ctx.parentContext ctx = ctx.parentContext
@ -234,6 +250,107 @@ func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
return nil return nil
} }
func lookupInt(name string, set *flag.FlagSet) int {
f := set.Lookup(name)
if f != nil {
val, err := strconv.Atoi(f.Value.String())
if err != nil {
return 0
}
return val
}
return 0
}
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
f := set.Lookup(name)
if f != nil {
val, err := time.ParseDuration(f.Value.String())
if err == nil {
return val
}
}
return 0
}
func lookupFloat64(name string, set *flag.FlagSet) float64 {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseFloat(f.Value.String(), 64)
if err != nil {
return 0
}
return val
}
return 0
}
func lookupString(name string, set *flag.FlagSet) string {
f := set.Lookup(name)
if f != nil {
return f.Value.String()
}
return ""
}
func lookupStringSlice(name string, set *flag.FlagSet) []string {
f := set.Lookup(name)
if f != nil {
return (f.Value.(*StringSlice)).Value()
}
return nil
}
func lookupIntSlice(name string, set *flag.FlagSet) []int {
f := set.Lookup(name)
if f != nil {
return (f.Value.(*IntSlice)).Value()
}
return nil
}
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
f := set.Lookup(name)
if f != nil {
return f.Value
}
return nil
}
func lookupBool(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseBool(f.Value.String())
if err != nil {
return false
}
return val
}
return false
}
func lookupBoolT(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
val, err := strconv.ParseBool(f.Value.String())
if err != nil {
return true
}
return val
}
return false
}
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) { func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
switch ff.Value.(type) { switch ff.Value.(type) {
case *StringSlice: case *StringSlice:

View File

@ -1,110 +0,0 @@
package cli
import (
"fmt"
"io"
"os"
"strings"
)
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
var OsExiter = os.Exit
// ErrWriter is used to write errors to the user. This can be anything
// implementing the io.Writer interface and defaults to os.Stderr.
var ErrWriter io.Writer = os.Stderr
// MultiError is an error that wraps multiple errors.
type MultiError struct {
Errors []error
}
// NewMultiError creates a new MultiError. Pass in one or more errors.
func NewMultiError(err ...error) MultiError {
return MultiError{Errors: err}
}
// Error implements the error interface.
func (m MultiError) Error() string {
errs := make([]string, len(m.Errors))
for i, err := range m.Errors {
errs[i] = err.Error()
}
return strings.Join(errs, "\n")
}
type ErrorFormatter interface {
Format(s fmt.State, verb rune)
}
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
// code
type ExitCoder interface {
error
ExitCode() int
}
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
type ExitError struct {
exitCode int
message interface{}
}
// NewExitError makes a new *ExitError
func NewExitError(message interface{}, exitCode int) *ExitError {
return &ExitError{
exitCode: exitCode,
message: message,
}
}
// Error returns the string message, fulfilling the interface required by
// `error`
func (ee *ExitError) Error() string {
return fmt.Sprintf("%v", ee.message)
}
// ExitCode returns the exit code, fulfilling the interface required by
// `ExitCoder`
func (ee *ExitError) ExitCode() int {
return ee.exitCode
}
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
// given exit code. If the given error is a MultiError, then this func is
// called on all members of the Errors slice.
func HandleExitCoder(err error) {
if err == nil {
return
}
if exitErr, ok := err.(ExitCoder); ok {
if err.Error() != "" {
if _, ok := exitErr.(ErrorFormatter); ok {
fmt.Fprintf(ErrWriter, "%+v\n", err)
} else {
fmt.Fprintln(ErrWriter, err)
}
}
OsExiter(exitErr.ExitCode())
return
}
if multiErr, ok := err.(MultiError); ok {
for _, merr := range multiErr.Errors {
HandleExitCoder(merr)
}
return
}
if err.Error() != "" {
if _, ok := err.(ErrorFormatter); ok {
fmt.Fprintf(ErrWriter, "%+v\n", err)
} else {
fmt.Fprintln(ErrWriter, err)
}
}
OsExiter(1)
}

679
vendor/github.com/urfave/cli/flag.go generated vendored
View File

@ -3,29 +3,25 @@ package cli
import ( import (
"flag" "flag"
"fmt" "fmt"
"reflect" "os"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"syscall"
"time" "time"
) )
const defaultPlaceholder = "value" // This flag enables bash-completion for all commands and subcommands
// BashCompletionFlag enables bash-completion for all commands and subcommands
var BashCompletionFlag = BoolFlag{ var BashCompletionFlag = BoolFlag{
Name: "generate-bash-completion", Name: "generate-bash-completion",
Hidden: true,
} }
// VersionFlag prints the version for the application // This flag prints the version for the application
var VersionFlag = BoolFlag{ var VersionFlag = BoolFlag{
Name: "version, v", Name: "version, v",
Usage: "print the version", Usage: "print the version",
} }
// HelpFlag prints the help for all commands and subcommands // This flag prints the help for all commands and subcommands
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand // Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
// unless HideHelp is set to true) // unless HideHelp is set to true)
var HelpFlag = BoolFlag{ var HelpFlag = BoolFlag{
@ -33,25 +29,6 @@ var HelpFlag = BoolFlag{
Usage: "show help", Usage: "show help",
} }
// FlagStringer converts a flag definition to a string. This is used by help
// to display a flag.
var FlagStringer FlagStringFunc = stringifyFlag
// FlagsByName is a slice of Flag.
type FlagsByName []Flag
func (f FlagsByName) Len() int {
return len(f)
}
func (f FlagsByName) Less(i, j int) bool {
return f[i].GetName() < f[j].GetName()
}
func (f FlagsByName) Swap(i, j int) {
f[i], f[j] = f[j], f[i]
}
// Flag is a common interface related to parsing flags in cli. // Flag is a common interface related to parsing flags in cli.
// For more advanced flag parsing techniques, it is recommended that // For more advanced flag parsing techniques, it is recommended that
// this interface be implemented. // this interface be implemented.
@ -62,29 +39,13 @@ type Flag interface {
GetName() string GetName() string
} }
// errorableFlag is an interface that allows us to return errors during apply func flagSet(name string, flags []Flag) *flag.FlagSet {
// it allows flags defined in this library to return errors in a fashion backwards compatible
// TODO remove in v2 and modify the existing Flag interface to return errors
type errorableFlag interface {
Flag
ApplyWithError(*flag.FlagSet) error
}
func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
set := flag.NewFlagSet(name, flag.ContinueOnError) set := flag.NewFlagSet(name, flag.ContinueOnError)
for _, f := range flags { for _, f := range flags {
//TODO remove in v2 when errorableFlag is removed f.Apply(set)
if ef, ok := f.(errorableFlag); ok {
if err := ef.ApplyWithError(set); err != nil {
return nil, err
}
} else {
f.Apply(set)
}
} }
return set, nil return set
} }
func eachName(longName string, fn func(string)) { func eachName(longName string, fn func(string)) {
@ -101,24 +62,41 @@ type Generic interface {
String() string String() string
} }
// Apply takes the flagset and calls Set on the generic flag with the value // GenericFlag is the flag type for types implementing Generic
// provided by the user for parsing by the flag type GenericFlag struct {
// Ignores parsing errors Name string
func (f GenericFlag) Apply(set *flag.FlagSet) { Value Generic
f.ApplyWithError(set) Usage string
EnvVar string
} }
// ApplyWithError takes the flagset and calls Set on the generic flag with the value // String returns the string representation of the generic flag to display the
// help text to the user (uses the String() method of the generic flag to show
// the value)
func (f GenericFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s %v\t%v", prefixedNames(f.Name), f.FormatValueHelp(), f.Usage))
}
func (f GenericFlag) FormatValueHelp() string {
if f.Value == nil {
return ""
}
s := f.Value.String()
if len(s) == 0 {
return ""
}
return fmt.Sprintf("\"%s\"", s)
}
// Apply takes the flagset and calls Set on the generic flag with the value
// provided by the user for parsing by the flag // provided by the user for parsing by the flag
func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error { func (f GenericFlag) Apply(set *flag.FlagSet) {
val := f.Value val := f.Value
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
if err := val.Set(envVal); err != nil { val.Set(envVal)
return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err)
}
break break
} }
} }
@ -127,11 +105,13 @@ func (f GenericFlag) ApplyWithError(set *flag.FlagSet) error {
eachName(f.Name, func(name string) { eachName(f.Name, func(name string) {
set.Var(f.Value, name, f.Usage) set.Var(f.Value, name, f.Usage)
}) })
return nil
} }
// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter func (f GenericFlag) GetName() string {
return f.Name
}
// StringSlice is an opaque type for []string to satisfy flag.Value
type StringSlice []string type StringSlice []string
// Set appends the string value to the list of values // Set appends the string value to the list of values
@ -150,29 +130,32 @@ func (f *StringSlice) Value() []string {
return *f return *f
} }
// Get returns the slice of strings set by this flag // StringSlice is a string flag that can be specified multiple times on the
func (f *StringSlice) Get() interface{} { // command-line
return *f type StringSliceFlag struct {
Name string
Value *StringSlice
Usage string
EnvVar string
}
// String returns the usage
func (f StringSliceFlag) String() string {
firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
pref := prefixFor(firstName)
return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
} }
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
// Ignores errors
func (f StringSliceFlag) Apply(set *flag.FlagSet) { func (f StringSliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
newVal := &StringSlice{} newVal := &StringSlice{}
for _, s := range strings.Split(envVal, ",") { for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s) s = strings.TrimSpace(s)
if err := newVal.Set(s); err != nil { newVal.Set(s)
return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err)
}
} }
f.Value = newVal f.Value = newVal
break break
@ -186,11 +169,13 @@ func (f StringSliceFlag) ApplyWithError(set *flag.FlagSet) error {
} }
set.Var(f.Value, name, f.Usage) set.Var(f.Value, name, f.Usage)
}) })
return nil
} }
// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter func (f StringSliceFlag) GetName() string {
return f.Name
}
// StringSlice is an opaque type for []int to satisfy flag.Value
type IntSlice []int type IntSlice []int
// Set parses the value into an integer and appends it to the list of values // Set parses the value into an integer and appends it to the list of values
@ -198,14 +183,15 @@ func (f *IntSlice) Set(value string) error {
tmp, err := strconv.Atoi(value) tmp, err := strconv.Atoi(value)
if err != nil { if err != nil {
return err return err
} else {
*f = append(*f, tmp)
} }
*f = append(*f, tmp)
return nil return nil
} }
// String returns a readable representation of this value (for usage defaults) // String returns a readable representation of this value (for usage defaults)
func (f *IntSlice) String() string { func (f *IntSlice) String() string {
return fmt.Sprintf("%#v", *f) return fmt.Sprintf("%d", *f)
} }
// Value returns the slice of ints set by this flag // Value returns the slice of ints set by this flag
@ -213,28 +199,34 @@ func (f *IntSlice) Value() []int {
return *f return *f
} }
// Get returns the slice of ints set by this flag // IntSliceFlag is an int flag that can be specified multiple times on the
func (f *IntSlice) Get() interface{} { // command-line
return *f type IntSliceFlag struct {
Name string
Value *IntSlice
Usage string
EnvVar string
}
// String returns the usage
func (f IntSliceFlag) String() string {
firstName := strings.Trim(strings.Split(f.Name, ",")[0], " ")
pref := prefixFor(firstName)
return withEnvHint(f.EnvVar, fmt.Sprintf("%s [%v]\t%v", prefixedNames(f.Name), pref+firstName+" option "+pref+firstName+" option", f.Usage))
} }
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
// Ignores errors
func (f IntSliceFlag) Apply(set *flag.FlagSet) { func (f IntSliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
newVal := &IntSlice{} newVal := &IntSlice{}
for _, s := range strings.Split(envVal, ",") { for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s) s = strings.TrimSpace(s)
if err := newVal.Set(s); err != nil { err := newVal.Set(s)
return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err) if err != nil {
fmt.Fprintf(os.Stderr, err.Error())
} }
} }
f.Value = newVal f.Value = newVal
@ -249,96 +241,36 @@ func (f IntSliceFlag) ApplyWithError(set *flag.FlagSet) error {
} }
set.Var(f.Value, name, f.Usage) set.Var(f.Value, name, f.Usage)
}) })
return nil
} }
// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter func (f IntSliceFlag) GetName() string {
type Int64Slice []int64 return f.Name
}
// Set parses the value into an integer and appends it to the list of values // BoolFlag is a switch that defaults to false
func (f *Int64Slice) Set(value string) error { type BoolFlag struct {
tmp, err := strconv.ParseInt(value, 10, 64) Name string
if err != nil { Usage string
return err EnvVar string
} Destination *bool
*f = append(*f, tmp)
return nil
} }
// String returns a readable representation of this value (for usage defaults) // String returns a readable representation of this value (for usage defaults)
func (f *Int64Slice) String() string { func (f BoolFlag) String() string {
return fmt.Sprintf("%#v", *f) return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
}
// Value returns the slice of ints set by this flag
func (f *Int64Slice) Value() []int64 {
return *f
}
// Get returns the slice of ints set by this flag
func (f *Int64Slice) Get() interface{} {
return *f
} }
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
// Ignores errors
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Int64SliceFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok {
newVal := &Int64Slice{}
for _, s := range strings.Split(envVal, ",") {
s = strings.TrimSpace(s)
if err := newVal.Set(s); err != nil {
return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err)
}
}
f.Value = newVal
break
}
}
}
eachName(f.Name, func(name string) {
if f.Value == nil {
f.Value = &Int64Slice{}
}
set.Var(f.Value, name, f.Usage)
})
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f BoolFlag) Apply(set *flag.FlagSet) { func (f BoolFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error {
val := false val := false
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
if envVal == "" {
val = false
break
}
envValBool, err := strconv.ParseBool(envVal) envValBool, err := strconv.ParseBool(envVal)
if err != nil { if err == nil {
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) val = envValBool
} }
val = envValBool
break break
} }
} }
@ -351,35 +283,38 @@ func (f BoolFlag) ApplyWithError(set *flag.FlagSet) error {
} }
set.Bool(name, val, f.Usage) set.Bool(name, val, f.Usage)
}) })
}
return nil func (f BoolFlag) GetName() string {
return f.Name
}
// BoolTFlag this represents a boolean flag that is true by default, but can
// still be set to false by --some-flag=false
type BoolTFlag struct {
Name string
Usage string
EnvVar string
Destination *bool
}
// String returns a readable representation of this value (for usage defaults)
func (f BoolTFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s\t%v", prefixedNames(f.Name), f.Usage))
} }
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
// Ignores errors
func (f BoolTFlag) Apply(set *flag.FlagSet) { func (f BoolTFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
val := true val := true
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
if envVal == "" { envValBool, err := strconv.ParseBool(envVal)
val = false if err == nil {
val = envValBool
break break
} }
envValBool, err := strconv.ParseBool(envVal)
if err != nil {
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
}
val = envValBool
break
} }
} }
} }
@ -391,22 +326,40 @@ func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error {
} }
set.Bool(name, val, f.Usage) set.Bool(name, val, f.Usage)
}) })
}
return nil func (f BoolTFlag) GetName() string {
return f.Name
}
// StringFlag represents a flag that takes as string value
type StringFlag struct {
Name string
Value string
Usage string
EnvVar string
Destination *string
}
// String returns the usage
func (f StringFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s %v\t%v", prefixedNames(f.Name), f.FormatValueHelp(), f.Usage))
}
func (f StringFlag) FormatValueHelp() string {
s := f.Value
if len(s) == 0 {
return ""
}
return fmt.Sprintf("\"%s\"", s)
} }
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
// Ignores errors
func (f StringFlag) Apply(set *flag.FlagSet) { func (f StringFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f StringFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
f.Value = envVal f.Value = envVal
break break
} }
@ -420,28 +373,38 @@ func (f StringFlag) ApplyWithError(set *flag.FlagSet) error {
} }
set.String(name, f.Value, f.Usage) set.String(name, f.Value, f.Usage)
}) })
}
return nil func (f StringFlag) GetName() string {
return f.Name
}
// IntFlag is a flag that takes an integer
// Errors if the value provided cannot be parsed
type IntFlag struct {
Name string
Value int
Usage string
EnvVar string
Destination *int
}
// String returns the usage
func (f IntFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
} }
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
// Ignores errors
func (f IntFlag) Apply(set *flag.FlagSet) { func (f IntFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f IntFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
envValInt, err := strconv.ParseInt(envVal, 0, 64) envValInt, err := strconv.ParseInt(envVal, 0, 64)
if err != nil { if err == nil {
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err) f.Value = int(envValInt)
break
} }
f.Value = int(envValInt)
break
} }
} }
} }
@ -453,131 +416,38 @@ func (f IntFlag) ApplyWithError(set *flag.FlagSet) error {
} }
set.Int(name, f.Value, f.Usage) set.Int(name, f.Value, f.Usage)
}) })
}
return nil func (f IntFlag) GetName() string {
return f.Name
}
// DurationFlag is a flag that takes a duration specified in Go's duration
// format: https://golang.org/pkg/time/#ParseDuration
type DurationFlag struct {
Name string
Value time.Duration
Usage string
EnvVar string
Destination *time.Duration
}
// String returns a readable representation of this value (for usage defaults)
func (f DurationFlag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
} }
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
// Ignores errors
func (f Int64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Int64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok {
envValInt, err := strconv.ParseInt(envVal, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
}
f.Value = envValInt
break
}
}
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.Int64Var(f.Destination, name, f.Value, f.Usage)
return
}
set.Int64(name, f.Value, f.Usage)
})
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f UintFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f UintFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok {
envValInt, err := strconv.ParseUint(envVal, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err)
}
f.Value = uint(envValInt)
break
}
}
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.UintVar(f.Destination, name, f.Value, f.Usage)
return
}
set.Uint(name, f.Value, f.Usage)
})
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f Uint64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Uint64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok {
envValInt, err := strconv.ParseUint(envVal, 0, 64)
if err != nil {
return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err)
}
f.Value = uint64(envValInt)
break
}
}
}
eachName(f.Name, func(name string) {
if f.Destination != nil {
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
return
}
set.Uint64(name, f.Value, f.Usage)
})
return nil
}
// Apply populates the flag given the flag set and environment
// Ignores errors
func (f DurationFlag) Apply(set *flag.FlagSet) { func (f DurationFlag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
envValDuration, err := time.ParseDuration(envVal) envValDuration, err := time.ParseDuration(envVal)
if err != nil { if err == nil {
return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err) f.Value = envValDuration
break
} }
f.Value = envValDuration
break
} }
} }
} }
@ -589,29 +459,37 @@ func (f DurationFlag) ApplyWithError(set *flag.FlagSet) error {
} }
set.Duration(name, f.Value, f.Usage) set.Duration(name, f.Value, f.Usage)
}) })
}
return nil func (f DurationFlag) GetName() string {
return f.Name
}
// Float64Flag is a flag that takes an float value
// Errors if the value provided cannot be parsed
type Float64Flag struct {
Name string
Value float64
Usage string
EnvVar string
Destination *float64
}
// String returns the usage
func (f Float64Flag) String() string {
return withEnvHint(f.EnvVar, fmt.Sprintf("%s \"%v\"\t%v", prefixedNames(f.Name), f.Value, f.Usage))
} }
// Apply populates the flag given the flag set and environment // Apply populates the flag given the flag set and environment
// Ignores errors
func (f Float64Flag) Apply(set *flag.FlagSet) { func (f Float64Flag) Apply(set *flag.FlagSet) {
f.ApplyWithError(set)
}
// ApplyWithError populates the flag given the flag set and environment
func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error {
if f.EnvVar != "" { if f.EnvVar != "" {
for _, envVar := range strings.Split(f.EnvVar, ",") { for _, envVar := range strings.Split(f.EnvVar, ",") {
envVar = strings.TrimSpace(envVar) envVar = strings.TrimSpace(envVar)
if envVal, ok := syscall.Getenv(envVar); ok { if envVal := os.Getenv(envVar); envVal != "" {
envValFloat, err := strconv.ParseFloat(envVal, 10) envValFloat, err := strconv.ParseFloat(envVal, 10)
if err != nil { if err == nil {
return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err) f.Value = float64(envValFloat)
} }
f.Value = float64(envValFloat)
break
} }
} }
} }
@ -623,18 +501,10 @@ func (f Float64Flag) ApplyWithError(set *flag.FlagSet) error {
} }
set.Float64(name, f.Value, f.Usage) set.Float64(name, f.Value, f.Usage)
}) })
return nil
} }
func visibleFlags(fl []Flag) []Flag { func (f Float64Flag) GetName() string {
visible := []Flag{} return f.Name
for _, flag := range fl {
if !flagValue(flag).FieldByName("Hidden").Bool() {
visible = append(visible, flag)
}
}
return visible
} }
func prefixFor(name string) (prefix string) { func prefixFor(name string) (prefix string) {
@ -647,37 +517,16 @@ func prefixFor(name string) (prefix string) {
return return
} }
// Returns the placeholder, if any, and the unquoted usage string. func prefixedNames(fullName string) (prefixed string) {
func unquoteUsage(usage string) (string, string) {
for i := 0; i < len(usage); i++ {
if usage[i] == '`' {
for j := i + 1; j < len(usage); j++ {
if usage[j] == '`' {
name := usage[i+1 : j]
usage = usage[:i] + name + usage[j+1:]
return name, usage
}
}
break
}
}
return "", usage
}
func prefixedNames(fullName, placeholder string) string {
var prefixed string
parts := strings.Split(fullName, ",") parts := strings.Split(fullName, ",")
for i, name := range parts { for i, name := range parts {
name = strings.Trim(name, " ") name = strings.Trim(name, " ")
prefixed += prefixFor(name) + name prefixed += prefixFor(name) + name
if placeholder != "" {
prefixed += " " + placeholder
}
if i < len(parts)-1 { if i < len(parts)-1 {
prefixed += ", " prefixed += ", "
} }
} }
return prefixed return
} }
func withEnvHint(envVar, str string) string { func withEnvHint(envVar, str string) string {
@ -695,105 +544,3 @@ func withEnvHint(envVar, str string) string {
} }
return str + envText return str + envText
} }
func flagValue(f Flag) reflect.Value {
fv := reflect.ValueOf(f)
for fv.Kind() == reflect.Ptr {
fv = reflect.Indirect(fv)
}
return fv
}
func stringifyFlag(f Flag) string {
fv := flagValue(f)
switch f.(type) {
case IntSliceFlag:
return withEnvHint(fv.FieldByName("EnvVar").String(),
stringifyIntSliceFlag(f.(IntSliceFlag)))
case Int64SliceFlag:
return withEnvHint(fv.FieldByName("EnvVar").String(),
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
case StringSliceFlag:
return withEnvHint(fv.FieldByName("EnvVar").String(),
stringifyStringSliceFlag(f.(StringSliceFlag)))
}
placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
needsPlaceholder := false
defaultValueString := ""
val := fv.FieldByName("Value")
if val.IsValid() {
needsPlaceholder = true
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
if val.Kind() == reflect.String && val.String() != "" {
defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
}
}
if defaultValueString == " (default: )" {
defaultValueString = ""
}
if needsPlaceholder && placeholder == "" {
placeholder = defaultPlaceholder
}
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
return withEnvHint(fv.FieldByName("EnvVar").String(),
fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
}
func stringifyIntSliceFlag(f IntSliceFlag) string {
defaultVals := []string{}
if f.Value != nil && len(f.Value.Value()) > 0 {
for _, i := range f.Value.Value() {
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
}
}
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}
func stringifyInt64SliceFlag(f Int64SliceFlag) string {
defaultVals := []string{}
if f.Value != nil && len(f.Value.Value()) > 0 {
for _, i := range f.Value.Value() {
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
}
}
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}
func stringifyStringSliceFlag(f StringSliceFlag) string {
defaultVals := []string{}
if f.Value != nil && len(f.Value.Value()) > 0 {
for _, s := range f.Value.Value() {
if len(s) > 0 {
defaultVals = append(defaultVals, fmt.Sprintf("%q", s))
}
}
}
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
}
func stringifySliceFlag(usage, name string, defaultVals []string) string {
placeholder, usage := unquoteUsage(usage)
if placeholder == "" {
placeholder = defaultPlaceholder
}
defaultVal := ""
if len(defaultVals) > 0 {
defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
}
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal))
return fmt.Sprintf("%s\t%s", prefixedNames(name, placeholder), usageWithDefault)
}

View File

@ -1,627 +0,0 @@
package cli
import (
"flag"
"strconv"
"time"
)
// WARNING: This file is generated!
// BoolFlag is a flag with type bool
type BoolFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Destination *bool
}
// String returns a readable representation of this value
// (for usage defaults)
func (f BoolFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f BoolFlag) GetName() string {
return f.Name
}
// Bool looks up the value of a local BoolFlag, returns
// false if not found
func (c *Context) Bool(name string) bool {
return lookupBool(name, c.flagSet)
}
// GlobalBool looks up the value of a global BoolFlag, returns
// false if not found
func (c *Context) GlobalBool(name string) bool {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupBool(name, fs)
}
return false
}
func lookupBool(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseBool(f.Value.String())
if err != nil {
return false
}
return parsed
}
return false
}
// BoolTFlag is a flag with type bool that is true by default
type BoolTFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Destination *bool
}
// String returns a readable representation of this value
// (for usage defaults)
func (f BoolTFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f BoolTFlag) GetName() string {
return f.Name
}
// BoolT looks up the value of a local BoolTFlag, returns
// false if not found
func (c *Context) BoolT(name string) bool {
return lookupBoolT(name, c.flagSet)
}
// GlobalBoolT looks up the value of a global BoolTFlag, returns
// false if not found
func (c *Context) GlobalBoolT(name string) bool {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupBoolT(name, fs)
}
return false
}
func lookupBoolT(name string, set *flag.FlagSet) bool {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseBool(f.Value.String())
if err != nil {
return false
}
return parsed
}
return false
}
// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
type DurationFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value time.Duration
Destination *time.Duration
}
// String returns a readable representation of this value
// (for usage defaults)
func (f DurationFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f DurationFlag) GetName() string {
return f.Name
}
// Duration looks up the value of a local DurationFlag, returns
// 0 if not found
func (c *Context) Duration(name string) time.Duration {
return lookupDuration(name, c.flagSet)
}
// GlobalDuration looks up the value of a global DurationFlag, returns
// 0 if not found
func (c *Context) GlobalDuration(name string) time.Duration {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupDuration(name, fs)
}
return 0
}
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
f := set.Lookup(name)
if f != nil {
parsed, err := time.ParseDuration(f.Value.String())
if err != nil {
return 0
}
return parsed
}
return 0
}
// Float64Flag is a flag with type float64
type Float64Flag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value float64
Destination *float64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Float64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Float64Flag) GetName() string {
return f.Name
}
// Float64 looks up the value of a local Float64Flag, returns
// 0 if not found
func (c *Context) Float64(name string) float64 {
return lookupFloat64(name, c.flagSet)
}
// GlobalFloat64 looks up the value of a global Float64Flag, returns
// 0 if not found
func (c *Context) GlobalFloat64(name string) float64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupFloat64(name, fs)
}
return 0
}
func lookupFloat64(name string, set *flag.FlagSet) float64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseFloat(f.Value.String(), 64)
if err != nil {
return 0
}
return parsed
}
return 0
}
// GenericFlag is a flag with type Generic
type GenericFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value Generic
}
// String returns a readable representation of this value
// (for usage defaults)
func (f GenericFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f GenericFlag) GetName() string {
return f.Name
}
// Generic looks up the value of a local GenericFlag, returns
// nil if not found
func (c *Context) Generic(name string) interface{} {
return lookupGeneric(name, c.flagSet)
}
// GlobalGeneric looks up the value of a global GenericFlag, returns
// nil if not found
func (c *Context) GlobalGeneric(name string) interface{} {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupGeneric(name, fs)
}
return nil
}
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
f := set.Lookup(name)
if f != nil {
parsed, err := f.Value, error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}
// Int64Flag is a flag with type int64
type Int64Flag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value int64
Destination *int64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Int64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Int64Flag) GetName() string {
return f.Name
}
// Int64 looks up the value of a local Int64Flag, returns
// 0 if not found
func (c *Context) Int64(name string) int64 {
return lookupInt64(name, c.flagSet)
}
// GlobalInt64 looks up the value of a global Int64Flag, returns
// 0 if not found
func (c *Context) GlobalInt64(name string) int64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt64(name, fs)
}
return 0
}
func lookupInt64(name string, set *flag.FlagSet) int64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return parsed
}
return 0
}
// IntFlag is a flag with type int
type IntFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value int
Destination *int
}
// String returns a readable representation of this value
// (for usage defaults)
func (f IntFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f IntFlag) GetName() string {
return f.Name
}
// Int looks up the value of a local IntFlag, returns
// 0 if not found
func (c *Context) Int(name string) int {
return lookupInt(name, c.flagSet)
}
// GlobalInt looks up the value of a global IntFlag, returns
// 0 if not found
func (c *Context) GlobalInt(name string) int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt(name, fs)
}
return 0
}
func lookupInt(name string, set *flag.FlagSet) int {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return int(parsed)
}
return 0
}
// IntSliceFlag is a flag with type *IntSlice
type IntSliceFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value *IntSlice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f IntSliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f IntSliceFlag) GetName() string {
return f.Name
}
// IntSlice looks up the value of a local IntSliceFlag, returns
// nil if not found
func (c *Context) IntSlice(name string) []int {
return lookupIntSlice(name, c.flagSet)
}
// GlobalIntSlice looks up the value of a global IntSliceFlag, returns
// nil if not found
func (c *Context) GlobalIntSlice(name string) []int {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupIntSlice(name, fs)
}
return nil
}
func lookupIntSlice(name string, set *flag.FlagSet) []int {
f := set.Lookup(name)
if f != nil {
parsed, err := (f.Value.(*IntSlice)).Value(), error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}
// Int64SliceFlag is a flag with type *Int64Slice
type Int64SliceFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value *Int64Slice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Int64SliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Int64SliceFlag) GetName() string {
return f.Name
}
// Int64Slice looks up the value of a local Int64SliceFlag, returns
// nil if not found
func (c *Context) Int64Slice(name string) []int64 {
return lookupInt64Slice(name, c.flagSet)
}
// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns
// nil if not found
func (c *Context) GlobalInt64Slice(name string) []int64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupInt64Slice(name, fs)
}
return nil
}
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
f := set.Lookup(name)
if f != nil {
parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}
// StringFlag is a flag with type string
type StringFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value string
Destination *string
}
// String returns a readable representation of this value
// (for usage defaults)
func (f StringFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f StringFlag) GetName() string {
return f.Name
}
// String looks up the value of a local StringFlag, returns
// "" if not found
func (c *Context) String(name string) string {
return lookupString(name, c.flagSet)
}
// GlobalString looks up the value of a global StringFlag, returns
// "" if not found
func (c *Context) GlobalString(name string) string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupString(name, fs)
}
return ""
}
func lookupString(name string, set *flag.FlagSet) string {
f := set.Lookup(name)
if f != nil {
parsed, err := f.Value.String(), error(nil)
if err != nil {
return ""
}
return parsed
}
return ""
}
// StringSliceFlag is a flag with type *StringSlice
type StringSliceFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value *StringSlice
}
// String returns a readable representation of this value
// (for usage defaults)
func (f StringSliceFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f StringSliceFlag) GetName() string {
return f.Name
}
// StringSlice looks up the value of a local StringSliceFlag, returns
// nil if not found
func (c *Context) StringSlice(name string) []string {
return lookupStringSlice(name, c.flagSet)
}
// GlobalStringSlice looks up the value of a global StringSliceFlag, returns
// nil if not found
func (c *Context) GlobalStringSlice(name string) []string {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupStringSlice(name, fs)
}
return nil
}
func lookupStringSlice(name string, set *flag.FlagSet) []string {
f := set.Lookup(name)
if f != nil {
parsed, err := (f.Value.(*StringSlice)).Value(), error(nil)
if err != nil {
return nil
}
return parsed
}
return nil
}
// Uint64Flag is a flag with type uint64
type Uint64Flag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value uint64
Destination *uint64
}
// String returns a readable representation of this value
// (for usage defaults)
func (f Uint64Flag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f Uint64Flag) GetName() string {
return f.Name
}
// Uint64 looks up the value of a local Uint64Flag, returns
// 0 if not found
func (c *Context) Uint64(name string) uint64 {
return lookupUint64(name, c.flagSet)
}
// GlobalUint64 looks up the value of a global Uint64Flag, returns
// 0 if not found
func (c *Context) GlobalUint64(name string) uint64 {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint64(name, fs)
}
return 0
}
func lookupUint64(name string, set *flag.FlagSet) uint64 {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return parsed
}
return 0
}
// UintFlag is a flag with type uint
type UintFlag struct {
Name string
Usage string
EnvVar string
Hidden bool
Value uint
Destination *uint
}
// String returns a readable representation of this value
// (for usage defaults)
func (f UintFlag) String() string {
return FlagStringer(f)
}
// GetName returns the name of the flag
func (f UintFlag) GetName() string {
return f.Name
}
// Uint looks up the value of a local UintFlag, returns
// 0 if not found
func (c *Context) Uint(name string) uint {
return lookupUint(name, c.flagSet)
}
// GlobalUint looks up the value of a global UintFlag, returns
// 0 if not found
func (c *Context) GlobalUint(name string) uint {
if fs := lookupGlobalFlagSet(name, c); fs != nil {
return lookupUint(name, fs)
}
return 0
}
func lookupUint(name string, set *flag.FlagSet) uint {
f := set.Lookup(name)
if f != nil {
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
if err != nil {
return 0
}
return uint(parsed)
}
return 0
}

View File

@ -1,28 +0,0 @@
package cli
// BashCompleteFunc is an action to execute when the bash-completion flag is set
type BashCompleteFunc func(*Context)
// BeforeFunc is an action to execute before any subcommands are run, but after
// the context is ready if a non-nil error is returned, no subcommands are run
type BeforeFunc func(*Context) error
// AfterFunc is an action to execute after any subcommands are run, but after the
// subcommand has finished it is run even if Action() panics
type AfterFunc func(*Context) error
// ActionFunc is the action to execute when no subcommands are specified
type ActionFunc func(*Context) error
// CommandNotFoundFunc is executed if the proper command cannot be found
type CommandNotFoundFunc func(*Context, string)
// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying
// customized usage error messages. This function is able to replace the
// original error messages. If this function is not set, the "Incorrect usage"
// is displayed and the execution is interrupted.
type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
// FlagStringFunc is used by the help generation to display a flag, which is
// expected to be a single line.
type FlagStringFunc func(Flag) string

171
vendor/github.com/urfave/cli/help.go generated vendored
View File

@ -3,78 +3,73 @@ package cli
import ( import (
"fmt" "fmt"
"io" "io"
"os"
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"text/template" "text/template"
) )
// AppHelpTemplate is the text template for the Default help topic. // The text template for the Default help topic.
// cli.go uses text/template to render templates. You can // cli.go uses text/template to render templates. You can
// render custom help text by setting this variable. // render custom help text by setting this variable.
var AppHelpTemplate = `NAME: var AppHelpTemplate = `NAME:
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}} {{.Name}} - {{.Usage}}
USAGE: USAGE:
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}} {{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .Flags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}
{{if .Version}}{{if not .HideVersion}}
VERSION: VERSION:
{{.Version}}{{end}}{{end}}{{if .Description}} {{.Version}}
{{end}}{{end}}{{if len .Authors}}
DESCRIPTION: AUTHOR(S):
{{.Description}}{{end}}{{if len .Authors}} {{range .Authors}}{{ . }}{{end}}
{{end}}{{if .Commands}}
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}: COMMANDS:{{range .Categories}}{{if .Name}}
{{range $index, $author := .Authors}}{{if $index}} {{.Name}}{{ ":" }}{{end}}{{range .Commands}}
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}} {{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}{{end}}
{{end}}{{end}}{{if .Flags}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
{{.Name}}:{{end}}{{range .VisibleCommands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
GLOBAL OPTIONS: GLOBAL OPTIONS:
{{range $index, $option := .VisibleFlags}}{{if $index}} {{range .Flags}}{{.}}
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}} {{end}}{{end}}{{if .Copyright }}
COPYRIGHT: COPYRIGHT:
{{.Copyright}}{{end}} {{.Copyright}}
{{end}}
` `
// CommandHelpTemplate is the text template for the command help topic. // The text template for the command help topic.
// cli.go uses text/template to render templates. You can // cli.go uses text/template to render templates. You can
// render custom help text by setting this variable. // render custom help text by setting this variable.
var CommandHelpTemplate = `NAME: var CommandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}} {{.HelpName}} - {{.Usage}}
USAGE: USAGE:
{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}} {{.HelpName}}{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}}
CATEGORY: CATEGORY:
{{.Category}}{{end}}{{if .Description}} {{.Category}}{{end}}{{if .Description}}
DESCRIPTION: DESCRIPTION:
{{.Description}}{{end}}{{if .VisibleFlags}} {{.Description}}{{end}}{{if .Flags}}
OPTIONS: OPTIONS:
{{range .VisibleFlags}}{{.}} {{range .Flags}}{{.}}
{{end}}{{end}} {{end}}{{ end }}
` `
// SubcommandHelpTemplate is the text template for the subcommand help topic. // The text template for the subcommand help topic.
// cli.go uses text/template to render templates. You can // cli.go uses text/template to render templates. You can
// render custom help text by setting this variable. // render custom help text by setting this variable.
var SubcommandHelpTemplate = `NAME: var SubcommandHelpTemplate = `NAME:
{{.HelpName}} - {{.Usage}} {{.HelpName}} - {{.Usage}}
USAGE: USAGE:
{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}} {{.HelpName}} command{{if .Flags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
COMMANDS:{{range .VisibleCategories}}{{if .Name}} COMMANDS:{{range .Categories}}{{if .Name}}
{{.Name}}:{{end}}{{range .VisibleCommands}} {{.Name}}{{ ":" }}{{end}}{{range .Commands}}
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}} {{.Name}}{{with .ShortName}}, {{.}}{{end}}{{ "\t" }}{{.Usage}}{{end}}
{{end}}{{if .VisibleFlags}} {{end}}{{if .Flags}}
OPTIONS: OPTIONS:
{{range .VisibleFlags}}{{.}} {{range .Flags}}{{.}}
{{end}}{{end}} {{end}}{{end}}
` `
@ -83,14 +78,13 @@ var helpCommand = Command{
Aliases: []string{"h"}, Aliases: []string{"h"},
Usage: "Shows a list of commands or help for one command", Usage: "Shows a list of commands or help for one command",
ArgsUsage: "[command]", ArgsUsage: "[command]",
Action: func(c *Context) error { Action: func(c *Context) {
args := c.Args() args := c.Args()
if args.Present() { if args.Present() {
return ShowCommandHelp(c, args.First()) ShowCommandHelp(c, args.First())
} else {
ShowAppHelp(c)
} }
ShowAppHelp(c)
return nil
}, },
} }
@ -99,74 +93,65 @@ var helpSubcommand = Command{
Aliases: []string{"h"}, Aliases: []string{"h"},
Usage: "Shows a list of commands or help for one command", Usage: "Shows a list of commands or help for one command",
ArgsUsage: "[command]", ArgsUsage: "[command]",
Action: func(c *Context) error { Action: func(c *Context) {
args := c.Args() args := c.Args()
if args.Present() { if args.Present() {
return ShowCommandHelp(c, args.First()) ShowCommandHelp(c, args.First())
} else {
ShowSubcommandHelp(c)
} }
return ShowSubcommandHelp(c)
}, },
} }
// Prints help for the App or Command // Prints help for the App or Command
type helpPrinter func(w io.Writer, templ string, data interface{}) type helpPrinter func(w io.Writer, templ string, data interface{})
// HelpPrinter is a function that writes the help output. If not set a default
// is used. The function signature is:
// func(w io.Writer, templ string, data interface{})
var HelpPrinter helpPrinter = printHelp var HelpPrinter helpPrinter = printHelp
// VersionPrinter prints the version for the App // Prints version for the App
var VersionPrinter = printVersion var VersionPrinter = printVersion
// ShowAppHelp is an action that displays the help. func ShowAppHelp(c *Context) {
func ShowAppHelp(c *Context) error {
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App) HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
return nil
} }
// DefaultAppComplete prints the list of subcommands as the default app completion method // Prints the list of subcommands as the default app completion method
func DefaultAppComplete(c *Context) { func DefaultAppComplete(c *Context) {
for _, command := range c.App.Commands { for _, command := range c.App.Commands {
if command.Hidden {
continue
}
for _, name := range command.Names() { for _, name := range command.Names() {
fmt.Fprintln(c.App.Writer, name) fmt.Fprintln(c.App.Writer, name)
} }
} }
} }
// ShowCommandHelp prints help for the given command // Prints help for the given command
func ShowCommandHelp(ctx *Context, command string) error { func ShowCommandHelp(ctx *Context, command string) {
// show the subcommand help for a command with subcommands // show the subcommand help for a command with subcommands
if command == "" { if command == "" {
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App) HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
return nil return
} }
for _, c := range ctx.App.Commands { for _, c := range ctx.App.Commands {
if c.HasName(command) { if c.HasName(command) {
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c) HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
return nil return
} }
} }
if ctx.App.CommandNotFound == nil { if ctx.App.CommandNotFound != nil {
return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3) ctx.App.CommandNotFound(ctx, command)
} else {
fmt.Fprintf(ctx.App.Writer, "No help topic for '%v'\n", command)
} }
ctx.App.CommandNotFound(ctx, command)
return nil
} }
// ShowSubcommandHelp prints help for the given subcommand // Prints help for the given subcommand
func ShowSubcommandHelp(c *Context) error { func ShowSubcommandHelp(c *Context) {
return ShowCommandHelp(c, c.Command.Name) ShowCommandHelp(c, c.Command.Name)
} }
// ShowVersion prints the version number of the App // Prints the version number of the App
func ShowVersion(c *Context) { func ShowVersion(c *Context) {
VersionPrinter(c) VersionPrinter(c)
} }
@ -175,7 +160,7 @@ func printVersion(c *Context) {
fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version) fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
} }
// ShowCompletions prints the lists of commands within a given context // Prints the lists of commands within a given context
func ShowCompletions(c *Context) { func ShowCompletions(c *Context) {
a := c.App a := c.App
if a != nil && a.BashComplete != nil { if a != nil && a.BashComplete != nil {
@ -183,7 +168,7 @@ func ShowCompletions(c *Context) {
} }
} }
// ShowCommandCompletions prints the custom completions for a given command // Prints the custom completions for a given command
func ShowCommandCompletions(ctx *Context, command string) { func ShowCommandCompletions(ctx *Context, command string) {
c := ctx.App.Command(command) c := ctx.App.Command(command)
if c != nil && c.BashComplete != nil { if c != nil && c.BashComplete != nil {
@ -196,15 +181,12 @@ func printHelp(out io.Writer, templ string, data interface{}) {
"join": strings.Join, "join": strings.Join,
} }
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0) w := tabwriter.NewWriter(out, 0, 8, 1, '\t', 0)
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ)) t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
err := t.Execute(w, data) err := t.Execute(w, data)
if err != nil { if err != nil {
// If the writer is closed, t.Execute will fail, and there's nothing // If the writer is closed, t.Execute will fail, and there's nothing
// we can do to recover. // we can do to recover. We could send this to os.Stderr if we need.
if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" {
fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err)
}
return return
} }
w.Flush() w.Flush()
@ -244,7 +226,7 @@ func checkCommandHelp(c *Context, name string) bool {
} }
func checkSubcommandHelp(c *Context) bool { func checkSubcommandHelp(c *Context) bool {
if c.Bool("h") || c.Bool("help") { if c.GlobalBool("h") || c.GlobalBool("help") {
ShowSubcommandHelp(c) ShowSubcommandHelp(c)
return true return true
} }
@ -252,43 +234,20 @@ func checkSubcommandHelp(c *Context) bool {
return false return false
} }
func checkShellCompleteFlag(a *App, arguments []string) (bool, []string) {
if !a.EnableBashCompletion {
return false, arguments
}
pos := len(arguments) - 1
lastArg := arguments[pos]
if lastArg != "--"+BashCompletionFlag.Name {
return false, arguments
}
return true, arguments[:pos]
}
func checkCompletions(c *Context) bool { func checkCompletions(c *Context) bool {
if !c.shellComplete { if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion {
return false ShowCompletions(c)
return true
} }
if args := c.Args(); args.Present() { return false
name := args.First()
if cmd := c.App.Command(name); cmd != nil {
// let the command handle the completion
return false
}
}
ShowCompletions(c)
return true
} }
func checkCommandCompletions(c *Context, name string) bool { func checkCommandCompletions(c *Context, name string) bool {
if !c.shellComplete { if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
return false ShowCommandCompletions(c, name)
return true
} }
ShowCommandCompletions(c, name) return false
return true
} }

View File

@ -1,12 +1,10 @@
package gojsonschema package gojsonschema
import ( import (
"bytes" "fmt"
"text/template" "strings"
) )
var errorTemplates *template.Template
type ( type (
// RequiredError. ErrorDetails: property string // RequiredError. ErrorDetails: property string
RequiredError struct { RequiredError struct {
@ -232,32 +230,13 @@ func newError(err ResultError, context *jsonContext, value interface{}, locale l
err.SetDescription(formatErrorDescription(d, details)) err.SetDescription(formatErrorDescription(d, details))
} }
// formatErrorDescription takes a string in the default text/template // formatErrorDescription takes a string in this format: %field% is required
// format and converts it to a string with replacements. The fields come // and converts it to a string with replacements. The fields come from
// from the ErrorDetails struct and vary for each type of error. // the ErrorDetails struct and vary for each type of error.
func formatErrorDescription(s string, details ErrorDetails) string { func formatErrorDescription(s string, details ErrorDetails) string {
for name, val := range details {
var tpl *template.Template s = strings.Replace(s, "%"+strings.ToLower(name)+"%", fmt.Sprintf("%v", val), -1)
var descrAsBuffer bytes.Buffer
var err error
if errorTemplates == nil {
errorTemplates = template.New("all-errors")
} }
tpl = errorTemplates.Lookup(s) return s
if tpl == nil {
tpl = errorTemplates.New(s)
tpl, err = tpl.Parse(s)
if err != nil {
return err.Error()
}
}
err = tpl.Execute(&descrAsBuffer, details)
if err != nil {
return err.Error()
}
return descrAsBuffer.String()
} }

View File

@ -5,7 +5,6 @@ import (
"net/url" "net/url"
"reflect" "reflect"
"regexp" "regexp"
"strings"
"time" "time"
) )
@ -60,9 +59,6 @@ type (
// UUIDFormatChecker validates a UUID is in the correct format // UUIDFormatChecker validates a UUID is in the correct format
UUIDFormatChecker struct{} UUIDFormatChecker struct{}
// RegexFormatChecker validates a regex is in the correct format
RegexFormatChecker struct{}
) )
var ( var (
@ -77,7 +73,6 @@ var (
"ipv6": IPV6FormatChecker{}, "ipv6": IPV6FormatChecker{},
"uri": URIFormatChecker{}, "uri": URIFormatChecker{},
"uuid": UUIDFormatChecker{}, "uuid": UUIDFormatChecker{},
"regex": RegexFormatChecker{},
}, },
} }
@ -85,7 +80,7 @@ var (
rxEmail = regexp.MustCompile("^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$") rxEmail = regexp.MustCompile("^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$")
// Regex credit: https://www.socketloop.com/tutorials/golang-validate-hostname // Regex credit: https://www.socketloop.com/tutorials/golang-validate-hostname
rxHostname = regexp.MustCompile(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`) rxHostname = regexp.MustCompile(`^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$`)
rxUUID = regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$") rxUUID = regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
) )
@ -137,13 +132,13 @@ func (f EmailFormatChecker) IsFormat(input string) bool {
// Credit: https://github.com/asaskevich/govalidator // Credit: https://github.com/asaskevich/govalidator
func (f IPV4FormatChecker) IsFormat(input string) bool { func (f IPV4FormatChecker) IsFormat(input string) bool {
ip := net.ParseIP(input) ip := net.ParseIP(input)
return ip != nil && strings.Contains(input, ".") return ip != nil && ip.To4() != nil
} }
// Credit: https://github.com/asaskevich/govalidator // Credit: https://github.com/asaskevich/govalidator
func (f IPV6FormatChecker) IsFormat(input string) bool { func (f IPV6FormatChecker) IsFormat(input string) bool {
ip := net.ParseIP(input) ip := net.ParseIP(input)
return ip != nil && strings.Contains(input, ":") return ip != nil && ip.To4() == nil
} }
func (f DateTimeFormatChecker) IsFormat(input string) bool { func (f DateTimeFormatChecker) IsFormat(input string) bool {
@ -174,21 +169,9 @@ func (f URIFormatChecker) IsFormat(input string) bool {
} }
func (f HostnameFormatChecker) IsFormat(input string) bool { func (f HostnameFormatChecker) IsFormat(input string) bool {
return rxHostname.MatchString(input) && len(input) < 256 return rxHostname.MatchString(input)
} }
func (f UUIDFormatChecker) IsFormat(input string) bool { func (f UUIDFormatChecker) IsFormat(input string) bool {
return rxUUID.MatchString(input) return rxUUID.MatchString(input)
} }
// IsFormat implements FormatChecker interface.
func (f RegexFormatChecker) IsFormat(input string) bool {
if input == "" {
return true
}
_, err := regexp.Compile(input)
if err != nil {
return false
}
return true
}

View File

@ -33,7 +33,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"os"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strings" "strings"
@ -41,90 +40,34 @@ import (
"github.com/xeipuuv/gojsonreference" "github.com/xeipuuv/gojsonreference"
) )
var osFS = osFileSystem(os.Open)
// JSON loader interface // JSON loader interface
type JSONLoader interface { type JSONLoader interface {
JsonSource() interface{} jsonSource() interface{}
LoadJSON() (interface{}, error) loadJSON() (interface{}, error)
JsonReference() (gojsonreference.JsonReference, error) loadSchema() (*Schema, error)
LoaderFactory() JSONLoaderFactory
}
type JSONLoaderFactory interface {
New(source string) JSONLoader
}
type DefaultJSONLoaderFactory struct {
}
type FileSystemJSONLoaderFactory struct {
fs http.FileSystem
}
func (d DefaultJSONLoaderFactory) New(source string) JSONLoader {
return &jsonReferenceLoader{
fs: osFS,
source: source,
}
}
func (f FileSystemJSONLoaderFactory) New(source string) JSONLoader {
return &jsonReferenceLoader{
fs: f.fs,
source: source,
}
}
// osFileSystem is a functional wrapper for os.Open that implements http.FileSystem.
type osFileSystem func(string) (*os.File, error)
func (o osFileSystem) Open(name string) (http.File, error) {
return o(name)
} }
// JSON Reference loader // JSON Reference loader
// references are used to load JSONs from files and HTTP // references are used to load JSONs from files and HTTP
type jsonReferenceLoader struct { type jsonReferenceLoader struct {
fs http.FileSystem
source string source string
} }
func (l *jsonReferenceLoader) JsonSource() interface{} { func (l *jsonReferenceLoader) jsonSource() interface{} {
return l.source return l.source
} }
func (l *jsonReferenceLoader) JsonReference() (gojsonreference.JsonReference, error) {
return gojsonreference.NewJsonReference(l.JsonSource().(string))
}
func (l *jsonReferenceLoader) LoaderFactory() JSONLoaderFactory {
return &DefaultJSONLoaderFactory{}
}
// NewReferenceLoader returns a JSON reference loader using the given source and the local OS file system.
func NewReferenceLoader(source string) *jsonReferenceLoader { func NewReferenceLoader(source string) *jsonReferenceLoader {
return &jsonReferenceLoader{ return &jsonReferenceLoader{source: source}
fs: osFS,
source: source,
}
} }
// NewReferenceLoaderFileSystem returns a JSON reference loader using the given source and file system. func (l *jsonReferenceLoader) loadJSON() (interface{}, error) {
func NewReferenceLoaderFileSystem(source string, fs http.FileSystem) *jsonReferenceLoader {
return &jsonReferenceLoader{
fs: fs,
source: source,
}
}
func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
var err error var err error
reference, err := gojsonreference.NewJsonReference(l.JsonSource().(string)) reference, err := gojsonreference.NewJsonReference(l.jsonSource().(string))
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -136,7 +79,7 @@ func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
if reference.HasFileScheme { if reference.HasFileScheme {
filename := strings.Replace(refToUrl.GetUrl().Path, "file://", "", -1) filename := strings.Replace(refToUrl.String(), "file://", "", -1)
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
// on Windows, a file URL may have an extra leading slash, use slashes // on Windows, a file URL may have an extra leading slash, use slashes
// instead of backslashes, and have spaces escaped // instead of backslashes, and have spaces escaped
@ -144,6 +87,7 @@ func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
filename = filename[1:] filename = filename[1:]
} }
filename = filepath.FromSlash(filename) filename = filepath.FromSlash(filename)
filename = strings.Replace(filename, "%20", " ", -1)
} }
document, err = l.loadFromFile(filename) document, err = l.loadFromFile(filename)
@ -164,6 +108,33 @@ func (l *jsonReferenceLoader) LoadJSON() (interface{}, error) {
} }
func (l *jsonReferenceLoader) loadSchema() (*Schema, error) {
var err error
d := Schema{}
d.pool = newSchemaPool()
d.referencePool = newSchemaReferencePool()
d.documentReference, err = gojsonreference.NewJsonReference(l.jsonSource().(string))
if err != nil {
return nil, err
}
spd, err := d.pool.GetDocument(d.documentReference)
if err != nil {
return nil, err
}
err = d.parse(spd.Document)
if err != nil {
return nil, err
}
return &d, nil
}
func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) { func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error) {
resp, err := http.Get(address) resp, err := http.Get(address)
@ -186,13 +157,8 @@ func (l *jsonReferenceLoader) loadFromHTTP(address string) (interface{}, error)
} }
func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) { func (l *jsonReferenceLoader) loadFromFile(path string) (interface{}, error) {
f, err := l.fs.Open(path)
if err != nil {
return nil, err
}
defer f.Close()
bodyBuff, err := ioutil.ReadAll(f) bodyBuff, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -207,52 +173,45 @@ type jsonStringLoader struct {
source string source string
} }
func (l *jsonStringLoader) JsonSource() interface{} { func (l *jsonStringLoader) jsonSource() interface{} {
return l.source return l.source
} }
func (l *jsonStringLoader) JsonReference() (gojsonreference.JsonReference, error) {
return gojsonreference.NewJsonReference("#")
}
func (l *jsonStringLoader) LoaderFactory() JSONLoaderFactory {
return &DefaultJSONLoaderFactory{}
}
func NewStringLoader(source string) *jsonStringLoader { func NewStringLoader(source string) *jsonStringLoader {
return &jsonStringLoader{source: source} return &jsonStringLoader{source: source}
} }
func (l *jsonStringLoader) LoadJSON() (interface{}, error) { func (l *jsonStringLoader) loadJSON() (interface{}, error) {
return decodeJsonUsingNumber(strings.NewReader(l.JsonSource().(string))) return decodeJsonUsingNumber(strings.NewReader(l.jsonSource().(string)))
} }
// JSON bytes loader func (l *jsonStringLoader) loadSchema() (*Schema, error) {
type jsonBytesLoader struct { var err error
source []byte
}
func (l *jsonBytesLoader) JsonSource() interface{} { document, err := l.loadJSON()
return l.source if err != nil {
} return nil, err
}
func (l *jsonBytesLoader) JsonReference() (gojsonreference.JsonReference, error) { d := Schema{}
return gojsonreference.NewJsonReference("#") d.pool = newSchemaPool()
} d.referencePool = newSchemaReferencePool()
d.documentReference, err = gojsonreference.NewJsonReference("#")
d.pool.SetStandaloneDocument(document)
if err != nil {
return nil, err
}
func (l *jsonBytesLoader) LoaderFactory() JSONLoaderFactory { err = d.parse(document)
return &DefaultJSONLoaderFactory{} if err != nil {
} return nil, err
}
func NewBytesLoader(source []byte) *jsonBytesLoader { return &d, nil
return &jsonBytesLoader{source: source}
}
func (l *jsonBytesLoader) LoadJSON() (interface{}, error) {
return decodeJsonUsingNumber(bytes.NewReader(l.JsonSource().([]byte)))
} }
// JSON Go (types) loader // JSON Go (types) loader
@ -262,27 +221,19 @@ type jsonGoLoader struct {
source interface{} source interface{}
} }
func (l *jsonGoLoader) JsonSource() interface{} { func (l *jsonGoLoader) jsonSource() interface{} {
return l.source return l.source
} }
func (l *jsonGoLoader) JsonReference() (gojsonreference.JsonReference, error) {
return gojsonreference.NewJsonReference("#")
}
func (l *jsonGoLoader) LoaderFactory() JSONLoaderFactory {
return &DefaultJSONLoaderFactory{}
}
func NewGoLoader(source interface{}) *jsonGoLoader { func NewGoLoader(source interface{}) *jsonGoLoader {
return &jsonGoLoader{source: source} return &jsonGoLoader{source: source}
} }
func (l *jsonGoLoader) LoadJSON() (interface{}, error) { func (l *jsonGoLoader) loadJSON() (interface{}, error) {
// convert it to a compliant JSON first to avoid types "mismatches" // convert it to a compliant JSON first to avoid types "mismatches"
jsonBytes, err := json.Marshal(l.JsonSource()) jsonBytes, err := json.Marshal(l.jsonSource())
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -291,6 +242,33 @@ func (l *jsonGoLoader) LoadJSON() (interface{}, error) {
} }
func (l *jsonGoLoader) loadSchema() (*Schema, error) {
var err error
document, err := l.loadJSON()
if err != nil {
return nil, err
}
d := Schema{}
d.pool = newSchemaPool()
d.referencePool = newSchemaReferencePool()
d.documentReference, err = gojsonreference.NewJsonReference("#")
d.pool.SetStandaloneDocument(document)
if err != nil {
return nil, err
}
err = d.parse(document)
if err != nil {
return nil, err
}
return &d, nil
}
func decodeJsonUsingNumber(r io.Reader) (interface{}, error) { func decodeJsonUsingNumber(r io.Reader) (interface{}, error) {
var document interface{} var document interface{}

View File

@ -37,7 +37,6 @@ type (
MissingDependency() string MissingDependency() string
Internal() string Internal() string
Enum() string Enum() string
ArrayNotEnoughItems() string
ArrayNoAdditionalItems() string ArrayNoAdditionalItems() string
ArrayMinItems() string ArrayMinItems() string
ArrayMaxItems() string ArrayMaxItems() string
@ -84,11 +83,11 @@ type (
) )
func (l DefaultLocale) Required() string { func (l DefaultLocale) Required() string {
return `{{.property}} is required` return `%property% is required`
} }
func (l DefaultLocale) InvalidType() string { func (l DefaultLocale) InvalidType() string {
return `Invalid type. Expected: {{.expected}}, given: {{.given}}` return `Invalid type. Expected: %expected%, given: %given%`
} }
func (l DefaultLocale) NumberAnyOf() string { func (l DefaultLocale) NumberAnyOf() string {
@ -108,161 +107,157 @@ func (l DefaultLocale) NumberNot() string {
} }
func (l DefaultLocale) MissingDependency() string { func (l DefaultLocale) MissingDependency() string {
return `Has a dependency on {{.dependency}}` return `Has a dependency on %dependency%`
} }
func (l DefaultLocale) Internal() string { func (l DefaultLocale) Internal() string {
return `Internal Error {{.error}}` return `Internal Error %error%`
} }
func (l DefaultLocale) Enum() string { func (l DefaultLocale) Enum() string {
return `{{.field}} must be one of the following: {{.allowed}}` return `%field% must be one of the following: %allowed%`
} }
func (l DefaultLocale) ArrayNoAdditionalItems() string { func (l DefaultLocale) ArrayNoAdditionalItems() string {
return `No additional items allowed on array` return `No additional items allowed on array`
} }
func (l DefaultLocale) ArrayNotEnoughItems() string {
return `Not enough items on array to match positional list of schema`
}
func (l DefaultLocale) ArrayMinItems() string { func (l DefaultLocale) ArrayMinItems() string {
return `Array must have at least {{.min}} items` return `Array must have at least %min% items`
} }
func (l DefaultLocale) ArrayMaxItems() string { func (l DefaultLocale) ArrayMaxItems() string {
return `Array must have at most {{.max}} items` return `Array must have at most %max% items`
} }
func (l DefaultLocale) Unique() string { func (l DefaultLocale) Unique() string {
return `{{.type}} items must be unique` return `%type% items must be unique`
} }
func (l DefaultLocale) ArrayMinProperties() string { func (l DefaultLocale) ArrayMinProperties() string {
return `Must have at least {{.min}} properties` return `Must have at least %min% properties`
} }
func (l DefaultLocale) ArrayMaxProperties() string { func (l DefaultLocale) ArrayMaxProperties() string {
return `Must have at most {{.max}} properties` return `Must have at most %max% properties`
} }
func (l DefaultLocale) AdditionalPropertyNotAllowed() string { func (l DefaultLocale) AdditionalPropertyNotAllowed() string {
return `Additional property {{.property}} is not allowed` return `Additional property %property% is not allowed`
} }
func (l DefaultLocale) InvalidPropertyPattern() string { func (l DefaultLocale) InvalidPropertyPattern() string {
return `Property "{{.property}}" does not match pattern {{.pattern}}` return `Property "%property%" does not match pattern %pattern%`
} }
func (l DefaultLocale) StringGTE() string { func (l DefaultLocale) StringGTE() string {
return `String length must be greater than or equal to {{.min}}` return `String length must be greater than or equal to %min%`
} }
func (l DefaultLocale) StringLTE() string { func (l DefaultLocale) StringLTE() string {
return `String length must be less than or equal to {{.max}}` return `String length must be less than or equal to %max%`
} }
func (l DefaultLocale) DoesNotMatchPattern() string { func (l DefaultLocale) DoesNotMatchPattern() string {
return `Does not match pattern '{{.pattern}}'` return `Does not match pattern '%pattern%'`
} }
func (l DefaultLocale) DoesNotMatchFormat() string { func (l DefaultLocale) DoesNotMatchFormat() string {
return `Does not match format '{{.format}}'` return `Does not match format '%format%'`
} }
func (l DefaultLocale) MultipleOf() string { func (l DefaultLocale) MultipleOf() string {
return `Must be a multiple of {{.multiple}}` return `Must be a multiple of %multiple%`
} }
func (l DefaultLocale) NumberGTE() string { func (l DefaultLocale) NumberGTE() string {
return `Must be greater than or equal to {{.min}}` return `Must be greater than or equal to %min%`
} }
func (l DefaultLocale) NumberGT() string { func (l DefaultLocale) NumberGT() string {
return `Must be greater than {{.min}}` return `Must be greater than %min%`
} }
func (l DefaultLocale) NumberLTE() string { func (l DefaultLocale) NumberLTE() string {
return `Must be less than or equal to {{.max}}` return `Must be less than or equal to %max%`
} }
func (l DefaultLocale) NumberLT() string { func (l DefaultLocale) NumberLT() string {
return `Must be less than {{.max}}` return `Must be less than %max%`
} }
// Schema validators // Schema validators
func (l DefaultLocale) RegexPattern() string { func (l DefaultLocale) RegexPattern() string {
return `Invalid regex pattern '{{.pattern}}'` return `Invalid regex pattern '%pattern%'`
} }
func (l DefaultLocale) GreaterThanZero() string { func (l DefaultLocale) GreaterThanZero() string {
return `{{.number}} must be strictly greater than 0` return `%number% must be strictly greater than 0`
} }
func (l DefaultLocale) MustBeOfA() string { func (l DefaultLocale) MustBeOfA() string {
return `{{.x}} must be of a {{.y}}` return `%x% must be of a %y%`
} }
func (l DefaultLocale) MustBeOfAn() string { func (l DefaultLocale) MustBeOfAn() string {
return `{{.x}} must be of an {{.y}}` return `%x% must be of an %y%`
} }
func (l DefaultLocale) CannotBeUsedWithout() string { func (l DefaultLocale) CannotBeUsedWithout() string {
return `{{.x}} cannot be used without {{.y}}` return `%x% cannot be used without %y%`
} }
func (l DefaultLocale) CannotBeGT() string { func (l DefaultLocale) CannotBeGT() string {
return `{{.x}} cannot be greater than {{.y}}` return `%x% cannot be greater than %y%`
} }
func (l DefaultLocale) MustBeOfType() string { func (l DefaultLocale) MustBeOfType() string {
return `{{.key}} must be of type {{.type}}` return `%key% must be of type %type%`
} }
func (l DefaultLocale) MustBeValidRegex() string { func (l DefaultLocale) MustBeValidRegex() string {
return `{{.key}} must be a valid regex` return `%key% must be a valid regex`
} }
func (l DefaultLocale) MustBeValidFormat() string { func (l DefaultLocale) MustBeValidFormat() string {
return `{{.key}} must be a valid format {{.given}}` return `%key% must be a valid format %given%`
} }
func (l DefaultLocale) MustBeGTEZero() string { func (l DefaultLocale) MustBeGTEZero() string {
return `{{.key}} must be greater than or equal to 0` return `%key% must be greater than or equal to 0`
} }
func (l DefaultLocale) KeyCannotBeGreaterThan() string { func (l DefaultLocale) KeyCannotBeGreaterThan() string {
return `{{.key}} cannot be greater than {{.y}}` return `%key% cannot be greater than %y%`
} }
func (l DefaultLocale) KeyItemsMustBeOfType() string { func (l DefaultLocale) KeyItemsMustBeOfType() string {
return `{{.key}} items must be {{.type}}` return `%key% items must be %type%`
} }
func (l DefaultLocale) KeyItemsMustBeUnique() string { func (l DefaultLocale) KeyItemsMustBeUnique() string {
return `{{.key}} items must be unique` return `%key% items must be unique`
} }
func (l DefaultLocale) ReferenceMustBeCanonical() string { func (l DefaultLocale) ReferenceMustBeCanonical() string {
return `Reference {{.reference}} must be canonical` return `Reference %reference% must be canonical`
} }
func (l DefaultLocale) NotAValidType() string { func (l DefaultLocale) NotAValidType() string {
return `{{.type}} is not a valid type -- ` return `%type% is not a valid type -- `
} }
func (l DefaultLocale) Duplicated() string { func (l DefaultLocale) Duplicated() string {
return `{{.type}} type is duplicated` return `%type% type is duplicated`
} }
func (l DefaultLocale) httpBadStatus() string { func (l DefaultLocale) httpBadStatus() string {
return `Could not read schema from HTTP, response status is {{.status}}` return `Could not read schema from HTTP, response status is %status%`
} }
// Replacement options: field, description, context, value // Replacement options: field, description, context, value
func (l DefaultLocale) ErrorFormat() string { func (l DefaultLocale) ErrorFormat() string {
return `{{.field}}: {{.description}}` return `%field%: %description%`
} }
const ( const (

View File

@ -48,7 +48,6 @@ type (
Value() interface{} Value() interface{}
SetDetails(ErrorDetails) SetDetails(ErrorDetails)
Details() ErrorDetails Details() ErrorDetails
String() string
} }
// ResultErrorFields holds the fields for each ResultError implementation. // ResultErrorFields holds the fields for each ResultError implementation.
@ -127,7 +126,7 @@ func (v ResultErrorFields) String() string {
valueString := fmt.Sprintf("%v", v.value) valueString := fmt.Sprintf("%v", v.value)
// marshal the go value value to json // marshal the go value value to json
if v.value == nil { if v.Value == nil {
valueString = TYPE_NULL valueString = TYPE_NULL
} else { } else {
if vs, err := marshalToJsonString(v.value); err == nil { if vs, err := marshalToJsonString(v.value); err == nil {

View File

@ -42,39 +42,7 @@ var (
) )
func NewSchema(l JSONLoader) (*Schema, error) { func NewSchema(l JSONLoader) (*Schema, error) {
ref, err := l.JsonReference() return l.loadSchema()
if err != nil {
return nil, err
}
d := Schema{}
d.pool = newSchemaPool(l.LoaderFactory())
d.documentReference = ref
d.referencePool = newSchemaReferencePool()
var doc interface{}
if ref.String() != "" {
// Get document from schema pool
spd, err := d.pool.GetDocument(d.documentReference)
if err != nil {
return nil, err
}
doc = spd.Document
} else {
// Load JSON directly
doc, err = l.LoadJSON()
if err != nil {
return nil, err
}
d.pool.SetStandaloneDocument(doc)
}
err = d.parse(doc)
if err != nil {
return nil, err
}
return &d, nil
} }
type Schema struct { type Schema struct {
@ -148,27 +116,14 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
} }
if k, ok := m[KEY_REF].(string); ok { if k, ok := m[KEY_REF].(string); ok {
jsonReference, err := gojsonreference.NewJsonReference(k)
if err != nil {
return err
}
if jsonReference.HasFullUrl {
currentSchema.ref = &jsonReference
} else {
inheritedReference, err := currentSchema.ref.Inherits(jsonReference)
if err != nil {
return err
}
currentSchema.ref = inheritedReference
}
if sch, ok := d.referencePool.Get(currentSchema.ref.String() + k); ok { if sch, ok := d.referencePool.Get(currentSchema.ref.String() + k); ok {
currentSchema.refSchema = sch currentSchema.refSchema = sch
} else { } else {
err := d.parseReference(documentNode, currentSchema, k)
var err error
err = d.parseReference(documentNode, currentSchema, k)
if err != nil { if err != nil {
return err return err
} }
@ -800,11 +755,31 @@ func (d *Schema) parseSchema(documentNode interface{}, currentSchema *subSchema)
return nil return nil
} }
func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSchema, reference string) error { func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSchema, reference string) (e error) {
var refdDocumentNode interface{}
jsonPointer := currentSchema.ref.GetPointer() var err error
jsonReference, err := gojsonreference.NewJsonReference(reference)
if err != nil {
return err
}
standaloneDocument := d.pool.GetStandaloneDocument() standaloneDocument := d.pool.GetStandaloneDocument()
if jsonReference.HasFullUrl {
currentSchema.ref = &jsonReference
} else {
inheritedReference, err := currentSchema.ref.Inherits(jsonReference)
if err != nil {
return err
}
currentSchema.ref = inheritedReference
}
jsonPointer := currentSchema.ref.GetPointer()
var refdDocumentNode interface{}
if standaloneDocument != nil { if standaloneDocument != nil {
var err error var err error
@ -814,6 +789,8 @@ func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSche
} }
} else { } else {
var err error
dsp, err := d.pool.GetDocument(*currentSchema.ref) dsp, err := d.pool.GetDocument(*currentSchema.ref)
if err != nil { if err != nil {
return err return err
@ -835,10 +812,11 @@ func (d *Schema) parseReference(documentNode interface{}, currentSchema *subSche
// returns the loaded referenced subSchema for the caller to update its current subSchema // returns the loaded referenced subSchema for the caller to update its current subSchema
newSchemaDocument := refdDocumentNode.(map[string]interface{}) newSchemaDocument := refdDocumentNode.(map[string]interface{})
newSchema := &subSchema{property: KEY_REF, parent: currentSchema, ref: currentSchema.ref} newSchema := &subSchema{property: KEY_REF, parent: currentSchema, ref: currentSchema.ref}
d.referencePool.Add(currentSchema.ref.String()+reference, newSchema) d.referencePool.Add(currentSchema.ref.String()+reference, newSchema)
err := d.parseSchema(newSchemaDocument, newSchema) err = d.parseSchema(newSchemaDocument, newSchema)
if err != nil { if err != nil {
return err return err
} }

View File

@ -39,15 +39,13 @@ type schemaPoolDocument struct {
type schemaPool struct { type schemaPool struct {
schemaPoolDocuments map[string]*schemaPoolDocument schemaPoolDocuments map[string]*schemaPoolDocument
standaloneDocument interface{} standaloneDocument interface{}
jsonLoaderFactory JSONLoaderFactory
} }
func newSchemaPool(f JSONLoaderFactory) *schemaPool { func newSchemaPool() *schemaPool {
p := &schemaPool{} p := &schemaPool{}
p.schemaPoolDocuments = make(map[string]*schemaPoolDocument) p.schemaPoolDocuments = make(map[string]*schemaPoolDocument)
p.standaloneDocument = nil p.standaloneDocument = nil
p.jsonLoaderFactory = f
return p return p
} }
@ -95,8 +93,8 @@ func (p *schemaPool) GetDocument(reference gojsonreference.JsonReference) (*sche
return spd, nil return spd, nil
} }
jsonReferenceLoader := p.jsonLoaderFactory.New(reference.String()) jsonReferenceLoader := NewReferenceLoader(reference.String())
document, err := jsonReferenceLoader.LoadJSON() document, err := jsonReferenceLoader.loadJSON()
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -214,7 +214,7 @@ func (s *subSchema) PatternPropertiesString() string {
} }
patternPropertiesKeySlice := []string{} patternPropertiesKeySlice := []string{}
for pk := range s.patternProperties { for pk, _ := range s.patternProperties {
patternPropertiesKeySlice = append(patternPropertiesKeySlice, `"`+pk+`"`) patternPropertiesKeySlice = append(patternPropertiesKeySlice, `"`+pk+`"`)
} }

View File

@ -34,12 +34,7 @@ import (
) )
func isKind(what interface{}, kind reflect.Kind) bool { func isKind(what interface{}, kind reflect.Kind) bool {
target := what return reflect.ValueOf(what).Kind() == kind
if isJsonNumber(what) {
// JSON Numbers are strings!
target = *mustBeNumber(what)
}
return reflect.ValueOf(target).Kind() == kind
} }
func existsMapKey(m map[string]interface{}, k string) bool { func existsMapKey(m map[string]interface{}, k string) bool {
@ -82,14 +77,13 @@ func checkJsonNumber(what interface{}) (isValidFloat64 bool, isValidInt64 bool,
jsonNumber := what.(json.Number) jsonNumber := what.(json.Number)
f64, errFloat64 := jsonNumber.Float64() _, errFloat64 := jsonNumber.Float64()
s64 := strconv.FormatFloat(f64, 'f', -1, 64) _, errInt64 := jsonNumber.Int64()
_, errInt64 := strconv.ParseInt(s64, 10, 64)
isValidFloat64 = errFloat64 == nil isValidFloat64 = errFloat64 == nil
isValidInt64 = errInt64 == nil isValidInt64 = errInt64 == nil
_, errInt32 := strconv.ParseInt(s64, 10, 32) _, errInt32 := strconv.ParseInt(jsonNumber.String(), 10, 32)
isValidInt32 = isValidInt64 && errInt32 == nil isValidInt32 = isValidInt64 && errInt32 == nil
return return

View File

@ -55,7 +55,7 @@ func (v *Schema) Validate(l JSONLoader) (*Result, error) {
// load document // load document
root, err := l.LoadJSON() root, err := l.loadJSON()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -412,7 +412,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
internalLog(" %v", value) internalLog(" %v", value)
} }
nbValues := len(value) nbItems := len(value)
// TODO explain // TODO explain
if currentSubSchema.itemsChildrenIsSingleSchema { if currentSubSchema.itemsChildrenIsSingleSchema {
@ -425,18 +425,15 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
if currentSubSchema.itemsChildren != nil && len(currentSubSchema.itemsChildren) > 0 { if currentSubSchema.itemsChildren != nil && len(currentSubSchema.itemsChildren) > 0 {
nbItems := len(currentSubSchema.itemsChildren) nbItems := len(currentSubSchema.itemsChildren)
nbValues := len(value)
// while we have both schemas and values, check them against each other if nbItems == nbValues {
for i := 0; i != nbItems && i != nbValues; i++ { for i := 0; i != nbItems; i++ {
subContext := newJsonContext(strconv.Itoa(i), context) subContext := newJsonContext(strconv.Itoa(i), context)
validationResult := currentSubSchema.itemsChildren[i].subValidateWithContext(value[i], subContext) validationResult := currentSubSchema.itemsChildren[i].subValidateWithContext(value[i], subContext)
result.mergeErrors(validationResult) result.mergeErrors(validationResult)
} }
} else if nbItems < nbValues {
if nbItems < nbValues {
// we have less schemas than elements in the instance array,
// but that might be ok if "additionalItems" is specified.
switch currentSubSchema.additionalItems.(type) { switch currentSubSchema.additionalItems.(type) {
case bool: case bool:
if !currentSubSchema.additionalItems.(bool) { if !currentSubSchema.additionalItems.(bool) {
@ -456,7 +453,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
// minItems & maxItems // minItems & maxItems
if currentSubSchema.minItems != nil { if currentSubSchema.minItems != nil {
if nbValues < int(*currentSubSchema.minItems) { if nbItems < int(*currentSubSchema.minItems) {
result.addError( result.addError(
new(ArrayMinItemsError), new(ArrayMinItemsError),
context, context,
@ -466,7 +463,7 @@ func (v *subSchema) validateArray(currentSubSchema *subSchema, value []interface
} }
} }
if currentSubSchema.maxItems != nil { if currentSubSchema.maxItems != nil {
if nbValues > int(*currentSubSchema.maxItems) { if nbItems > int(*currentSubSchema.maxItems) {
result.addError( result.addError(
new(ArrayMaxItemsError), new(ArrayMaxItemsError),
context, context,
@ -779,22 +776,22 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
if currentSubSchema.exclusiveMaximum { if currentSubSchema.exclusiveMaximum {
if float64Value >= *currentSubSchema.maximum { if float64Value >= *currentSubSchema.maximum {
result.addError( result.addError(
new(NumberLTError), new(NumberLTEError),
context, context,
resultErrorFormatJsonNumber(number), resultErrorFormatJsonNumber(number),
ErrorDetails{ ErrorDetails{
"max": resultErrorFormatNumber(*currentSubSchema.maximum), "min": resultErrorFormatNumber(*currentSubSchema.maximum),
}, },
) )
} }
} else { } else {
if float64Value > *currentSubSchema.maximum { if float64Value > *currentSubSchema.maximum {
result.addError( result.addError(
new(NumberLTEError), new(NumberLTError),
context, context,
resultErrorFormatJsonNumber(number), resultErrorFormatJsonNumber(number),
ErrorDetails{ ErrorDetails{
"max": resultErrorFormatNumber(*currentSubSchema.maximum), "min": resultErrorFormatNumber(*currentSubSchema.maximum),
}, },
) )
} }
@ -806,22 +803,22 @@ func (v *subSchema) validateNumber(currentSubSchema *subSchema, value interface{
if currentSubSchema.exclusiveMinimum { if currentSubSchema.exclusiveMinimum {
if float64Value <= *currentSubSchema.minimum { if float64Value <= *currentSubSchema.minimum {
result.addError( result.addError(
new(NumberGTError), new(NumberGTEError),
context, context,
resultErrorFormatJsonNumber(number), resultErrorFormatJsonNumber(number),
ErrorDetails{ ErrorDetails{
"min": resultErrorFormatNumber(*currentSubSchema.minimum), "max": resultErrorFormatNumber(*currentSubSchema.minimum),
}, },
) )
} }
} else { } else {
if float64Value < *currentSubSchema.minimum { if float64Value < *currentSubSchema.minimum {
result.addError( result.addError(
new(NumberGTEError), new(NumberGTError),
context, context,
resultErrorFormatJsonNumber(number), resultErrorFormatJsonNumber(number),
ErrorDetails{ ErrorDetails{
"min": resultErrorFormatNumber(*currentSubSchema.minimum), "max": resultErrorFormatNumber(*currentSubSchema.minimum),
}, },
) )
} }

View File

@ -1,28 +1,29 @@
// Copyright 2015 The Go Authors. All rights reserved. // Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// +build linux
// +build mips64 mips64le
// +build !gccgo // +build !gccgo
#include "textflag.h" #include "textflag.h"
// //
// System calls for mips64, Linux // System call support for 386, FreeBSD
// //
// Just jump to package syscall's implementation for all these functions. // Just jump to package syscall's implementation for all these functions.
// The runtime may know about them. // The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56 TEXT ·Syscall(SB),NOSPLIT,$0-32
JMP syscall·Syscall(SB) JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80 TEXT ·Syscall6(SB),NOSPLIT,$0-44
JMP syscall·Syscall6(SB) JMP syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56 TEXT ·Syscall9(SB),NOSPLIT,$0-56
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-32
JMP syscall·RawSyscall(SB) JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80 TEXT ·RawSyscall6(SB),NOSPLIT,$0-44
JMP syscall·RawSyscall6(SB) JMP syscall·RawSyscall6(SB)

View File

@ -1,31 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
// +build mips mipsle
// +build !gccgo
#include "textflag.h"
//
// System calls for mips, Linux
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-28
JMP syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-40
JMP syscall·Syscall6(SB)
TEXT ·Syscall9(SB),NOSPLIT,$0-52
JMP syscall·Syscall9(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-28
JMP syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-40
JMP syscall·RawSyscall6(SB)

View File

@ -1,28 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build s390x
// +build linux
// +build !gccgo
#include "textflag.h"
//
// System calls for s390x, Linux
//
// Just jump to package syscall's implementation for all these functions.
// The runtime may know about them.
TEXT ·Syscall(SB),NOSPLIT,$0-56
BR syscall·Syscall(SB)
TEXT ·Syscall6(SB),NOSPLIT,$0-80
BR syscall·Syscall6(SB)
TEXT ·RawSyscall(SB),NOSPLIT,$0-56
BR syscall·RawSyscall(SB)
TEXT ·RawSyscall6(SB),NOSPLIT,$0-80
BR syscall·RawSyscall6(SB)

View File

@ -1,35 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Bluetooth sockets and messages
package unix
// Bluetooth Protocols
const (
BTPROTO_L2CAP = 0
BTPROTO_HCI = 1
BTPROTO_SCO = 2
BTPROTO_RFCOMM = 3
BTPROTO_BNEP = 4
BTPROTO_CMTP = 5
BTPROTO_HIDP = 6
BTPROTO_AVDTP = 7
)
const (
HCI_CHANNEL_RAW = 0
HCI_CHANNEL_USER = 1
HCI_CHANNEL_MONITOR = 2
HCI_CHANNEL_CONTROL = 3
)
// Socketoption Level
const (
SOL_BLUETOOTH = 0x112
SOL_HCI = 0x0
SOL_L2CAP = 0x6
SOL_RFCOMM = 0x12
SOL_SCO = 0x11
)

View File

@ -1,4 +1,4 @@
// +build linux,386 linux,arm linux,mips linux,mipsle // +build linux,386 linux,arm
// Copyright 2014 The Go Authors. All rights reserved. // Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style

View File

@ -1,20 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build gccgo,linux,sparc64
package unix
import "syscall"
//extern sysconf
func realSysconf(name int) int64
func sysconf(name int) (n int64, err syscall.Errno) {
r := realSysconf(name)
if r < 0 {
return 0, syscall.GetErrno()
}
return r, 0
}

View File

@ -1,62 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build ignore
// mkpost processes the output of cgo -godefs to
// modify the generated types. It is used to clean up
// the sys API in an architecture specific manner.
//
// mkpost is run after cgo -godefs by mkall.sh.
package main
import (
"fmt"
"go/format"
"io/ioutil"
"log"
"os"
"regexp"
)
func main() {
b, err := ioutil.ReadAll(os.Stdin)
if err != nil {
log.Fatal(err)
}
s := string(b)
goarch := os.Getenv("GOARCH")
goos := os.Getenv("GOOS")
if goarch == "s390x" && goos == "linux" {
// Export the types of PtraceRegs fields.
re := regexp.MustCompile("ptrace(Psw|Fpregs|Per)")
s = re.ReplaceAllString(s, "Ptrace$1")
// Replace padding fields inserted by cgo with blank identifiers.
re = regexp.MustCompile("Pad_cgo[A-Za-z0-9_]*")
s = re.ReplaceAllString(s, "_")
// Replace other unwanted fields with blank identifiers.
re = regexp.MustCompile("X_[A-Za-z0-9_]*")
s = re.ReplaceAllString(s, "_")
// Replace the control_regs union with a blank identifier for now.
re = regexp.MustCompile("(Control_regs)\\s+\\[0\\]uint64")
s = re.ReplaceAllString(s, "_ [0]uint64")
}
// gofmt
b, err = format.Source([]byte(s))
if err != nil {
log.Fatal(err)
}
// Append this command to the header to show where the new file
// came from.
re := regexp.MustCompile("(cgo -godefs [a-zA-Z0-9_]+\\.go.*)")
b = re.ReplaceAll(b, []byte("$1 | go run mkpost.go"))
fmt.Printf("%s", b)
}

View File

@ -62,7 +62,7 @@ func ParseSocketControlMessage(b []byte) ([]SocketControlMessage, error) {
func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) { func socketControlMessageHeaderAndData(b []byte) (*Cmsghdr, []byte, error) {
h := (*Cmsghdr)(unsafe.Pointer(&b[0])) h := (*Cmsghdr)(unsafe.Pointer(&b[0]))
if h.Len < SizeofCmsghdr || uint64(h.Len) > uint64(len(b)) { if h.Len < SizeofCmsghdr || int(h.Len) > len(b) {
return nil, nil, EINVAL return nil, nil, EINVAL
} }
return h, b[cmsgAlignOf(SizeofCmsghdr):h.Len], nil return h, b[cmsgAlignOf(SizeofCmsghdr):h.Len], nil

View File

@ -68,8 +68,6 @@ func (tv *Timeval) Nano() int64 {
return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000 return int64(tv.Sec)*1e9 + int64(tv.Usec)*1000
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
// use is a no-op, but the compiler cannot see that it is. // use is a no-op, but the compiler cannot see that it is.
// Calling use(p) ensures that p is kept live until that point. // Calling use(p) ensures that p is kept live until that point.
//go:noescape //go:noescape

View File

@ -470,11 +470,25 @@ func Sysctl(name string) (string, error) {
} }
func SysctlArgs(name string, args ...int) (string, error) { func SysctlArgs(name string, args ...int) (string, error) {
buf, err := SysctlRaw(name, args...) mib, err := sysctlmib(name, args...)
if err != nil { if err != nil {
return "", err return "", err
} }
n := len(buf)
// Find size.
n := uintptr(0)
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
return "", err
}
if n == 0 {
return "", nil
}
// Read into buffer of that size.
buf := make([]byte, n)
if err := sysctl(mib, &buf[0], &n, nil, 0); err != nil {
return "", err
}
// Throw away terminating NUL. // Throw away terminating NUL.
if n > 0 && buf[n-1] == '\x00' { if n > 0 && buf[n-1] == '\x00' {

View File

@ -144,7 +144,6 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (
uintptr(options), uintptr(options),
0, 0,
) )
use(unsafe.Pointer(_p0))
if e1 != 0 { if e1 != 0 {
return nil, e1 return nil, e1
} }
@ -197,7 +196,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
} }
r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags)) r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0) n = int(r0)
if e1 != 0 { if e1 != 0 {
err = e1 err = e1

View File

@ -21,6 +21,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

View File

@ -23,6 +23,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

View File

@ -19,6 +19,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

View File

@ -21,6 +21,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

View File

@ -109,7 +109,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
} }
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0) n = int(r0)
if e1 != 0 { if e1 != 0 {
err = e1 err = e1

63
vendor/golang.org/x/sys/unix/syscall_dragonfly_386.go generated vendored Normal file
View File

@ -0,0 +1,63 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build 386,dragonfly
package unix
import (
"syscall"
"unsafe"
)
func Getpagesize() int { return 4096 }
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int32(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9)
return
}
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3)
tv.Sec = int32(nsec / 1e9)
return
}
func SetKevent(k *Kevent_t, fd, mode, flags int) {
k.Ident = uint32(fd)
k.Filter = int16(mode)
k.Flags = uint16(flags)
}
func (iov *Iovec) SetLen(length int) {
iov.Len = uint32(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
func sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) {
var writtenOut uint64 = 0
_, _, e1 := Syscall9(SYS_SENDFILE, uintptr(infd), uintptr(outfd), uintptr(*offset), uintptr((*offset)>>32), uintptr(count), 0, uintptr(unsafe.Pointer(&writtenOut)), 0, 0)
written = int(writtenOut)
if e1 != 0 {
err = e1
}
return
}
func Syscall9(num, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)

View File

@ -21,6 +21,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = nsec % 1e9 / 1e3 tv.Usec = nsec % 1e9 / 1e3

View File

@ -129,7 +129,6 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
} }
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0) n = int(r0)
if e1 != 0 { if e1 != 0 {
err = e1 err = e1

View File

@ -21,6 +21,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

View File

@ -21,6 +21,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = nsec % 1e9 / 1e3 tv.Usec = nsec % 1e9 / 1e3

View File

@ -21,6 +21,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return tv.Sec*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Usec = int32(nsec % 1e9 / 1e3) tv.Usec = int32(nsec % 1e9 / 1e3)

View File

@ -36,10 +36,10 @@ func Creat(path string, mode uint32) (fd int, err error) {
return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode) return Open(path, O_CREAT|O_WRONLY|O_TRUNC, mode)
} }
//sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) //sys linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
func Link(oldpath string, newpath string) (err error) { func Link(oldpath string, newpath string) (err error) {
return Linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0) return linkat(AT_FDCWD, oldpath, AT_FDCWD, newpath, 0)
} }
func Mkdir(path string, mode uint32) (err error) { func Mkdir(path string, mode uint32) (err error) {
@ -60,19 +60,10 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
return openat(dirfd, path, flags|O_LARGEFILE, mode) return openat(dirfd, path, flags|O_LARGEFILE, mode)
} }
//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) //sys readlinkat(dirfd int, path string, buf []byte) (n int, err error)
func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) {
if len(fds) == 0 {
return ppoll(nil, 0, timeout, sigmask)
}
return ppoll(&fds[0], len(fds), timeout, sigmask)
}
//sys Readlinkat(dirfd int, path string, buf []byte) (n int, err error)
func Readlink(path string, buf []byte) (n int, err error) { func Readlink(path string, buf []byte) (n int, err error) {
return Readlinkat(AT_FDCWD, path, buf) return readlinkat(AT_FDCWD, path, buf)
} }
func Rename(oldpath string, newpath string) (err error) { func Rename(oldpath string, newpath string) (err error) {
@ -80,41 +71,34 @@ func Rename(oldpath string, newpath string) (err error) {
} }
func Rmdir(path string) error { func Rmdir(path string) error {
return Unlinkat(AT_FDCWD, path, AT_REMOVEDIR) return unlinkat(AT_FDCWD, path, AT_REMOVEDIR)
} }
//sys Symlinkat(oldpath string, newdirfd int, newpath string) (err error) //sys symlinkat(oldpath string, newdirfd int, newpath string) (err error)
func Symlink(oldpath string, newpath string) (err error) { func Symlink(oldpath string, newpath string) (err error) {
return Symlinkat(oldpath, AT_FDCWD, newpath) return symlinkat(oldpath, AT_FDCWD, newpath)
} }
func Unlink(path string) error { func Unlink(path string) error {
return Unlinkat(AT_FDCWD, path, 0) return unlinkat(AT_FDCWD, path, 0)
} }
//sys Unlinkat(dirfd int, path string, flags int) (err error) //sys unlinkat(dirfd int, path string, flags int) (err error)
func Unlinkat(dirfd int, path string) error {
return unlinkat(dirfd, path, 0)
}
//sys utimes(path string, times *[2]Timeval) (err error) //sys utimes(path string, times *[2]Timeval) (err error)
func Utimes(path string, tv []Timeval) error { func Utimes(path string, tv []Timeval) (err error) {
if tv == nil { if tv == nil {
err := utimensat(AT_FDCWD, path, nil, 0)
if err != ENOSYS {
return err
}
return utimes(path, nil) return utimes(path, nil)
} }
if len(tv) != 2 { if len(tv) != 2 {
return EINVAL return EINVAL
} }
var ts [2]Timespec
ts[0] = NsecToTimespec(TimevalToNsec(tv[0]))
ts[1] = NsecToTimespec(TimevalToNsec(tv[1]))
err := utimensat(AT_FDCWD, path, (*[2]Timespec)(unsafe.Pointer(&ts[0])), 0)
if err != ENOSYS {
return err
}
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
} }
@ -139,7 +123,8 @@ func UtimesNano(path string, ts []Timespec) error {
// in 2.6.22, Released, 8 July 2007) then fall back to utimes // in 2.6.22, Released, 8 July 2007) then fall back to utimes
var tv [2]Timeval var tv [2]Timeval
for i := 0; i < 2; i++ { for i := 0; i < 2; i++ {
tv[i] = NsecToTimeval(TimespecToNsec(ts[i])) tv[i].Sec = ts[i].Sec
tv[i].Usec = ts[i].Nsec / 1000
} }
return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0]))) return utimes(path, (*[2]Timeval)(unsafe.Pointer(&tv[0])))
} }
@ -398,60 +383,6 @@ func (sa *SockaddrNetlink) sockaddr() (unsafe.Pointer, _Socklen, error) {
return unsafe.Pointer(&sa.raw), SizeofSockaddrNetlink, nil return unsafe.Pointer(&sa.raw), SizeofSockaddrNetlink, nil
} }
type SockaddrHCI struct {
Dev uint16
Channel uint16
raw RawSockaddrHCI
}
func (sa *SockaddrHCI) sockaddr() (unsafe.Pointer, _Socklen, error) {
sa.raw.Family = AF_BLUETOOTH
sa.raw.Dev = sa.Dev
sa.raw.Channel = sa.Channel
return unsafe.Pointer(&sa.raw), SizeofSockaddrHCI, nil
}
// SockaddrCAN implements the Sockaddr interface for AF_CAN type sockets.
// The RxID and TxID fields are used for transport protocol addressing in
// (CAN_TP16, CAN_TP20, CAN_MCNET, and CAN_ISOTP), they can be left with
// zero values for CAN_RAW and CAN_BCM sockets as they have no meaning.
//
// The SockaddrCAN struct must be bound to the socket file descriptor
// using Bind before the CAN socket can be used.
//
// // Read one raw CAN frame
// fd, _ := Socket(AF_CAN, SOCK_RAW, CAN_RAW)
// addr := &SockaddrCAN{Ifindex: index}
// Bind(fd, addr)
// frame := make([]byte, 16)
// Read(fd, frame)
//
// The full SocketCAN documentation can be found in the linux kernel
// archives at: https://www.kernel.org/doc/Documentation/networking/can.txt
type SockaddrCAN struct {
Ifindex int
RxID uint32
TxID uint32
raw RawSockaddrCAN
}
func (sa *SockaddrCAN) sockaddr() (unsafe.Pointer, _Socklen, error) {
if sa.Ifindex < 0 || sa.Ifindex > 0x7fffffff {
return nil, 0, EINVAL
}
sa.raw.Family = AF_CAN
sa.raw.Ifindex = int32(sa.Ifindex)
rx := (*[4]byte)(unsafe.Pointer(&sa.RxID))
for i := 0; i < 4; i++ {
sa.raw.Addr[i] = rx[i]
}
tx := (*[4]byte)(unsafe.Pointer(&sa.TxID))
for i := 0; i < 4; i++ {
sa.raw.Addr[i+4] = tx[i]
}
return unsafe.Pointer(&sa.raw), SizeofSockaddrCAN, nil
}
func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) { func anyToSockaddr(rsa *RawSockaddrAny) (Sockaddr, error) {
switch rsa.Addr.Family { switch rsa.Addr.Family {
case AF_NETLINK: case AF_NETLINK:
@ -917,6 +848,7 @@ func Mount(source string, target string, fstype string, flags uintptr, data stri
//sysnb EpollCreate(size int) (fd int, err error) //sysnb EpollCreate(size int) (fd int, err error)
//sysnb EpollCreate1(flag int) (fd int, err error) //sysnb EpollCreate1(flag int) (fd int, err error)
//sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error) //sysnb EpollCtl(epfd int, op int, fd int, event *EpollEvent) (err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Exit(code int) = SYS_EXIT_GROUP //sys Exit(code int) = SYS_EXIT_GROUP
//sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error) //sys Faccessat(dirfd int, path string, mode uint32, flags int) (err error)
//sys Fallocate(fd int, mode uint32, off int64, len int64) (err error) //sys Fallocate(fd int, mode uint32, off int64, len int64) (err error)
@ -940,7 +872,6 @@ func Getpgrp() (pid int) {
//sysnb Getppid() (ppid int) //sysnb Getppid() (ppid int)
//sys Getpriority(which int, who int) (prio int, err error) //sys Getpriority(which int, who int) (prio int, err error)
//sysnb Getrusage(who int, rusage *Rusage) (err error) //sysnb Getrusage(who int, rusage *Rusage) (err error)
//sysnb Getsid(pid int) (sid int, err error)
//sysnb Gettid() (tid int) //sysnb Gettid() (tid int)
//sys Getxattr(path string, attr string, dest []byte) (sz int, err error) //sys Getxattr(path string, attr string, dest []byte) (sz int, err error)
//sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error) //sys InotifyAddWatch(fd int, pathname string, mask uint32) (watchdesc int, err error)
@ -952,8 +883,9 @@ func Getpgrp() (pid int) {
//sys Mkdirat(dirfd int, path string, mode uint32) (err error) //sys Mkdirat(dirfd int, path string, mode uint32) (err error)
//sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error) //sys Mknodat(dirfd int, path string, mode uint32, dev int) (err error)
//sys Nanosleep(time *Timespec, leftover *Timespec) (err error) //sys Nanosleep(time *Timespec, leftover *Timespec) (err error)
//sys Pause() (err error)
//sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT //sys PivotRoot(newroot string, putold string) (err error) = SYS_PIVOT_ROOT
//sysnb prlimit(pid int, resource int, newlimit *Rlimit, old *Rlimit) (err error) = SYS_PRLIMIT64 //sysnb prlimit(pid int, resource int, old *Rlimit, newlimit *Rlimit) (err error) = SYS_PRLIMIT64
//sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error) //sys Prctl(option int, arg2 uintptr, arg3 uintptr, arg4 uintptr, arg5 uintptr) (err error)
//sys read(fd int, p []byte) (n int, err error) //sys read(fd int, p []byte) (n int, err error)
//sys Removexattr(path string, attr string) (err error) //sys Removexattr(path string, attr string) (err error)
@ -963,7 +895,6 @@ func Getpgrp() (pid int) {
//sysnb Setpgid(pid int, pgid int) (err error) //sysnb Setpgid(pid int, pgid int) (err error)
//sysnb Setsid() (pid int, err error) //sysnb Setsid() (pid int, err error)
//sysnb Settimeofday(tv *Timeval) (err error) //sysnb Settimeofday(tv *Timeval) (err error)
//sys Setns(fd int, nstype int) (err error)
// issue 1435. // issue 1435.
// On linux Setuid and Setgid only affects the current thread, not the process. // On linux Setuid and Setgid only affects the current thread, not the process.
@ -990,6 +921,7 @@ func Setgid(uid int) (err error) {
//sys Unmount(target string, flags int) (err error) = SYS_UMOUNT2 //sys Unmount(target string, flags int) (err error) = SYS_UMOUNT2
//sys Unshare(flags int) (err error) //sys Unshare(flags int) (err error)
//sys Ustat(dev int, ubuf *Ustat_t) (err error) //sys Ustat(dev int, ubuf *Ustat_t) (err error)
//sys Utime(path string, buf *Utimbuf) (err error)
//sys write(fd int, p []byte) (n int, err error) //sys write(fd int, p []byte) (n int, err error)
//sys exitThread(code int) (err error) = SYS_EXIT //sys exitThread(code int) (err error) = SYS_EXIT
//sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ //sys readlen(fd int, p *byte, np int) (n int, err error) = SYS_READ
@ -1089,6 +1021,8 @@ func Munmap(b []byte) (err error) {
// Newfstatat // Newfstatat
// Nfsservctl // Nfsservctl
// Personality // Personality
// Poll
// Ppoll
// Pselect6 // Pselect6
// Ptrace // Ptrace
// Putpmsg // Putpmsg

View File

@ -24,6 +24,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Sec = int32(nsec / 1e9) tv.Sec = int32(nsec / 1e9)
@ -91,8 +93,6 @@ func Pipe2(p []int, flags int) (err error) {
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT //sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error) //sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Pause() (err error)
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) { func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
page := uintptr(offset / 4096) page := uintptr(offset / 4096)
@ -181,8 +181,6 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
//sysnb Gettimeofday(tv *Timeval) (err error) //sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Time(t *Time_t) (tt Time_t, err error) //sysnb Time(t *Time_t) (tt Time_t, err error)
//sys Utime(path string, buf *Utimbuf) (err error)
// On x86 Linux, all the socket calls go through an extra indirection, // On x86 Linux, all the socket calls go through an extra indirection,
// I think because the 5-register system call interface can't handle // I think because the 5-register system call interface can't handle
// the 6-argument calls like sendto and recvfrom. Instead the // the 6-argument calls like sendto and recvfrom. Instead the
@ -388,12 +386,3 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@ -6,8 +6,9 @@
package unix package unix
import "syscall"
//sys Dup2(oldfd int, newfd int) (err error) //sys Dup2(oldfd int, newfd int) (err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64 //sys Fadvise(fd int, offset int64, length int64, advice int) (err error) = SYS_FADVISE64
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstat(fd int, stat *Stat_t) (err error)
@ -24,7 +25,6 @@ package unix
//sys Lchown(path string, uid int, gid int) (err error) //sys Lchown(path string, uid int, gid int) (err error)
//sys Listen(s int, n int) (err error) //sys Listen(s int, n int) (err error)
//sys Lstat(path string, stat *Stat_t) (err error) //sys Lstat(path string, stat *Stat_t) (err error)
//sys Pause() (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 //sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
@ -61,6 +61,9 @@ package unix
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error) //sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) //sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
//go:noescape
func gettimeofday(tv *Timeval) (err syscall.Errno)
func Gettimeofday(tv *Timeval) (err error) { func Gettimeofday(tv *Timeval) (err error) {
errno := gettimeofday(tv) errno := gettimeofday(tv)
if errno != 0 { if errno != 0 {
@ -83,8 +86,6 @@ func Time(t *Time_t) (tt Time_t, err error) {
return Time_t(tv.Sec), nil return Time_t(tv.Sec), nil
} }
//sys Utime(path string, buf *Utimbuf) (err error)
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
@ -93,6 +94,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Sec = nsec / 1e9 tv.Sec = nsec / 1e9
@ -141,12 +144,3 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length) cmsg.Len = uint64(length)
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@ -1,13 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build amd64,linux
// +build !gccgo
package unix
import "syscall"
//go:noescape
func gettimeofday(tv *Timeval) (err syscall.Errno)

View File

@ -108,28 +108,7 @@ func Seek(fd int, offset int64, whence int) (newoffset int64, err error) {
// Vsyscalls on amd64. // Vsyscalls on amd64.
//sysnb Gettimeofday(tv *Timeval) (err error) //sysnb Gettimeofday(tv *Timeval) (err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) //sysnb Time(t *Time_t) (tt Time_t, err error)
//sys Pause() (err error)
func Time(t *Time_t) (Time_t, error) {
var tv Timeval
err := Gettimeofday(&tv)
if err != nil {
return 0, err
}
if t != nil {
*t = Time_t(tv.Sec)
}
return Time_t(tv.Sec), nil
}
func Utime(path string, buf *Utimbuf) error {
tv := []Timeval{
{Sec: buf.Actime},
{Sec: buf.Modtime},
}
return Utimes(path, tv)
}
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 //sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
@ -179,7 +158,7 @@ type rlimit32 struct {
Max uint32 Max uint32
} }
//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_UGETRLIMIT //sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT
const rlimInf32 = ^uint32(0) const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0) const rlimInf64 = ^uint64(0)
@ -252,12 +231,3 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length) cmsg.Len = uint32(length)
} }
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@ -6,7 +6,8 @@
package unix package unix
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error) = SYS_EPOLL_PWAIT const _SYS_dup = SYS_DUP3
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error) //sys Fstatat(fd int, path string, stat *Stat_t, flags int) (err error)
@ -69,6 +70,7 @@ func Lstat(path string, stat *Stat_t) (err error) {
func Getpagesize() int { return 65536 } func Getpagesize() int { return 65536 }
//sysnb Gettimeofday(tv *Timeval) (err error) //sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Time(t *Time_t) (tt Time_t, err error)
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
@ -78,6 +80,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Sec = nsec / 1e9 tv.Sec = nsec / 1e9
@ -85,26 +89,6 @@ func NsecToTimeval(nsec int64) (tv Timeval) {
return return
} }
func Time(t *Time_t) (Time_t, error) {
var tv Timeval
err := Gettimeofday(&tv)
if err != nil {
return 0, err
}
if t != nil {
*t = Time_t(tv.Sec)
}
return Time_t(tv.Sec), nil
}
func Utime(path string, buf *Utimbuf) error {
tv := []Timeval{
{Sec: buf.Actime},
{Sec: buf.Modtime},
}
return Utimes(path, tv)
}
func Pipe(p []int) (err error) { func Pipe(p []int) (err error) {
if len(p) != 2 { if len(p) != 2 {
return EINVAL return EINVAL
@ -149,18 +133,6 @@ func InotifyInit() (fd int, err error) {
return InotifyInit1(0) return InotifyInit1(0)
} }
func Dup2(oldfd int, newfd int) (err error) {
return Dup3(oldfd, newfd, 0)
}
func Pause() (err error) {
_, _, e1 := Syscall6(SYS_PPOLL, 0, 0, 0, 0, 0, 0)
if e1 != 0 {
err = errnoErr(e1)
}
return
}
// TODO(dfc): constants that should be in zsysnum_linux_arm64.go, remove // TODO(dfc): constants that should be in zsysnum_linux_arm64.go, remove
// these when the deprecated syscalls that the syscall package relies on // these when the deprecated syscalls that the syscall package relies on
// are removed. // are removed.
@ -176,15 +148,3 @@ const (
SYS_EPOLL_CREATE = 1042 SYS_EPOLL_CREATE = 1042
SYS_EPOLL_WAIT = 1069 SYS_EPOLL_WAIT = 1069
) )
func Poll(fds []PollFd, timeout int) (n int, err error) {
var ts *Timespec
if timeout >= 0 {
ts = new(Timespec)
*ts = NsecToTimespec(int64(timeout) * 1e6)
}
if len(fds) == 0 {
return ppoll(nil, 0, ts, nil)
}
return ppoll(&fds[0], len(fds), ts, nil)
}

View File

@ -1,208 +0,0 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
// +build mips64 mips64le
package unix
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstatfs(fd int, buf *Statfs_t) (err error)
//sys Ftruncate(fd int, length int64) (err error)
//sysnb Getegid() (egid int)
//sysnb Geteuid() (euid int)
//sysnb Getgid() (gid int)
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Getuid() (uid int)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Listen(s int, n int) (err error)
//sys Pause() (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS_PSELECT6
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error)
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setrlimit(resource int, rlim *Rlimit) (err error)
//sysnb Setreuid(ruid int, euid int) (err error)
//sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys Statfs(path string, buf *Statfs_t) (err error)
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
//sys Truncate(path string, length int64) (err error)
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
//sysnb setgroups(n int, list *_Gid_t) (err error)
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
//sysnb socket(domain int, typ int, proto int) (fd int, err error)
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error)
func Getpagesize() int { return 65536 }
//sysnb Gettimeofday(tv *Timeval) (err error)
func Time(t *Time_t) (tt Time_t, err error) {
var tv Timeval
err = Gettimeofday(&tv)
if err != nil {
return 0, err
}
if t != nil {
*t = Time_t(tv.Sec)
}
return Time_t(tv.Sec), nil
}
//sys Utime(path string, buf *Utimbuf) (err error)
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = nsec / 1e9
ts.Nsec = nsec % 1e9
return
}
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Sec = nsec / 1e9
tv.Usec = nsec % 1e9 / 1e3
return
}
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, 0)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func Ioperm(from int, num int, on int) (err error) {
return ENOSYS
}
func Iopl(level int) (err error) {
return ENOSYS
}
type stat_t struct {
Dev uint32
Pad0 [3]int32
Ino uint64
Mode uint32
Nlink uint32
Uid uint32
Gid uint32
Rdev uint32
Pad1 [3]uint32
Size int64
Atime uint32
Atime_nsec uint32
Mtime uint32
Mtime_nsec uint32
Ctime uint32
Ctime_nsec uint32
Blksize uint32
Pad2 uint32
Blocks int64
}
//sys fstat(fd int, st *stat_t) (err error)
//sys lstat(path string, st *stat_t) (err error)
//sys stat(path string, st *stat_t) (err error)
func Fstat(fd int, s *Stat_t) (err error) {
st := &stat_t{}
err = fstat(fd, st)
fillStat_t(s, st)
return
}
func Lstat(path string, s *Stat_t) (err error) {
st := &stat_t{}
err = lstat(path, st)
fillStat_t(s, st)
return
}
func Stat(path string, s *Stat_t) (err error) {
st := &stat_t{}
err = stat(path, st)
fillStat_t(s, st)
return
}
func fillStat_t(s *Stat_t, st *stat_t) {
s.Dev = st.Dev
s.Ino = st.Ino
s.Mode = st.Mode
s.Nlink = st.Nlink
s.Uid = st.Uid
s.Gid = st.Gid
s.Rdev = st.Rdev
s.Size = st.Size
s.Atim = Timespec{int64(st.Atime), int64(st.Atime_nsec)}
s.Mtim = Timespec{int64(st.Mtime), int64(st.Mtime_nsec)}
s.Ctim = Timespec{int64(st.Ctime), int64(st.Ctime_nsec)}
s.Blksize = st.Blksize
s.Blocks = st.Blocks
}
func (r *PtraceRegs) PC() uint64 { return r.Regs[64] }
func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = pc }
func (iov *Iovec) SetLen(length int) {
iov.Len = uint64(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint64(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

View File

@ -1,241 +0,0 @@
// Copyright 2016 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build linux
// +build mips mipsle
package unix
import (
"syscall"
"unsafe"
)
func Syscall9(trap, a1, a2, a3, a4, a5, a6, a7, a8, a9 uintptr) (r1, r2 uintptr, err syscall.Errno)
//sys Dup2(oldfd int, newfd int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error)
//sys Ftruncate(fd int, length int64) (err error) = SYS_FTRUNCATE64
//sysnb Getegid() (egid int)
//sysnb Geteuid() (euid int)
//sysnb Getgid() (gid int)
//sysnb Getuid() (uid int)
//sys Lchown(path string, uid int, gid int) (err error)
//sys Listen(s int, n int) (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Select(nfd int, r *FdSet, w *FdSet, e *FdSet, timeout *Timeval) (n int, err error) = SYS__NEWSELECT
//sys sendfile(outfd int, infd int, offset *int64, count int) (written int, err error) = SYS_SENDFILE64
//sys Setfsgid(gid int) (err error)
//sys Setfsuid(uid int) (err error)
//sysnb Setregid(rgid int, egid int) (err error)
//sysnb Setresgid(rgid int, egid int, sgid int) (err error)
//sysnb Setresuid(ruid int, euid int, suid int) (err error)
//sysnb Setreuid(ruid int, euid int) (err error)
//sys Shutdown(fd int, how int) (err error)
//sys Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
//sys SyncFileRange(fd int, off int64, n int64, flags int) (err error)
//sys Truncate(path string, length int64) (err error) = SYS_TRUNCATE64
//sys accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
//sys accept4(s int, rsa *RawSockaddrAny, addrlen *_Socklen, flags int) (fd int, err error)
//sys bind(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sys connect(s int, addr unsafe.Pointer, addrlen _Socklen) (err error)
//sysnb getgroups(n int, list *_Gid_t) (nn int, err error)
//sysnb setgroups(n int, list *_Gid_t) (err error)
//sys getsockopt(s int, level int, name int, val unsafe.Pointer, vallen *_Socklen) (err error)
//sys setsockopt(s int, level int, name int, val unsafe.Pointer, vallen uintptr) (err error)
//sysnb socket(domain int, typ int, proto int) (fd int, err error)
//sysnb socketpair(domain int, typ int, proto int, fd *[2]int32) (err error)
//sysnb getpeername(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sysnb getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error)
//sys recvfrom(fd int, p []byte, flags int, from *RawSockaddrAny, fromlen *_Socklen) (n int, err error)
//sys sendto(s int, buf []byte, flags int, to unsafe.Pointer, addrlen _Socklen) (err error)
//sys recvmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sys sendmsg(s int, msg *Msghdr, flags int) (n int, err error)
//sysnb InotifyInit() (fd int, err error)
//sys Ioperm(from int, num int, on int) (err error)
//sys Iopl(level int) (err error)
//sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Time(t *Time_t) (tt Time_t, err error)
//sys Lstat(path string, stat *Stat_t) (err error) = SYS_LSTAT64
//sys Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
//sys Stat(path string, stat *Stat_t) (err error) = SYS_STAT64
//sys Utime(path string, buf *Utimbuf) (err error)
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Pause() (err error)
func Fstatfs(fd int, buf *Statfs_t) (err error) {
_, _, e := Syscall(SYS_FSTATFS64, uintptr(fd), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
use(unsafe.Pointer(buf))
if e != 0 {
err = errnoErr(e)
}
return
}
func Statfs(path string, buf *Statfs_t) (err error) {
p, err := BytePtrFromString(path)
if err != nil {
return err
}
_, _, e := Syscall(SYS_STATFS64, uintptr(unsafe.Pointer(p)), unsafe.Sizeof(*buf), uintptr(unsafe.Pointer(buf)))
use(unsafe.Pointer(p))
if e != 0 {
err = errnoErr(e)
}
return
}
func Seek(fd int, offset int64, whence int) (off int64, err error) {
_, _, e := Syscall6(SYS__LLSEEK, uintptr(fd), uintptr(offset>>32), uintptr(offset), uintptr(unsafe.Pointer(&off)), uintptr(whence), 0)
if e != 0 {
err = errnoErr(e)
}
return
}
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) {
ts.Sec = int32(nsec / 1e9)
ts.Nsec = int32(nsec % 1e9)
return
}
func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond
tv.Sec = int32(nsec / 1e9)
tv.Usec = int32(nsec % 1e9 / 1e3)
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, 0)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sys mmap2(addr uintptr, length uintptr, prot int, flags int, fd int, pageOffset uintptr) (xaddr uintptr, err error)
func mmap(addr uintptr, length uintptr, prot int, flags int, fd int, offset int64) (xaddr uintptr, err error) {
page := uintptr(offset / 4096)
if offset != int64(page)*4096 {
return 0, EINVAL
}
return mmap2(addr, length, prot, flags, fd, page)
}
const rlimInf32 = ^uint32(0)
const rlimInf64 = ^uint64(0)
type rlimit32 struct {
Cur uint32
Max uint32
}
//sysnb getrlimit(resource int, rlim *rlimit32) (err error) = SYS_GETRLIMIT
func Getrlimit(resource int, rlim *Rlimit) (err error) {
err = prlimit(0, resource, nil, rlim)
if err != ENOSYS {
return err
}
rl := rlimit32{}
err = getrlimit(resource, &rl)
if err != nil {
return
}
if rl.Cur == rlimInf32 {
rlim.Cur = rlimInf64
} else {
rlim.Cur = uint64(rl.Cur)
}
if rl.Max == rlimInf32 {
rlim.Max = rlimInf64
} else {
rlim.Max = uint64(rl.Max)
}
return
}
//sysnb setrlimit(resource int, rlim *rlimit32) (err error) = SYS_SETRLIMIT
func Setrlimit(resource int, rlim *Rlimit) (err error) {
err = prlimit(0, resource, rlim, nil)
if err != ENOSYS {
return err
}
rl := rlimit32{}
if rlim.Cur == rlimInf64 {
rl.Cur = rlimInf32
} else if rlim.Cur < uint64(rlimInf32) {
rl.Cur = uint32(rlim.Cur)
} else {
return EINVAL
}
if rlim.Max == rlimInf64 {
rl.Max = rlimInf32
} else if rlim.Max < uint64(rlimInf32) {
rl.Max = uint32(rlim.Max)
} else {
return EINVAL
}
return setrlimit(resource, &rl)
}
func (r *PtraceRegs) PC() uint64 { return uint64(r.Regs[64]) }
func (r *PtraceRegs) SetPC(pc uint64) { r.Regs[64] = uint32(pc) }
func (iov *Iovec) SetLen(length int) {
iov.Len = uint32(length)
}
func (msghdr *Msghdr) SetControllen(length int) {
msghdr.Controllen = uint32(length)
}
func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint32(length)
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}
func Getpagesize() int { return 4096 }

View File

@ -7,8 +7,6 @@
package unix package unix
//sys EpollWait(epfd int, events []EpollEvent, msec int) (n int, err error)
//sys Dup2(oldfd int, newfd int) (err error)
//sys Fchown(fd int, uid int, gid int) (err error) //sys Fchown(fd int, uid int, gid int) (err error)
//sys Fstat(fd int, stat *Stat_t) (err error) //sys Fstat(fd int, stat *Stat_t) (err error)
//sys Fstatfs(fd int, buf *Statfs_t) (err error) //sys Fstatfs(fd int, buf *Statfs_t) (err error)
@ -18,13 +16,11 @@ package unix
//sysnb Getgid() (gid int) //sysnb Getgid() (gid int)
//sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT //sysnb Getrlimit(resource int, rlim *Rlimit) (err error) = SYS_UGETRLIMIT
//sysnb Getuid() (uid int) //sysnb Getuid() (uid int)
//sysnb InotifyInit() (fd int, err error)
//sys Ioperm(from int, num int, on int) (err error) //sys Ioperm(from int, num int, on int) (err error)
//sys Iopl(level int) (err error) //sys Iopl(level int) (err error)
//sys Lchown(path string, uid int, gid int) (err error) //sys Lchown(path string, uid int, gid int) (err error)
//sys Listen(s int, n int) (err error) //sys Listen(s int, n int) (err error)
//sys Lstat(path string, stat *Stat_t) (err error) //sys Lstat(path string, stat *Stat_t) (err error)
//sys Pause() (err error)
//sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64 //sys Pread(fd int, p []byte, offset int64) (n int, err error) = SYS_PREAD64
//sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64 //sys Pwrite(fd int, p []byte, offset int64) (n int, err error) = SYS_PWRITE64
//sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK //sys Seek(fd int, offset int64, whence int) (off int64, err error) = SYS_LSEEK
@ -66,8 +62,6 @@ func Getpagesize() int { return 65536 }
//sysnb Gettimeofday(tv *Timeval) (err error) //sysnb Gettimeofday(tv *Timeval) (err error)
//sysnb Time(t *Time_t) (tt Time_t, err error) //sysnb Time(t *Time_t) (tt Time_t, err error)
//sys Utime(path string, buf *Utimbuf) (err error)
func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) } func TimespecToNsec(ts Timespec) int64 { return int64(ts.Sec)*1e9 + int64(ts.Nsec) }
func NsecToTimespec(nsec int64) (ts Timespec) { func NsecToTimespec(nsec int64) (ts Timespec) {
@ -76,6 +70,8 @@ func NsecToTimespec(nsec int64) (ts Timespec) {
return return
} }
func TimevalToNsec(tv Timeval) int64 { return int64(tv.Sec)*1e9 + int64(tv.Usec)*1e3 }
func NsecToTimeval(nsec int64) (tv Timeval) { func NsecToTimeval(nsec int64) (tv Timeval) {
nsec += 999 // round up to microsecond nsec += 999 // round up to microsecond
tv.Sec = nsec / 1e9 tv.Sec = nsec / 1e9
@ -98,38 +94,3 @@ func (msghdr *Msghdr) SetControllen(length int) {
func (cmsg *Cmsghdr) SetLen(length int) { func (cmsg *Cmsghdr) SetLen(length int) {
cmsg.Len = uint64(length) cmsg.Len = uint64(length)
} }
//sysnb pipe(p *[2]_C_int) (err error)
func Pipe(p []int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe(&pp)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sysnb pipe2(p *[2]_C_int, flags int) (err error)
func Pipe2(p []int, flags int) (err error) {
if len(p) != 2 {
return EINVAL
}
var pp [2]_C_int
err = pipe2(&pp, flags)
p[0] = int(pp[0])
p[1] = int(pp[1])
return
}
//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error)
func Poll(fds []PollFd, timeout int) (n int, err error) {
if len(fds) == 0 {
return poll(nil, 0, timeout)
}
return poll(&fds[0], len(fds), timeout)
}

Some files were not shown because too many files have changed in this diff Show More