mirror of https://github.com/docker/cli.git
Merge pull request #1583 from jdrouet/compose-on-kube-sync
replace implementation by compose-on-kubernetes
This commit is contained in:
commit
adf71a41b2
|
@ -7,8 +7,8 @@ import (
|
|||
"os"
|
||||
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/kubernetes"
|
||||
cliv1beta1 "github.com/docker/cli/kubernetes/client/clientset/typed/compose/v1beta1"
|
||||
kubernetes "github.com/docker/compose-on-kubernetes/api"
|
||||
cliv1beta1 "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1"
|
||||
"github.com/pkg/errors"
|
||||
flag "github.com/spf13/pflag"
|
||||
kubeclient "k8s.io/client-go/kubernetes"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes"
|
||||
kubernetes "github.com/docker/compose-on-kubernetes/api"
|
||||
"github.com/pkg/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
kubeclient "k8s.io/client-go/kubernetes"
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/docker/cli/cli/command/service"
|
||||
"github.com/docker/cli/kubernetes/labels"
|
||||
"github.com/docker/compose-on-kubernetes/api/labels"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/docker/cli/cli/command/service"
|
||||
"github.com/docker/cli/kubernetes/labels"
|
||||
"github.com/docker/compose-on-kubernetes/api/labels"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
"gotest.tools/assert"
|
||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
"github.com/docker/cli/cli/compose/schema"
|
||||
composeTypes "github.com/docker/cli/cli/compose/types"
|
||||
composetypes "github.com/docker/cli/cli/compose/types"
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta1"
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
"github.com/pkg/errors"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/docker/cli/cli/command/service"
|
||||
"github.com/docker/cli/cli/command/stack/formatter"
|
||||
"github.com/docker/cli/cli/command/stack/options"
|
||||
"github.com/docker/cli/kubernetes/labels"
|
||||
"github.com/docker/compose-on-kubernetes/api/labels"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/api/types/swarm"
|
||||
appsv1beta2 "k8s.io/api/apps/v1beta2"
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"github.com/docker/cli/kubernetes/labels"
|
||||
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
"github.com/docker/compose-on-kubernetes/api/labels"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
|
|
|
@ -3,9 +3,9 @@ package kubernetes
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
composev1beta1 "github.com/docker/cli/kubernetes/client/clientset/typed/compose/v1beta1"
|
||||
composev1beta2 "github.com/docker/cli/kubernetes/client/clientset/typed/compose/v1beta2"
|
||||
"github.com/docker/cli/kubernetes/labels"
|
||||
composev1beta1 "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1"
|
||||
composev1beta2 "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2"
|
||||
"github.com/docker/compose-on-kubernetes/api/labels"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/rest"
|
||||
|
|
|
@ -5,8 +5,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
apiv1beta1 "github.com/docker/cli/kubernetes/compose/v1beta1"
|
||||
"github.com/docker/cli/kubernetes/labels"
|
||||
apiv1beta1 "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
"github.com/docker/compose-on-kubernetes/api/labels"
|
||||
"github.com/pkg/errors"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
|
@ -3,8 +3,8 @@ package kubernetes
|
|||
import (
|
||||
"testing"
|
||||
|
||||
apiv1beta1 "github.com/docker/cli/kubernetes/compose/v1beta1"
|
||||
composelabels "github.com/docker/cli/kubernetes/labels"
|
||||
apiv1beta1 "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
composelabels "github.com/docker/compose-on-kubernetes/api/labels"
|
||||
"gotest.tools/assert"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
|
@ -11,8 +11,8 @@ import (
|
|||
|
||||
"github.com/docker/cli/cli"
|
||||
"github.com/docker/cli/cli/command"
|
||||
"github.com/docker/cli/kubernetes"
|
||||
"github.com/docker/cli/templates"
|
||||
kubernetes "github.com/docker/compose-on-kubernetes/api"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
|
|
|
@ -1,55 +1,20 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
apiv1beta1 "github.com/docker/cli/kubernetes/compose/v1beta1"
|
||||
apiv1beta2 "github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"github.com/pkg/errors"
|
||||
apimachinerymetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api"
|
||||
|
||||
// StackVersion represents the detected Compose Component on Kubernetes side.
|
||||
type StackVersion string
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api.StackVersion instead
|
||||
type StackVersion = api.StackVersion
|
||||
|
||||
const (
|
||||
// StackAPIV1Beta1 is returned if it's the most recent version available.
|
||||
StackAPIV1Beta1 = StackVersion("v1beta1")
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api.StackAPIV1Beta1 instead
|
||||
StackAPIV1Beta1 = api.StackAPIV1Beta1
|
||||
// StackAPIV1Beta2 is returned if it's the most recent version available.
|
||||
StackAPIV1Beta2 = StackVersion("v1beta2")
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api.StackAPIV1Beta2 instead
|
||||
StackAPIV1Beta2 = api.StackAPIV1Beta2
|
||||
)
|
||||
|
||||
// GetStackAPIVersion returns the most recent stack API installed.
|
||||
func GetStackAPIVersion(clientSet *kubernetes.Clientset) (StackVersion, error) {
|
||||
groups, err := clientSet.Discovery().ServerGroups()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return getAPIVersion(groups)
|
||||
}
|
||||
|
||||
func getAPIVersion(groups *metav1.APIGroupList) (StackVersion, error) {
|
||||
switch {
|
||||
case findVersion(apiv1beta2.SchemeGroupVersion, groups.Groups):
|
||||
return StackAPIV1Beta2, nil
|
||||
case findVersion(apiv1beta1.SchemeGroupVersion, groups.Groups):
|
||||
return StackAPIV1Beta1, nil
|
||||
default:
|
||||
return "", errors.Errorf("failed to find a Stack API version")
|
||||
}
|
||||
}
|
||||
|
||||
func findVersion(stackAPI schema.GroupVersion, groups []apimachinerymetav1.APIGroup) bool {
|
||||
for _, group := range groups {
|
||||
if group.Name == stackAPI.Group {
|
||||
for _, version := range group.Versions {
|
||||
if version.Version == stackAPI.Version {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api.GetStackAPIVersion instead
|
||||
var GetStackAPIVersion = api.GetStackAPIVersion
|
||||
|
|
|
@ -1,51 +0,0 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
is "gotest.tools/assert/cmp"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestGetStackAPIVersion(t *testing.T) {
|
||||
var tests = []struct {
|
||||
description string
|
||||
groups *metav1.APIGroupList
|
||||
err bool
|
||||
expectedStack StackVersion
|
||||
}{
|
||||
{"no stack api", makeGroups(), true, ""},
|
||||
{"v1beta1", makeGroups(groupVersion{"compose.docker.com", []string{"v1beta1"}}), false, StackAPIV1Beta1},
|
||||
{"v1beta2", makeGroups(groupVersion{"compose.docker.com", []string{"v1beta2"}}), false, StackAPIV1Beta2},
|
||||
{"most recent has precedence", makeGroups(groupVersion{"compose.docker.com", []string{"v1beta1", "v1beta2"}}), false, StackAPIV1Beta2},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
version, err := getAPIVersion(test.groups)
|
||||
if test.err {
|
||||
assert.ErrorContains(t, err, "")
|
||||
} else {
|
||||
assert.NilError(t, err)
|
||||
}
|
||||
assert.Check(t, is.Equal(test.expectedStack, version))
|
||||
}
|
||||
}
|
||||
|
||||
type groupVersion struct {
|
||||
name string
|
||||
versions []string
|
||||
}
|
||||
|
||||
func makeGroups(versions ...groupVersion) *metav1.APIGroupList {
|
||||
groups := make([]metav1.APIGroup, len(versions))
|
||||
for i := range versions {
|
||||
groups[i].Name = versions[i].name
|
||||
for _, v := range versions[i].versions {
|
||||
groups[i].Versions = append(groups[i].Versions, metav1.GroupVersionForDiscovery{Version: v})
|
||||
}
|
||||
}
|
||||
return &metav1.APIGroupList{
|
||||
Groups: groups,
|
||||
}
|
||||
}
|
|
@ -1,96 +1,25 @@
|
|||
package clientset
|
||||
|
||||
import (
|
||||
composev1beta1 "github.com/docker/cli/kubernetes/client/clientset/typed/compose/v1beta1"
|
||||
composev1beta2 "github.com/docker/cli/kubernetes/client/clientset/typed/compose/v1beta2"
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/clientset"
|
||||
|
||||
// Interface defines the methods a compose kube client should have
|
||||
// FIXME(vdemeester) is it required ?
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
ComposeV1beta2() composev1beta2.ComposeV1beta2Interface
|
||||
ComposeV1beta1() composev1beta1.ComposeV1beta1Interface
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset.Interface instead
|
||||
type Interface = api.Interface
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
*composev1beta2.ComposeV1beta2Client
|
||||
*composev1beta1.ComposeV1beta1Client
|
||||
}
|
||||
|
||||
// ComposeV1beta2 retrieves the ComposeV1beta2Client
|
||||
func (c *Clientset) ComposeV1beta2() composev1beta2.ComposeV1beta2Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.ComposeV1beta2Client
|
||||
}
|
||||
|
||||
// ComposeV1beta1 retrieves the ComposeV1beta1Client
|
||||
func (c *Clientset) ComposeV1beta1() composev1beta1.ComposeV1beta1Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.ComposeV1beta1Client
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset.Clientset instead
|
||||
type Clientset = api.Clientset
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.ComposeV1beta2Client, err = composev1beta2.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cs.ComposeV1beta1Client, err = composev1beta1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to create the DiscoveryClient: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset.NewForConfig instead
|
||||
var NewForConfig = api.NewForConfig
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.ComposeV1beta2Client = composev1beta2.NewForConfigOrDie(c)
|
||||
cs.ComposeV1beta1Client = composev1beta1.NewForConfigOrDie(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
||||
return &cs
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset.NewForConfigOrDie instead
|
||||
var NewForConfigOrDie = api.NewForConfigOrDie
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.ComposeV1beta2Client = composev1beta2.New(c)
|
||||
cs.ComposeV1beta1Client = composev1beta1.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset.New instead
|
||||
var New = api.New
|
||||
|
|
|
@ -1,26 +1,17 @@
|
|||
package scheme
|
||||
|
||||
import (
|
||||
composev1beta1 "github.com/docker/cli/kubernetes/compose/v1beta1"
|
||||
composev1beta2 "github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/clientset/scheme"
|
||||
|
||||
// Variables required for registration
|
||||
var (
|
||||
Scheme = runtime.NewScheme()
|
||||
Codecs = serializer.NewCodecFactory(Scheme)
|
||||
ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/scheme.Scheme instead
|
||||
Scheme = api.Scheme
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/scheme.Codecs instead
|
||||
Codecs = api.Codecs
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/scheme.ParameterCodec instead
|
||||
ParameterCodec = api.ParameterCodec
|
||||
)
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
AddToScheme(Scheme)
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
|
@ -35,7 +26,5 @@ func init() {
|
|||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
composev1beta2.AddToScheme(scheme)
|
||||
composev1beta1.AddToScheme(scheme)
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/scheme.AddToScheme instead
|
||||
var AddToScheme = api.AddToScheme
|
||||
|
|
|
@ -1,74 +1,24 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/client/clientset/scheme"
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1"
|
||||
|
||||
// ComposeV1beta1Interface defines the methods a compose v1beta1 client has
|
||||
type ComposeV1beta1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
StacksGetter
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1.ComposeV1beta1Interface instead
|
||||
type ComposeV1beta1Interface = api.ComposeV1beta1Interface
|
||||
|
||||
// ComposeV1beta1Client is used to interact with features provided by the compose.docker.com group.
|
||||
type ComposeV1beta1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
// Stacks returns a stack client
|
||||
func (c *ComposeV1beta1Client) Stacks(namespace string) StackInterface {
|
||||
return newStacks(c, namespace)
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1.ComposeV1beta1Client instead
|
||||
type ComposeV1beta1Client = api.ComposeV1beta1Client
|
||||
|
||||
// NewForConfig creates a new ComposeV1beta1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ComposeV1beta1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ComposeV1beta1Client{client}, nil
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1.NewForConfig instead
|
||||
var NewForConfig = api.NewForConfig
|
||||
|
||||
// NewForConfigOrDie creates a new ComposeV1beta1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ComposeV1beta1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1.NewForConfigOrDie instead
|
||||
var NewForConfigOrDie = api.NewForConfigOrDie
|
||||
|
||||
// New creates a new ComposeV1beta1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *ComposeV1beta1Client {
|
||||
return &ComposeV1beta1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1beta1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ComposeV1beta1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1.New instead
|
||||
var New = api.New
|
||||
|
|
|
@ -1,157 +1,12 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/client/clientset/scheme"
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1"
|
||||
|
||||
// StacksGetter has a method to return a StackInterface.
|
||||
// A group's client should implement this interface.
|
||||
type StacksGetter interface {
|
||||
Stacks(namespace string) StackInterface
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1.StacksGetter instead
|
||||
type StacksGetter = api.StacksGetter
|
||||
|
||||
// StackInterface has methods to work with Stack resources.
|
||||
type StackInterface interface {
|
||||
Create(*v1beta1.Stack) (*v1beta1.Stack, error)
|
||||
Update(*v1beta1.Stack) (*v1beta1.Stack, error)
|
||||
UpdateStatus(*v1beta1.Stack) (*v1beta1.Stack, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1beta1.Stack, error)
|
||||
List(opts v1.ListOptions) (*v1beta1.StackList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*v1beta1.Stack, error)
|
||||
}
|
||||
|
||||
var _ StackInterface = &stacks{}
|
||||
|
||||
// stacks implements StackInterface
|
||||
type stacks struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newStacks returns a Stacks
|
||||
func newStacks(c *ComposeV1beta1Client, namespace string) *stacks {
|
||||
return &stacks{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Create takes the representation of a stack and creates it. Returns the server's representation of the stack, and an error, if there is any.
|
||||
func (c *stacks) Create(stack *v1beta1.Stack) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Body(stack).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a stack and updates it. Returns the server's representation of the stack, and an error, if there is any.
|
||||
func (c *stacks) Update(stack *v1beta1.Stack) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(stack.Name).
|
||||
Body(stack).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclientstatus=false comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *stacks) UpdateStatus(stack *v1beta1.Stack) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(stack.Name).
|
||||
SubResource("status").
|
||||
Body(stack).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Delete takes name of the stack and deletes it. Returns an error if one occurs.
|
||||
func (c *stacks) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *stacks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Get takes name of the stack, and returns the corresponding stack object, and an error if there is any.
|
||||
func (c *stacks) Get(name string, options v1.GetOptions) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Stacks that match those selectors.
|
||||
func (c *stacks) List(opts v1.ListOptions) (*v1beta1.StackList, error) {
|
||||
result := &v1beta1.StackList{}
|
||||
err := c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested stacks.
|
||||
func (c *stacks) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched stack.
|
||||
func (c *stacks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1.StackInterface instead
|
||||
type StackInterface = api.StackInterface
|
||||
|
|
|
@ -1,74 +1,24 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/client/clientset/scheme"
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2"
|
||||
|
||||
// ComposeV1beta2Interface defines the methods a compose v1beta2 client has
|
||||
type ComposeV1beta2Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
StacksGetter
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2.StackInterface instead
|
||||
type ComposeV1beta2Interface = api.ComposeV1beta2Interface
|
||||
|
||||
// ComposeV1beta2Client is used to interact with features provided by the compose.docker.com group.
|
||||
type ComposeV1beta2Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
// Stacks returns a stack client
|
||||
func (c *ComposeV1beta2Client) Stacks(namespace string) StackInterface {
|
||||
return newStacks(c, namespace)
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2.ComposeV1beta2Client instead
|
||||
type ComposeV1beta2Client = api.ComposeV1beta2Client
|
||||
|
||||
// NewForConfig creates a new ComposeV1beta2Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ComposeV1beta2Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ComposeV1beta2Client{client}, nil
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2.NewForConfig instead
|
||||
var NewForConfig = api.NewForConfig
|
||||
|
||||
// NewForConfigOrDie creates a new ComposeV1beta2Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ComposeV1beta2Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2.NewForConfigOrDie instead
|
||||
var NewForConfigOrDie = api.NewForConfigOrDie
|
||||
|
||||
// New creates a new ComposeV1beta2Client for the given RESTClient.
|
||||
func New(c rest.Interface) *ComposeV1beta2Client {
|
||||
return &ComposeV1beta2Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1beta2.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ComposeV1beta2Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2.New instead
|
||||
var New = api.New
|
||||
|
|
|
@ -1,155 +1,12 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/client/clientset/scheme"
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2"
|
||||
|
||||
// StacksGetter has a method to return a StackInterface.
|
||||
// A group's client should implement this interface.
|
||||
type StacksGetter interface {
|
||||
Stacks(namespace string) StackInterface
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2.StacksGetter instead
|
||||
type StacksGetter = api.StacksGetter
|
||||
|
||||
// StackInterface has methods to work with Stack resources.
|
||||
type StackInterface interface {
|
||||
Create(*v1beta2.Stack) (*v1beta2.Stack, error)
|
||||
Update(*v1beta2.Stack) (*v1beta2.Stack, error)
|
||||
UpdateStatus(*v1beta2.Stack) (*v1beta2.Stack, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1beta2.Stack, error)
|
||||
List(opts v1.ListOptions) (*v1beta2.StackList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*v1beta2.Stack, error)
|
||||
}
|
||||
|
||||
// stacks implements StackInterface
|
||||
type stacks struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newStacks returns a Stacks
|
||||
func newStacks(c *ComposeV1beta2Client, namespace string) *stacks {
|
||||
return &stacks{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
// Create takes the representation of a stack and creates it. Returns the server's representation of the stack, and an error, if there is any.
|
||||
func (c *stacks) Create(stack *v1beta2.Stack) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Body(stack).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a stack and updates it. Returns the server's representation of the stack, and an error, if there is any.
|
||||
func (c *stacks) Update(stack *v1beta2.Stack) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(stack.Name).
|
||||
Body(stack).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclientstatus=false comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *stacks) UpdateStatus(stack *v1beta2.Stack) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(stack.Name).
|
||||
SubResource("status").
|
||||
Body(stack).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Delete takes name of the stack and deletes it. Returns an error if one occurs.
|
||||
func (c *stacks) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(name).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *stacks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Get takes name of the stack, and returns the corresponding stack object, and an error if there is any.
|
||||
func (c *stacks) Get(name string, options v1.GetOptions) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Stacks that match those selectors.
|
||||
func (c *stacks) List(opts v1.ListOptions) (*v1beta2.StackList, error) {
|
||||
result := &v1beta2.StackList{}
|
||||
err := c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested stacks.
|
||||
func (c *stacks) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched stack.
|
||||
func (c *stacks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2.StackInterface instead
|
||||
type StackInterface = api.StackInterface
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
package compose
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/client/informers/compose/v1beta2"
|
||||
"github.com/docker/cli/kubernetes/client/informers/internalinterfaces"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/informers/compose"
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
V1beta2() v1beta2.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers/compose.Interface instead
|
||||
type Interface = api.Interface
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory) Interface {
|
||||
return &group{f}
|
||||
}
|
||||
|
||||
// V1beta2 returns a new v1beta2.Interface.
|
||||
func (g *group) V1beta2() v1beta2.Interface {
|
||||
return v1beta2.New(g.SharedInformerFactory)
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers/compose.New instead
|
||||
var New = api.New
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/client/informers/internalinterfaces"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2"
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// Stacks returns a StackInformer.
|
||||
Stacks() StackInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2.Interface instead
|
||||
type Interface = api.Interface
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory) Interface {
|
||||
return &version{f}
|
||||
}
|
||||
|
||||
// Stacks returns a StackInformer.
|
||||
func (v *version) Stacks() StackInformer {
|
||||
return &stackInformer{factory: v.SharedInformerFactory}
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2.New instead
|
||||
var New = api.New
|
||||
|
|
|
@ -1,51 +1,8 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/kubernetes/client/clientset"
|
||||
"github.com/docker/cli/kubernetes/client/informers/internalinterfaces"
|
||||
"github.com/docker/cli/kubernetes/client/listers/compose/v1beta2"
|
||||
compose_v1beta2 "github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2"
|
||||
|
||||
// StackInformer provides access to a shared informer and lister for
|
||||
// Stacks.
|
||||
type StackInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1beta2.StackLister
|
||||
}
|
||||
|
||||
type stackInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
}
|
||||
|
||||
func newStackInformer(client clientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
sharedIndexInformer := cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return client.ComposeV1beta2().Stacks(v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return client.ComposeV1beta2().Stacks(v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&compose_v1beta2.Stack{},
|
||||
resyncPeriod,
|
||||
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
|
||||
)
|
||||
|
||||
return sharedIndexInformer
|
||||
}
|
||||
|
||||
func (f *stackInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&compose_v1beta2.Stack{}, newStackInformer)
|
||||
}
|
||||
|
||||
func (f *stackInformer) Lister() v1beta2.StackLister {
|
||||
return v1beta2.NewStackLister(f.Informer().GetIndexer())
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2.StackInformer instead
|
||||
type StackInformer = api.StackInformer
|
||||
|
|
|
@ -1,101 +1,12 @@
|
|||
package informers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/kubernetes/client/clientset"
|
||||
"github.com/docker/cli/kubernetes/client/informers/compose"
|
||||
"github.com/docker/cli/kubernetes/client/informers/internalinterfaces"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client clientset.Interface
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
}
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/informers"
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory
|
||||
func NewSharedInformerFactory(client clientset.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return &sharedInformerFactory{
|
||||
client: client,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
go informer.Run(stopCh)
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
informer = newFunc(f.client, f.defaultResync)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers.NewSharedInformerFactory instead
|
||||
var NewSharedInformerFactory = api.NewSharedInformerFactory
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
Compose() compose.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Compose() compose.Interface {
|
||||
return compose.New(f)
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers.SharedInformerFactory instead
|
||||
type SharedInformerFactory = api.SharedInformerFactory
|
||||
|
|
|
@ -1,44 +1,8 @@
|
|||
package informers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/informers"
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=Compose, Version=V1beta1
|
||||
case v1beta2.SchemeGroupVersion.WithResource("stacks"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Compose().V1beta2().Stacks().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers.GenericInformer instead
|
||||
type GenericInformer = api.GenericInformer
|
||||
|
|
|
@ -1,18 +1,11 @@
|
|||
package internalinterfaces
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/cli/kubernetes/client/clientset"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces"
|
||||
|
||||
// NewInformerFunc defines a Informer constructor (from a clientset and a duration)
|
||||
type NewInformerFunc func(clientset.Interface, time.Duration) cache.SharedIndexInformer
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces.NewInformerFunc instead
|
||||
type NewInformerFunc = api.NewInformerFunc
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces.SharedInformerFactory instead
|
||||
type SharedInformerFactory = api.SharedInformerFactory
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
package v1beta2
|
||||
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2"
|
||||
|
||||
// StackListerExpansion allows custom methods to be added to
|
||||
// StackLister.
|
||||
type StackListerExpansion interface{}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2.StackListerExpansion instead
|
||||
type StackListerExpansion = api.StackListerExpansion
|
||||
|
||||
// StackNamespaceListerExpansion allows custom methods to be added to
|
||||
// StackNamespaceLister.
|
||||
type StackNamespaceListerExpansion interface{}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2.StackNamespaceListerExpansion instead
|
||||
type StackNamespaceListerExpansion = api.StackNamespaceListerExpansion
|
||||
|
|
|
@ -1,78 +1,15 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2"
|
||||
|
||||
// StackLister helps list Stacks.
|
||||
type StackLister interface {
|
||||
// List lists all Stacks in the indexer.
|
||||
List(selector labels.Selector) ([]*v1beta2.Stack, error)
|
||||
// Stacks returns an object that can list and get Stacks.
|
||||
Stacks(namespace string) StackNamespaceLister
|
||||
StackListerExpansion
|
||||
}
|
||||
|
||||
// stackLister implements the StackLister interface.
|
||||
type stackLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2.StackLister instead
|
||||
type StackLister = api.StackLister
|
||||
|
||||
// NewStackLister returns a new StackLister.
|
||||
func NewStackLister(indexer cache.Indexer) StackLister {
|
||||
return &stackLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all Stacks in the indexer.
|
||||
func (s *stackLister) List(selector labels.Selector) ([]*v1beta2.Stack, error) {
|
||||
stacks := []*v1beta2.Stack{}
|
||||
err := cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
stacks = append(stacks, m.(*v1beta2.Stack))
|
||||
})
|
||||
return stacks, err
|
||||
}
|
||||
|
||||
// Stacks returns an object that can list and get Stacks.
|
||||
func (s *stackLister) Stacks(namespace string) StackNamespaceLister {
|
||||
return stackNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2.NewStackLister instead
|
||||
var NewStackLister = api.NewStackLister
|
||||
|
||||
// StackNamespaceLister helps list and get Stacks.
|
||||
type StackNamespaceLister interface {
|
||||
// List lists all Stacks in the indexer for a given namespace.
|
||||
List(selector labels.Selector) ([]*v1beta2.Stack, error)
|
||||
// Get retrieves the Stack from the indexer for a given namespace and name.
|
||||
Get(name string) (*v1beta2.Stack, error)
|
||||
StackNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// stackNamespaceLister implements the StackNamespaceLister
|
||||
// interface.
|
||||
type stackNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all Stacks in the indexer for a given namespace.
|
||||
func (s stackNamespaceLister) List(selector labels.Selector) ([]*v1beta2.Stack, error) {
|
||||
stacks := []*v1beta2.Stack{}
|
||||
err := cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
stacks = append(stacks, m.(*v1beta2.Stack))
|
||||
})
|
||||
return stacks, err
|
||||
}
|
||||
|
||||
// Get retrieves the Stack from the indexer for a given namespace and name.
|
||||
func (s stackNamespaceLister) Get(name string) (*v1beta2.Stack, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1beta2.GroupResource("stack"), name)
|
||||
}
|
||||
return obj.(*v1beta2.Stack), nil
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2.StackNamespaceLister instead
|
||||
type StackNamespaceLister = api.StackNamespaceLister
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
package clone
|
||||
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/clone"
|
||||
|
||||
// MapOfStringToSliceOfString deep copy a map[string][]string
|
||||
func MapOfStringToSliceOfString(source map[string][]string) map[string][]string {
|
||||
if source == nil {
|
||||
return nil
|
||||
}
|
||||
res := make(map[string][]string, len(source))
|
||||
for k, v := range source {
|
||||
res[k] = SliceOfString(v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/clone.MapOfStringToSliceOfString instead
|
||||
var MapOfStringToSliceOfString = api.MapOfStringToSliceOfString
|
||||
|
||||
// MapOfStringToInt deep copy a map[string]int
|
||||
func MapOfStringToInt(source map[string]int) map[string]int {
|
||||
if source == nil {
|
||||
return nil
|
||||
}
|
||||
res := make(map[string]int, len(source))
|
||||
for k, v := range source {
|
||||
res[k] = v
|
||||
}
|
||||
return res
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/clone.MapOfStringToInt instead
|
||||
var MapOfStringToInt = api.MapOfStringToInt
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
package clone
|
||||
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/clone"
|
||||
|
||||
// SliceOfString deep copy a slice of strings
|
||||
func SliceOfString(source []string) []string {
|
||||
if source == nil {
|
||||
return nil
|
||||
}
|
||||
res := make([]string, len(source))
|
||||
copy(res, source)
|
||||
return res
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/clone.SliceOfString instead
|
||||
var SliceOfString = api.SliceOfString
|
||||
|
|
|
@ -1,26 +1,7 @@
|
|||
package impersonation
|
||||
|
||||
import "github.com/docker/cli/kubernetes/compose/clone"
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/impersonation"
|
||||
|
||||
// Config contains the data required to impersonate a user.
|
||||
type Config struct {
|
||||
// UserName is the username to impersonate on each request.
|
||||
UserName string
|
||||
// Groups are the groups to impersonate on each request.
|
||||
Groups []string
|
||||
// Extra is a free-form field which can be used to link some authentication information
|
||||
// to authorization information. This field allows you to impersonate it.
|
||||
Extra map[string][]string
|
||||
}
|
||||
|
||||
// Clone clones the impersonation config
|
||||
func (ic *Config) Clone() *Config {
|
||||
if ic == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(Config)
|
||||
result.UserName = ic.UserName
|
||||
result.Groups = clone.SliceOfString(ic.Groups)
|
||||
result.Extra = clone.MapOfStringToSliceOfString(ic.Extra)
|
||||
return result
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/impersonation.Config instead
|
||||
type Config = api.Config
|
||||
|
|
|
@ -1,31 +1,8 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/compose/impersonation"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
|
||||
// Owner defines the owner of a stack. It is used to impersonate the controller calls
|
||||
// to kubernetes api.
|
||||
type Owner struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Owner impersonation.Config `json:"owner,omitempty"`
|
||||
}
|
||||
|
||||
func (o *Owner) clone() *Owner {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(Owner)
|
||||
result.TypeMeta = o.TypeMeta
|
||||
result.ObjectMeta = o.ObjectMeta
|
||||
result.Owner = *result.Owner.Clone()
|
||||
return result
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the owner
|
||||
func (o *Owner) DeepCopyObject() runtime.Object {
|
||||
return o.clone()
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.Owner instead
|
||||
type Owner = api.Owner
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
package v1beta1
|
||||
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
|
||||
// MaxComposeVersion is the most recent version of compose file Schema supported in v1beta1
|
||||
const MaxComposeVersion = "3.5"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.MaxComposeVersion instead
|
||||
const MaxComposeVersion = api.MaxComposeVersion
|
||||
|
|
|
@ -1,39 +1,22 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
|
||||
// GroupName is the group name used to register these objects
|
||||
const GroupName = "compose.docker.com"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.GroupName instead
|
||||
const GroupName = api.GroupName
|
||||
|
||||
// Alias variables for the registration
|
||||
var (
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.SchemeGroupVersion instead
|
||||
SchemeGroupVersion = api.SchemeGroupVersion
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.SchemeBuilder instead
|
||||
SchemeBuilder = api.SchemeBuilder
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.AddToScheme instead
|
||||
AddToScheme = api.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(addKnownTypes)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Stack{},
|
||||
&StackList{},
|
||||
&Owner{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.Resource instead
|
||||
var Resource = api.Resource
|
||||
|
|
|
@ -1,87 +1,37 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
|
||||
// StackList defines a list of stacks
|
||||
type StackList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
Items []Stack `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the stack list
|
||||
func (s *StackList) DeepCopyObject() runtime.Object {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(StackList)
|
||||
result.TypeMeta = s.TypeMeta
|
||||
result.ListMeta = s.ListMeta
|
||||
if s.Items == nil {
|
||||
return result
|
||||
}
|
||||
result.Items = make([]Stack, len(s.Items))
|
||||
for ix, s := range s.Items {
|
||||
result.Items[ix] = *s.clone()
|
||||
}
|
||||
return result
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.StackList instead
|
||||
type StackList = api.StackList
|
||||
|
||||
// Stack defines a stack object to be register in the kubernetes API
|
||||
type Stack struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec StackSpec `json:"spec,omitempty"`
|
||||
Status StackStatus `json:"status,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.Stack instead
|
||||
type Stack = api.Stack
|
||||
|
||||
// StackSpec defines the desired state of Stack
|
||||
type StackSpec struct {
|
||||
ComposeFile string `json:"composeFile,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.StackSpec instead
|
||||
type StackSpec = api.StackSpec
|
||||
|
||||
// StackPhase defines the status phase in which the stack is.
|
||||
type StackPhase string
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.StackPhase instead
|
||||
type StackPhase = api.StackPhase
|
||||
|
||||
// These are valid conditions of a stack.
|
||||
const (
|
||||
// StackAvailable means the stack is available.
|
||||
StackAvailable StackPhase = "Available"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.StackAvailable instead
|
||||
StackAvailable StackPhase = api.StackAvailable
|
||||
// StackProgressing means the deployment is progressing.
|
||||
StackProgressing StackPhase = "Progressing"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.StackProgressing instead
|
||||
StackProgressing StackPhase = api.StackProgressing
|
||||
// StackFailure is added in a stack when one of its members fails to be created
|
||||
// or deleted.
|
||||
StackFailure StackPhase = "Failure"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.StackFailure instead
|
||||
StackFailure StackPhase = api.StackFailure
|
||||
)
|
||||
|
||||
// StackStatus defines the observed state of Stack
|
||||
type StackStatus struct {
|
||||
// Current condition of the stack.
|
||||
Phase StackPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=StackPhase"`
|
||||
// A human readable message indicating details about the stack.
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
|
||||
}
|
||||
|
||||
func (s *Stack) clone() *Stack {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
// in v1beta1, Stack has no pointer, slice or map. Plain old struct copy is ok
|
||||
result := *s
|
||||
return &result
|
||||
}
|
||||
|
||||
// Clone implements the Cloner interface for kubernetes
|
||||
func (s *Stack) Clone() *Stack {
|
||||
return s.clone()
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the stack
|
||||
func (s *Stack) DeepCopyObject() runtime.Object {
|
||||
return s.clone()
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta1.StackStatus instead
|
||||
type StackStatus = api.StackStatus
|
||||
|
|
|
@ -1,26 +1,7 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
|
||||
// ComposeFile is the content of a stack's compose file if any
|
||||
type ComposeFile struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
ComposeFile string `json:"composeFile,omitempty"`
|
||||
}
|
||||
|
||||
func (c *ComposeFile) clone() *ComposeFile {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
res := *c
|
||||
return &res
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the ComposeFile
|
||||
func (c *ComposeFile) DeepCopyObject() runtime.Object {
|
||||
return c.clone()
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.ComposeFile instead
|
||||
type ComposeFile = api.ComposeFile
|
||||
|
|
|
@ -1,30 +1,7 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/compose/impersonation"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
|
||||
// Owner describes the user who created the stack
|
||||
type Owner struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Owner impersonation.Config `json:"owner,omitempty"`
|
||||
}
|
||||
|
||||
func (o *Owner) clone() *Owner {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(Owner)
|
||||
result.TypeMeta = o.TypeMeta
|
||||
result.ObjectMeta = o.ObjectMeta
|
||||
result.Owner = *result.Owner.Clone()
|
||||
return result
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the owner
|
||||
func (o *Owner) DeepCopyObject() runtime.Object {
|
||||
return o.clone()
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Owner instead
|
||||
type Owner = api.Owner
|
||||
|
|
|
@ -1,42 +1,23 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
|
||||
// GroupName is the name of the compose group
|
||||
const GroupName = "compose.docker.com"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Owner instead
|
||||
const GroupName = api.GroupName
|
||||
|
||||
var (
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta2"}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.SchemeGroupVersion instead
|
||||
SchemeGroupVersion = api.SchemeGroupVersion
|
||||
// SchemeBuilder is the scheme builder
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.SchemeBuilder instead
|
||||
SchemeBuilder = api.SchemeBuilder
|
||||
// AddToScheme adds to scheme
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.AddToScheme instead
|
||||
AddToScheme = api.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(addKnownTypes)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Stack{},
|
||||
&StackList{},
|
||||
&Owner{},
|
||||
&ComposeFile{},
|
||||
&Scale{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GroupResource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func GroupResource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.GroupResource instead
|
||||
var GroupResource = api.GroupResource
|
||||
|
|
|
@ -1,29 +1,7 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/cli/kubernetes/compose/clone"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
|
||||
// Scale contains the current/desired replica count for services in a stack.
|
||||
type Scale struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Spec map[string]int `json:"spec,omitempty"`
|
||||
Status map[string]int `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Scale) clone() *Scale {
|
||||
return &Scale{
|
||||
TypeMeta: s.TypeMeta,
|
||||
ObjectMeta: s.ObjectMeta,
|
||||
Spec: clone.MapOfStringToInt(s.Spec),
|
||||
Status: clone.MapOfStringToInt(s.Status),
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the scale
|
||||
func (s *Scale) DeepCopyObject() runtime.Object {
|
||||
return s.clone()
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Scale instead
|
||||
type Scale = api.Scale
|
||||
|
|
|
@ -1,256 +1,115 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
|
||||
// StackList is a list of stacks
|
||||
type StackList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
Items []Stack `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.StackList instead
|
||||
type StackList = api.StackList
|
||||
|
||||
// Stack is v1beta2's representation of a Stack
|
||||
type Stack struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec *StackSpec `json:"spec,omitempty"`
|
||||
Status *StackStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the stack
|
||||
func (s *Stack) DeepCopyObject() runtime.Object {
|
||||
return s.clone()
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the stack list
|
||||
func (s *StackList) DeepCopyObject() runtime.Object {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(StackList)
|
||||
result.TypeMeta = s.TypeMeta
|
||||
result.ListMeta = s.ListMeta
|
||||
if s.Items == nil {
|
||||
return result
|
||||
}
|
||||
result.Items = make([]Stack, len(s.Items))
|
||||
for ix, s := range s.Items {
|
||||
result.Items[ix] = *s.clone()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Stack) clone() *Stack {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(Stack)
|
||||
result.TypeMeta = s.TypeMeta
|
||||
result.ObjectMeta = s.ObjectMeta
|
||||
result.Spec = s.Spec.clone()
|
||||
result.Status = s.Status.clone()
|
||||
return result
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Stack instead
|
||||
type Stack = api.Stack
|
||||
|
||||
// StackSpec defines the desired state of Stack
|
||||
type StackSpec struct {
|
||||
Services []ServiceConfig `json:"services,omitempty"`
|
||||
Secrets map[string]SecretConfig `json:"secrets,omitempty"`
|
||||
Configs map[string]ConfigObjConfig `json:"configs,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.StackSpec instead
|
||||
type StackSpec = api.StackSpec
|
||||
|
||||
// ServiceConfig is the configuration of one service
|
||||
type ServiceConfig struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
CapAdd []string `json:"cap_add,omitempty"`
|
||||
CapDrop []string `json:"cap_drop,omitempty"`
|
||||
Command []string `json:"command,omitempty"`
|
||||
Configs []ServiceConfigObjConfig `json:"configs,omitempty"`
|
||||
Deploy DeployConfig `json:"deploy,omitempty"`
|
||||
Entrypoint []string `json:"entrypoint,omitempty"`
|
||||
Environment map[string]*string `json:"environment,omitempty"`
|
||||
ExtraHosts []string `json:"extra_hosts,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
HealthCheck *HealthCheckConfig `json:"health_check,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Ipc string `json:"ipc,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Pid string `json:"pid,omitempty"`
|
||||
Ports []ServicePortConfig `json:"ports,omitempty"`
|
||||
Privileged bool `json:"privileged,omitempty"`
|
||||
ReadOnly bool `json:"read_only,omitempty"`
|
||||
Secrets []ServiceSecretConfig `json:"secrets,omitempty"`
|
||||
StdinOpen bool `json:"stdin_open,omitempty"`
|
||||
StopGracePeriod *time.Duration `json:"stop_grace_period,omitempty"`
|
||||
Tmpfs []string `json:"tmpfs,omitempty"`
|
||||
Tty bool `json:"tty,omitempty"`
|
||||
User *int64 `json:"user,omitempty"`
|
||||
Volumes []ServiceVolumeConfig `json:"volumes,omitempty"`
|
||||
WorkingDir string `json:"working_dir,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.ServiceConfig instead
|
||||
type ServiceConfig = api.ServiceConfig
|
||||
|
||||
// ServicePortConfig is the port configuration for a service
|
||||
type ServicePortConfig struct {
|
||||
Mode string `json:"mode,omitempty"`
|
||||
Target uint32 `json:"target,omitempty"`
|
||||
Published uint32 `json:"published,omitempty"`
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.ServicePortConfig instead
|
||||
type ServicePortConfig = api.ServicePortConfig
|
||||
|
||||
// FileObjectConfig is a config type for a file used by a service
|
||||
type FileObjectConfig struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
File string `json:"file,omitempty"`
|
||||
External External `json:"external,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.FileObjectConfig instead
|
||||
type FileObjectConfig = api.FileObjectConfig
|
||||
|
||||
// SecretConfig for a secret
|
||||
type SecretConfig FileObjectConfig
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.SecretConfig instead
|
||||
type SecretConfig = api.SecretConfig
|
||||
|
||||
// ConfigObjConfig is the config for the swarm "Config" object
|
||||
type ConfigObjConfig FileObjectConfig
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.ConfigObjConfig instead
|
||||
type ConfigObjConfig = api.ConfigObjConfig
|
||||
|
||||
// External identifies a Volume or Network as a reference to a resource that is
|
||||
// not managed, and should already exist.
|
||||
// External.name is deprecated and replaced by Volume.name
|
||||
type External struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
External bool `json:"external,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.External instead
|
||||
type External = api.External
|
||||
|
||||
// FileReferenceConfig for a reference to a swarm file object
|
||||
type FileReferenceConfig struct {
|
||||
Source string `json:"source,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
UID string `json:"uid,omitempty"`
|
||||
GID string `json:"gid,omitempty"`
|
||||
Mode *uint32 `json:"mode,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.FileReferenceConfig instead
|
||||
type FileReferenceConfig = api.FileReferenceConfig
|
||||
|
||||
// ServiceConfigObjConfig is the config obj configuration for a service
|
||||
type ServiceConfigObjConfig FileReferenceConfig
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.ServiceConfigObjConfig instead
|
||||
type ServiceConfigObjConfig = api.ServiceConfigObjConfig
|
||||
|
||||
// ServiceSecretConfig is the secret configuration for a service
|
||||
type ServiceSecretConfig FileReferenceConfig
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.ServiceSecretConfig instead
|
||||
type ServiceSecretConfig = api.ServiceSecretConfig
|
||||
|
||||
// DeployConfig is the deployment configuration for a service
|
||||
type DeployConfig struct {
|
||||
Mode string `json:"mode,omitempty"`
|
||||
Replicas *uint64 `json:"replicas,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
UpdateConfig *UpdateConfig `json:"update_config,omitempty"`
|
||||
Resources Resources `json:"resources,omitempty"`
|
||||
RestartPolicy *RestartPolicy `json:"restart_policy,omitempty"`
|
||||
Placement Placement `json:"placement,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.DeployConfig instead
|
||||
type DeployConfig = api.DeployConfig
|
||||
|
||||
// UpdateConfig is the service update configuration
|
||||
type UpdateConfig struct {
|
||||
Parallelism *uint64 `json:"paralellism,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.UpdateConfig instead
|
||||
type UpdateConfig = api.UpdateConfig
|
||||
|
||||
// Resources the resource limits and reservations
|
||||
type Resources struct {
|
||||
Limits *Resource `json:"limits,omitempty"`
|
||||
Reservations *Resource `json:"reservations,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Resources instead
|
||||
type Resources = api.Resources
|
||||
|
||||
// Resource is a resource to be limited or reserved
|
||||
type Resource struct {
|
||||
NanoCPUs string `json:"cpus,omitempty"`
|
||||
MemoryBytes int64 `json:"memory,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Resource instead
|
||||
type Resource = api.Resource
|
||||
|
||||
// RestartPolicy is the service restart policy
|
||||
type RestartPolicy struct {
|
||||
Condition string `json:"condition,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.RestartPolicy instead
|
||||
type RestartPolicy = api.RestartPolicy
|
||||
|
||||
// Placement constraints for the service
|
||||
type Placement struct {
|
||||
Constraints *Constraints `json:"constraints,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Placement instead
|
||||
type Placement = api.Placement
|
||||
|
||||
// Constraints lists constraints that can be set on the service
|
||||
type Constraints struct {
|
||||
OperatingSystem *Constraint
|
||||
Architecture *Constraint
|
||||
Hostname *Constraint
|
||||
MatchLabels map[string]Constraint
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Constraints instead
|
||||
type Constraints = api.Constraints
|
||||
|
||||
// Constraint defines a constraint and it's operator (== or !=)
|
||||
type Constraint struct {
|
||||
Value string
|
||||
Operator string
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.Constraint instead
|
||||
type Constraint = api.Constraint
|
||||
|
||||
// HealthCheckConfig the healthcheck configuration for a service
|
||||
type HealthCheckConfig struct {
|
||||
Test []string `json:"test,omitempty"`
|
||||
Timeout *time.Duration `json:"timeout,omitempty"`
|
||||
Interval *time.Duration `json:"interval,omitempty"`
|
||||
Retries *uint64 `json:"retries,omitempty"`
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.HealthCheckConfig instead
|
||||
type HealthCheckConfig = api.HealthCheckConfig
|
||||
|
||||
// ServiceVolumeConfig are references to a volume used by a service
|
||||
type ServiceVolumeConfig struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
ReadOnly bool `json:"read_only,omitempty"`
|
||||
}
|
||||
|
||||
func (s *StackSpec) clone() *StackSpec {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := *s
|
||||
return &result
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.ServiceVolumeConfig instead
|
||||
type ServiceVolumeConfig = api.ServiceVolumeConfig
|
||||
|
||||
// StackPhase is the deployment phase of a stack
|
||||
type StackPhase string
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.StackPhase instead
|
||||
type StackPhase = api.StackPhase
|
||||
|
||||
// These are valid conditions of a stack.
|
||||
const (
|
||||
// StackAvailable means the stack is available.
|
||||
StackAvailable StackPhase = "Available"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.StackAvailable instead
|
||||
StackAvailable StackPhase = api.StackAvailable
|
||||
// StackProgressing means the deployment is progressing.
|
||||
StackProgressing StackPhase = "Progressing"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.StackProgressing instead
|
||||
StackProgressing StackPhase = api.StackProgressing
|
||||
// StackFailure is added in a stack when one of its members fails to be created
|
||||
// or deleted.
|
||||
StackFailure StackPhase = "Failure"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.StackFailure instead
|
||||
StackFailure StackPhase = api.StackFailure
|
||||
)
|
||||
|
||||
// StackStatus defines the observed state of Stack
|
||||
type StackStatus struct {
|
||||
// Current condition of the stack.
|
||||
// +optional
|
||||
Phase StackPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=StackPhase"`
|
||||
// A human readable message indicating details about the stack.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
|
||||
}
|
||||
|
||||
func (s *StackStatus) clone() *StackStatus {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := *s
|
||||
return &result
|
||||
}
|
||||
|
||||
// Clone clones a Stack
|
||||
func (s *Stack) Clone() *Stack {
|
||||
return s.clone()
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/compose/v1beta2.StackStatus instead
|
||||
type StackStatus = api.StackStatus
|
||||
|
|
|
@ -1,26 +1,8 @@
|
|||
package kubernetes
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
import api "github.com/docker/compose-on-kubernetes/api"
|
||||
|
||||
// NewKubernetesConfig resolves the path to the desired Kubernetes configuration file based on
|
||||
// the KUBECONFIG environment variable and command line flags.
|
||||
func NewKubernetesConfig(configPath string) clientcmd.ClientConfig {
|
||||
kubeConfig := configPath
|
||||
if kubeConfig == "" {
|
||||
if config := os.Getenv("KUBECONFIG"); config != "" {
|
||||
kubeConfig = config
|
||||
} else {
|
||||
kubeConfig = filepath.Join(homedir.Get(), ".kube/config")
|
||||
}
|
||||
}
|
||||
|
||||
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
|
||||
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfig},
|
||||
&clientcmd.ConfigOverrides{})
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api.NewKubernetesConfig instead
|
||||
var NewKubernetesConfig = api.NewKubernetesConfig
|
||||
|
|
|
@ -1,45 +1,24 @@
|
|||
package labels
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
import labels "github.com/docker/compose-on-kubernetes/api/labels"
|
||||
|
||||
const (
|
||||
// ForServiceName is the label for the service name.
|
||||
ForServiceName = "com.docker.service.name"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/labels.ForServiceName instead
|
||||
ForServiceName = labels.ForServiceName
|
||||
// ForStackName is the label for the stack name.
|
||||
ForStackName = "com.docker.stack.namespace"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/labels.ForStackName instead
|
||||
ForStackName = labels.ForStackName
|
||||
// ForServiceID is the label for the service id.
|
||||
ForServiceID = "com.docker.service.id"
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/labels.ForServiceID instead
|
||||
ForServiceID = labels.ForServiceID
|
||||
)
|
||||
|
||||
// ForService gives the labels to select a given service in a stack.
|
||||
func ForService(stackName, serviceName string) map[string]string {
|
||||
labels := map[string]string{}
|
||||
|
||||
if serviceName != "" {
|
||||
labels[ForServiceName] = serviceName
|
||||
}
|
||||
if stackName != "" {
|
||||
labels[ForStackName] = stackName
|
||||
}
|
||||
if serviceName != "" && stackName != "" {
|
||||
labels[ForServiceID] = stackName + "-" + serviceName
|
||||
}
|
||||
|
||||
return labels
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/labels.ForService instead
|
||||
var ForService = labels.ForService
|
||||
|
||||
// SelectorForStack gives the labelSelector to use for a given stack.
|
||||
// Specific service names can be passed to narrow down the selection.
|
||||
func SelectorForStack(stackName string, serviceNames ...string) string {
|
||||
switch len(serviceNames) {
|
||||
case 0:
|
||||
return fmt.Sprintf("%s=%s", ForStackName, stackName)
|
||||
case 1:
|
||||
return fmt.Sprintf("%s=%s,%s=%s", ForStackName, stackName, ForServiceName, serviceNames[0])
|
||||
default:
|
||||
return fmt.Sprintf("%s=%s,%s in (%s)", ForStackName, stackName, ForServiceName, strings.Join(serviceNames, ","))
|
||||
}
|
||||
}
|
||||
// Deprecated: Use github.com/docker/compose-on-kubernetes/api/labels.SelectorForStack instead
|
||||
var SelectorForStack = labels.SelectorForStack
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package labels
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
is "gotest.tools/assert/cmp"
|
||||
)
|
||||
|
||||
func TestForService(t *testing.T) {
|
||||
labels := ForService("stack", "service")
|
||||
|
||||
assert.Check(t, is.Len(labels, 3))
|
||||
assert.Check(t, is.Equal("stack", labels["com.docker.stack.namespace"]))
|
||||
assert.Check(t, is.Equal("service", labels["com.docker.service.name"]))
|
||||
assert.Check(t, is.Equal("stack-service", labels["com.docker.service.id"]))
|
||||
}
|
||||
|
||||
func TestSelectorForStack(t *testing.T) {
|
||||
assert.Check(t, is.Equal("com.docker.stack.namespace=demostack", SelectorForStack("demostack")))
|
||||
assert.Check(t, is.Equal("com.docker.stack.namespace=stack,com.docker.service.name=service", SelectorForStack("stack", "service")))
|
||||
assert.Check(t, is.Equal("com.docker.stack.namespace=stack,com.docker.service.name in (service1,service2)", SelectorForStack("stack", "service1", "service2")))
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
cloud.google.com/go 0ebda48a7f143b1cce9eb37a8c1106ac762a3430 # v0.34.0
|
||||
github.com/agl/ed25519 5312a61534124124185d41f09206b9fef1d88403
|
||||
github.com/asaskevich/govalidator f9ffefc3facfbe0caee3fea233cbb6e8208f4541
|
||||
github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109
|
||||
|
@ -13,6 +14,7 @@ github.com/davecgh/go-spew 346938d642f2ec3594ed81d874461961cd0faa76 # v1.1.0
|
|||
github.com/dgrijalva/jwt-go a2c85815a77d0f951e33ba4db5ae93629a1530af
|
||||
github.com/docker/distribution 83389a148052d74ac602f5f1d62f86ff2f3c4aa5
|
||||
github.com/docker/docker 6e3113f700dea1bf2785d94731b4b5a1e602d9ab
|
||||
github.com/docker/compose-on-kubernetes a6086e2369e39c2058a003a7eb42e567ecfd1f03 # v0.4.17
|
||||
github.com/docker/docker-credential-helpers 5241b46610f2491efdf9d1c85f1ddf5b02f6d962
|
||||
# the docker/go package contains a customized version of canonical/json
|
||||
# and is used by Notary. The package is periodically rebased on current Go versions.
|
||||
|
@ -83,6 +85,7 @@ github.com/xeipuuv/gojsonreference bd5ef7bd5415a7ac448318e64f11a24cd21e594b
|
|||
github.com/xeipuuv/gojsonschema 93e72a773fade158921402d6a24c819b48aba29d
|
||||
golang.org/x/crypto 0709b304e793a5edb4a2c0145f281ecdc20838a4
|
||||
golang.org/x/net a680a1efc54dd51c040b3b5ce4939ea3cf2ea0d1
|
||||
golang.org/x/oauth2 ef147856a6ddbb60760db74283d2424e98c87bff
|
||||
golang.org/x/sync 1d60e4601c6fd243af51cc01ddf169918a5407ca
|
||||
golang.org/x/sys 1b2967e3c290b7c545b3db0deeda16e9be4f98a2
|
||||
golang.org/x/text f21a4dfb5e38f5895301dc265a8def02365cc3d0 # v0.3.0
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,505 @@
|
|||
# Google Cloud Client Libraries for Go
|
||||
|
||||
[![GoDoc](https://godoc.org/cloud.google.com/go?status.svg)](https://godoc.org/cloud.google.com/go)
|
||||
|
||||
Go packages for [Google Cloud Platform](https://cloud.google.com) services.
|
||||
|
||||
``` go
|
||||
import "cloud.google.com/go"
|
||||
```
|
||||
|
||||
To install the packages on your system, *do not clone the repo*. Instead use
|
||||
|
||||
```
|
||||
$ go get -u cloud.google.com/go/...
|
||||
```
|
||||
|
||||
**NOTE:** Some of these packages are under development, and may occasionally
|
||||
make backwards-incompatible changes.
|
||||
|
||||
**NOTE:** Github repo is a mirror of [https://code.googlesource.com/gocloud](https://code.googlesource.com/gocloud).
|
||||
|
||||
* [News](#news)
|
||||
* [Supported APIs](#supported-apis)
|
||||
* [Go Versions Supported](#go-versions-supported)
|
||||
* [Authorization](#authorization)
|
||||
* [Cloud Datastore](#cloud-datastore-)
|
||||
* [Cloud Storage](#cloud-storage-)
|
||||
* [Cloud Pub/Sub](#cloud-pub-sub-)
|
||||
* [BigQuery](#cloud-bigquery-)
|
||||
* [Stackdriver Logging](#stackdriver-logging-)
|
||||
* [Cloud Spanner](#cloud-spanner-)
|
||||
|
||||
|
||||
## News
|
||||
|
||||
_7 August 2018_
|
||||
|
||||
As of November 1, the code in the repo will no longer support Go versions 1.8
|
||||
and earlier. No one other than AppEngine users should be on those old versions,
|
||||
and AppEngine
|
||||
[Standard](https://groups.google.com/forum/#!topic/google-appengine-go/e7oPNomd7ak)
|
||||
and
|
||||
[Flex](https://groups.google.com/forum/#!topic/google-appengine-go/wHsYtxvEbXI)
|
||||
will stop supporting new deployments with those versions on that date.
|
||||
|
||||
|
||||
Changes have been moved to [CHANGES](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/CHANGES.md).
|
||||
|
||||
|
||||
## Supported APIs
|
||||
|
||||
Google API | Status | Package
|
||||
---------------------------------------------|--------------|-----------------------------------------------------------
|
||||
[Asset][cloud-asset] | alpha | [`godoc.org/cloud.google.com/go/asset/v1beta`][cloud-asset-ref]
|
||||
[BigQuery][cloud-bigquery] | stable | [`godoc.org/cloud.google.com/go/bigquery`][cloud-bigquery-ref]
|
||||
[Bigtable][cloud-bigtable] | stable | [`godoc.org/cloud.google.com/go/bigtable`][cloud-bigtable-ref]
|
||||
[Cloudtasks][cloud-tasks] | beta | [`godoc.org/cloud.google.com/go/cloudtasks/apiv2beta3`][cloud-tasks-ref]
|
||||
[Container][cloud-container] | stable | [`godoc.org/cloud.google.com/go/container/apiv1`][cloud-container-ref]
|
||||
[ContainerAnalysis][cloud-containeranalysis] | beta | [`godoc.org/cloud.google.com/go/containeranalysis/apiv1beta1`][cloud-containeranalysis-ref]
|
||||
[Dataproc][cloud-dataproc] | stable | [`godoc.org/cloud.google.com/go/dataproc/apiv1`][cloud-dataproc-ref]
|
||||
[Datastore][cloud-datastore] | stable | [`godoc.org/cloud.google.com/go/datastore`][cloud-datastore-ref]
|
||||
[Debugger][cloud-debugger] | alpha | [`godoc.org/cloud.google.com/go/debugger/apiv2`][cloud-debugger-ref]
|
||||
[Dialogflow][cloud-dialogflow] | alpha | [`godoc.org/cloud.google.com/go/dialogflow/apiv2`][cloud-dialogflow-ref]
|
||||
[Data Loss Prevention][cloud-dlp] | alpha | [`godoc.org/cloud.google.com/go/dlp/apiv2`][cloud-dlp-ref]
|
||||
[ErrorReporting][cloud-errors] | alpha | [`godoc.org/cloud.google.com/go/errorreporting`][cloud-errors-ref]
|
||||
[Firestore][cloud-firestore] | beta | [`godoc.org/cloud.google.com/go/firestore`][cloud-firestore-ref]
|
||||
[IAM][cloud-iam] | stable | [`godoc.org/cloud.google.com/go/iam`][cloud-iam-ref]
|
||||
[KMS][cloud-kms] | stable | [`godoc.org/cloud.google.com/go/kms`][cloud-kms-ref]
|
||||
[Natural Language][cloud-natural-language] | stable | [`godoc.org/cloud.google.com/go/language/apiv1`][cloud-natural-language-ref]
|
||||
[Logging][cloud-logging] | stable | [`godoc.org/cloud.google.com/go/logging`][cloud-logging-ref]
|
||||
[Monitoring][cloud-monitoring] | alpha | [`godoc.org/cloud.google.com/go/monitoring/apiv3`][cloud-monitoring-ref]
|
||||
[OS Login][cloud-oslogin] | alpha | [`cloud.google.com/compute/docs/oslogin/rest`][cloud-oslogin-ref]
|
||||
[Pub/Sub][cloud-pubsub] | stable | [`godoc.org/cloud.google.com/go/pubsub`][cloud-pubsub-ref]
|
||||
[Memorystore][cloud-memorystore] | stable | [`godoc.org/cloud.google.com/go/redis/apiv1beta1`][cloud-memorystore-ref]
|
||||
[Spanner][cloud-spanner] | stable | [`godoc.org/cloud.google.com/go/spanner`][cloud-spanner-ref]
|
||||
[Speech][cloud-speech] | stable | [`godoc.org/cloud.google.com/go/speech/apiv1`][cloud-speech-ref]
|
||||
[Storage][cloud-storage] | stable | [`godoc.org/cloud.google.com/go/storage`][cloud-storage-ref]
|
||||
[Text To Speech][cloud-texttospeech] | alpha | [`godoc.org/cloud.google.com/go/texttospeech/apiv1`][cloud-storage-ref]
|
||||
[Trace][cloud-trace] | alpha | [`godoc.org/cloud.google.com/go/trace/apiv2`][cloud-translation-ref]
|
||||
[Translation][cloud-translation] | stable | [`godoc.org/cloud.google.com/go/translate`][cloud-translation-ref]
|
||||
[Video Intelligence][cloud-video] | alpha | [`godoc.org/cloud.google.com/go/videointelligence/apiv1beta1`][cloud-video-ref]
|
||||
[Vision][cloud-vision] | stable | [`godoc.org/cloud.google.com/go/vision/apiv1`][cloud-vision-ref]
|
||||
|
||||
> **Alpha status**: the API is still being actively developed. As a
|
||||
> result, it might change in backward-incompatible ways and is not recommended
|
||||
> for production use.
|
||||
>
|
||||
> **Beta status**: the API is largely complete, but still has outstanding
|
||||
> features and bugs to be addressed. There may be minor backwards-incompatible
|
||||
> changes where necessary.
|
||||
>
|
||||
> **Stable status**: the API is mature and ready for production use. We will
|
||||
> continue addressing bugs and feature requests.
|
||||
|
||||
Documentation and examples are available at
|
||||
https://godoc.org/cloud.google.com/go
|
||||
|
||||
Visit or join the
|
||||
[google-api-go-announce group](https://groups.google.com/forum/#!forum/google-api-go-announce)
|
||||
for updates on these packages.
|
||||
|
||||
## Go Versions Supported
|
||||
|
||||
We support the two most recent major versions of Go. If Google App Engine uses
|
||||
an older version, we support that as well.
|
||||
|
||||
## Authorization
|
||||
|
||||
By default, each API will use [Google Application Default Credentials][default-creds]
|
||||
for authorization credentials used in calling the API endpoints. This will allow your
|
||||
application to run in many environments without requiring explicit configuration.
|
||||
|
||||
[snip]:# (auth)
|
||||
```go
|
||||
client, err := storage.NewClient(ctx)
|
||||
```
|
||||
|
||||
To authorize using a
|
||||
[JSON key file](https://cloud.google.com/iam/docs/managing-service-account-keys),
|
||||
pass
|
||||
[`option.WithCredentialsFile`](https://godoc.org/google.golang.org/api/option#WithCredentialsFile)
|
||||
to the `NewClient` function of the desired package. For example:
|
||||
|
||||
[snip]:# (auth-JSON)
|
||||
```go
|
||||
client, err := storage.NewClient(ctx, option.WithCredentialsFile("path/to/keyfile.json"))
|
||||
```
|
||||
|
||||
You can exert more control over authorization by using the
|
||||
[`golang.org/x/oauth2`](https://godoc.org/golang.org/x/oauth2) package to
|
||||
create an `oauth2.TokenSource`. Then pass
|
||||
[`option.WithTokenSource`](https://godoc.org/google.golang.org/api/option#WithTokenSource)
|
||||
to the `NewClient` function:
|
||||
[snip]:# (auth-ts)
|
||||
```go
|
||||
tokenSource := ...
|
||||
client, err := storage.NewClient(ctx, option.WithTokenSource(tokenSource))
|
||||
```
|
||||
|
||||
## Cloud Datastore [![GoDoc](https://godoc.org/cloud.google.com/go/datastore?status.svg)](https://godoc.org/cloud.google.com/go/datastore)
|
||||
|
||||
- [About Cloud Datastore][cloud-datastore]
|
||||
- [Activating the API for your project][cloud-datastore-activation]
|
||||
- [API documentation][cloud-datastore-docs]
|
||||
- [Go client documentation](https://godoc.org/cloud.google.com/go/datastore)
|
||||
- [Complete sample program](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/datastore/tasks)
|
||||
|
||||
### Example Usage
|
||||
|
||||
First create a `datastore.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (datastore-1)
|
||||
```go
|
||||
client, err := datastore.NewClient(ctx, "my-project-id")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
Then use that client to interact with the API:
|
||||
|
||||
[snip]:# (datastore-2)
|
||||
```go
|
||||
type Post struct {
|
||||
Title string
|
||||
Body string `datastore:",noindex"`
|
||||
PublishedAt time.Time
|
||||
}
|
||||
keys := []*datastore.Key{
|
||||
datastore.NameKey("Post", "post1", nil),
|
||||
datastore.NameKey("Post", "post2", nil),
|
||||
}
|
||||
posts := []*Post{
|
||||
{Title: "Post 1", Body: "...", PublishedAt: time.Now()},
|
||||
{Title: "Post 2", Body: "...", PublishedAt: time.Now()},
|
||||
}
|
||||
if _, err := client.PutMulti(ctx, keys, posts); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
## Cloud Storage [![GoDoc](https://godoc.org/cloud.google.com/go/storage?status.svg)](https://godoc.org/cloud.google.com/go/storage)
|
||||
|
||||
- [About Cloud Storage][cloud-storage]
|
||||
- [API documentation][cloud-storage-docs]
|
||||
- [Go client documentation](https://godoc.org/cloud.google.com/go/storage)
|
||||
- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/storage)
|
||||
|
||||
### Example Usage
|
||||
|
||||
First create a `storage.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (storage-1)
|
||||
```go
|
||||
client, err := storage.NewClient(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
[snip]:# (storage-2)
|
||||
```go
|
||||
// Read the object1 from bucket.
|
||||
rc, err := client.Bucket("bucket").Object("object1").NewReader(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer rc.Close()
|
||||
body, err := ioutil.ReadAll(rc)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
## Cloud Pub/Sub [![GoDoc](https://godoc.org/cloud.google.com/go/pubsub?status.svg)](https://godoc.org/cloud.google.com/go/pubsub)
|
||||
|
||||
- [About Cloud Pubsub][cloud-pubsub]
|
||||
- [API documentation][cloud-pubsub-docs]
|
||||
- [Go client documentation](https://godoc.org/cloud.google.com/go/pubsub)
|
||||
- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/pubsub)
|
||||
|
||||
### Example Usage
|
||||
|
||||
First create a `pubsub.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (pubsub-1)
|
||||
```go
|
||||
client, err := pubsub.NewClient(ctx, "project-id")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
Then use the client to publish and subscribe:
|
||||
|
||||
[snip]:# (pubsub-2)
|
||||
```go
|
||||
// Publish "hello world" on topic1.
|
||||
topic := client.Topic("topic1")
|
||||
res := topic.Publish(ctx, &pubsub.Message{
|
||||
Data: []byte("hello world"),
|
||||
})
|
||||
// The publish happens asynchronously.
|
||||
// Later, you can get the result from res:
|
||||
...
|
||||
msgID, err := res.Get(ctx)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Use a callback to receive messages via subscription1.
|
||||
sub := client.Subscription("subscription1")
|
||||
err = sub.Receive(ctx, func(ctx context.Context, m *pubsub.Message) {
|
||||
fmt.Println(m.Data)
|
||||
m.Ack() // Acknowledge that we've consumed the message.
|
||||
})
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
}
|
||||
```
|
||||
|
||||
## BigQuery [![GoDoc](https://godoc.org/cloud.google.com/go/bigquery?status.svg)](https://godoc.org/cloud.google.com/go/bigquery)
|
||||
|
||||
- [About BigQuery][cloud-bigquery]
|
||||
- [API documentation][cloud-bigquery-docs]
|
||||
- [Go client documentation][cloud-bigquery-ref]
|
||||
- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/bigquery)
|
||||
|
||||
### Example Usage
|
||||
|
||||
First create a `bigquery.Client` to use throughout your application:
|
||||
[snip]:# (bq-1)
|
||||
```go
|
||||
c, err := bigquery.NewClient(ctx, "my-project-ID")
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
```
|
||||
|
||||
Then use that client to interact with the API:
|
||||
[snip]:# (bq-2)
|
||||
```go
|
||||
// Construct a query.
|
||||
q := c.Query(`
|
||||
SELECT year, SUM(number)
|
||||
FROM [bigquery-public-data:usa_names.usa_1910_2013]
|
||||
WHERE name = "William"
|
||||
GROUP BY year
|
||||
ORDER BY year
|
||||
`)
|
||||
// Execute the query.
|
||||
it, err := q.Read(ctx)
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
// Iterate through the results.
|
||||
for {
|
||||
var values []bigquery.Value
|
||||
err := it.Next(&values)
|
||||
if err == iterator.Done {
|
||||
break
|
||||
}
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
fmt.Println(values)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Stackdriver Logging [![GoDoc](https://godoc.org/cloud.google.com/go/logging?status.svg)](https://godoc.org/cloud.google.com/go/logging)
|
||||
|
||||
- [About Stackdriver Logging][cloud-logging]
|
||||
- [API documentation][cloud-logging-docs]
|
||||
- [Go client documentation][cloud-logging-ref]
|
||||
- [Complete sample programs](https://github.com/GoogleCloudPlatform/golang-samples/tree/master/logging)
|
||||
|
||||
### Example Usage
|
||||
|
||||
First create a `logging.Client` to use throughout your application:
|
||||
[snip]:# (logging-1)
|
||||
```go
|
||||
ctx := context.Background()
|
||||
client, err := logging.NewClient(ctx, "my-project")
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
```
|
||||
|
||||
Usually, you'll want to add log entries to a buffer to be periodically flushed
|
||||
(automatically and asynchronously) to the Stackdriver Logging service.
|
||||
[snip]:# (logging-2)
|
||||
```go
|
||||
logger := client.Logger("my-log")
|
||||
logger.Log(logging.Entry{Payload: "something happened!"})
|
||||
```
|
||||
|
||||
Close your client before your program exits, to flush any buffered log entries.
|
||||
[snip]:# (logging-3)
|
||||
```go
|
||||
err = client.Close()
|
||||
if err != nil {
|
||||
// TODO: Handle error.
|
||||
}
|
||||
```
|
||||
|
||||
## Cloud Spanner [![GoDoc](https://godoc.org/cloud.google.com/go/spanner?status.svg)](https://godoc.org/cloud.google.com/go/spanner)
|
||||
|
||||
- [About Cloud Spanner][cloud-spanner]
|
||||
- [API documentation][cloud-spanner-docs]
|
||||
- [Go client documentation](https://godoc.org/cloud.google.com/go/spanner)
|
||||
|
||||
### Example Usage
|
||||
|
||||
First create a `spanner.Client` to use throughout your application:
|
||||
|
||||
[snip]:# (spanner-1)
|
||||
```go
|
||||
client, err := spanner.NewClient(ctx, "projects/P/instances/I/databases/D")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
[snip]:# (spanner-2)
|
||||
```go
|
||||
// Simple Reads And Writes
|
||||
_, err = client.Apply(ctx, []*spanner.Mutation{
|
||||
spanner.Insert("Users",
|
||||
[]string{"name", "email"},
|
||||
[]interface{}{"alice", "a@example.com"})})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
row, err := client.Single().ReadRow(ctx, "Users",
|
||||
spanner.Key{"alice"}, []string{"email"})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome. Please, see the
|
||||
[CONTRIBUTING](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/CONTRIBUTING.md)
|
||||
document for details. We're using Gerrit for our code reviews. Please don't open pull
|
||||
requests against this repo, new pull requests will be automatically closed.
|
||||
|
||||
Please note that this project is released with a Contributor Code of Conduct.
|
||||
By participating in this project you agree to abide by its terms.
|
||||
See [Contributor Code of Conduct](https://github.com/GoogleCloudPlatform/google-cloud-go/blob/master/CONTRIBUTING.md#contributor-code-of-conduct)
|
||||
for more information.
|
||||
|
||||
[cloud-datastore]: https://cloud.google.com/datastore/
|
||||
[cloud-datastore-ref]: https://godoc.org/cloud.google.com/go/datastore
|
||||
[cloud-datastore-docs]: https://cloud.google.com/datastore/docs
|
||||
[cloud-datastore-activation]: https://cloud.google.com/datastore/docs/activate
|
||||
|
||||
[cloud-firestore]: https://cloud.google.com/firestore/
|
||||
[cloud-firestore-ref]: https://godoc.org/cloud.google.com/go/firestore
|
||||
[cloud-firestore-docs]: https://cloud.google.com/firestore/docs
|
||||
[cloud-firestore-activation]: https://cloud.google.com/firestore/docs/activate
|
||||
|
||||
[cloud-pubsub]: https://cloud.google.com/pubsub/
|
||||
[cloud-pubsub-ref]: https://godoc.org/cloud.google.com/go/pubsub
|
||||
[cloud-pubsub-docs]: https://cloud.google.com/pubsub/docs
|
||||
|
||||
[cloud-storage]: https://cloud.google.com/storage/
|
||||
[cloud-storage-ref]: https://godoc.org/cloud.google.com/go/storage
|
||||
[cloud-storage-docs]: https://cloud.google.com/storage/docs
|
||||
[cloud-storage-create-bucket]: https://cloud.google.com/storage/docs/cloud-console#_creatingbuckets
|
||||
|
||||
[cloud-bigtable]: https://cloud.google.com/bigtable/
|
||||
[cloud-bigtable-ref]: https://godoc.org/cloud.google.com/go/bigtable
|
||||
|
||||
[cloud-bigquery]: https://cloud.google.com/bigquery/
|
||||
[cloud-bigquery-docs]: https://cloud.google.com/bigquery/docs
|
||||
[cloud-bigquery-ref]: https://godoc.org/cloud.google.com/go/bigquery
|
||||
|
||||
[cloud-logging]: https://cloud.google.com/logging/
|
||||
[cloud-logging-docs]: https://cloud.google.com/logging/docs
|
||||
[cloud-logging-ref]: https://godoc.org/cloud.google.com/go/logging
|
||||
|
||||
[cloud-monitoring]: https://cloud.google.com/monitoring/
|
||||
[cloud-monitoring-ref]: https://godoc.org/cloud.google.com/go/monitoring/apiv3
|
||||
|
||||
[cloud-vision]: https://cloud.google.com/vision
|
||||
[cloud-vision-ref]: https://godoc.org/cloud.google.com/go/vision/apiv1
|
||||
|
||||
[cloud-language]: https://cloud.google.com/natural-language
|
||||
[cloud-language-ref]: https://godoc.org/cloud.google.com/go/language/apiv1
|
||||
|
||||
[cloud-oslogin]: https://cloud.google.com/compute/docs/oslogin/rest
|
||||
[cloud-oslogin-ref]: https://cloud.google.com/compute/docs/oslogin/rest
|
||||
|
||||
[cloud-speech]: https://cloud.google.com/speech
|
||||
[cloud-speech-ref]: https://godoc.org/cloud.google.com/go/speech/apiv1
|
||||
|
||||
[cloud-spanner]: https://cloud.google.com/spanner/
|
||||
[cloud-spanner-ref]: https://godoc.org/cloud.google.com/go/spanner
|
||||
[cloud-spanner-docs]: https://cloud.google.com/spanner/docs
|
||||
|
||||
[cloud-translation]: https://cloud.google.com/translation
|
||||
[cloud-translation-ref]: https://godoc.org/cloud.google.com/go/translation
|
||||
|
||||
[cloud-video]: https://cloud.google.com/video-intelligence/
|
||||
[cloud-video-ref]: https://godoc.org/cloud.google.com/go/videointelligence/apiv1beta1
|
||||
|
||||
[cloud-errors]: https://cloud.google.com/error-reporting/
|
||||
[cloud-errors-ref]: https://godoc.org/cloud.google.com/go/errorreporting
|
||||
|
||||
[cloud-container]: https://cloud.google.com/containers/
|
||||
[cloud-container-ref]: https://godoc.org/cloud.google.com/go/container/apiv1
|
||||
|
||||
[cloud-debugger]: https://cloud.google.com/debugger/
|
||||
[cloud-debugger-ref]: https://godoc.org/cloud.google.com/go/debugger/apiv2
|
||||
|
||||
[cloud-dlp]: https://cloud.google.com/dlp/
|
||||
[cloud-dlp-ref]: https://godoc.org/cloud.google.com/go/dlp/apiv2beta1
|
||||
|
||||
[default-creds]: https://developers.google.com/identity/protocols/application-default-credentials
|
||||
|
||||
[cloud-dataproc]: https://cloud.google.com/dataproc/
|
||||
[cloud-dataproc-docs]: https://cloud.google.com/dataproc/docs
|
||||
[cloud-dataproc-ref]: https://godoc.org/cloud.google.com/go/dataproc/apiv1
|
||||
|
||||
[cloud-iam]: https://cloud.google.com/iam/
|
||||
[cloud-iam-docs]: https://cloud.google.com/iam/docs
|
||||
[cloud-iam-ref]: https://godoc.org/cloud.google.com/go/iam
|
||||
|
||||
[cloud-kms]: https://cloud.google.com/kms/
|
||||
[cloud-kms-docs]: https://cloud.google.com/kms/docs
|
||||
[cloud-kms-ref]: https://godoc.org/cloud.google.com/go/kms/apiv1
|
||||
|
||||
[cloud-natural-language]: https://cloud.google.com/natural-language/
|
||||
[cloud-natural-language-docs]: https://cloud.google.com/natural-language/docs
|
||||
[cloud-natural-language-ref]: https://godoc.org/cloud.google.com/go/language/apiv1
|
||||
|
||||
[cloud-memorystore]: https://cloud.google.com/memorystore/
|
||||
[cloud-memorystore-docs]: https://cloud.google.com/memorystore/docs
|
||||
[cloud-memorystore-ref]: https://godoc.org/cloud.google.com/go/redis/apiv1beta1
|
||||
|
||||
[cloud-texttospeech]: https://cloud.google.com/texttospeech/
|
||||
[cloud-texttospeech-docs]: https://cloud.google.com/texttospeech/docs
|
||||
[cloud-texttospeech-ref]: https://godoc.org/cloud.google.com/go/texttospeech/apiv1
|
||||
|
||||
[cloud-trace]: https://cloud.google.com/trace/
|
||||
[cloud-trace-docs]: https://cloud.google.com/trace/docs
|
||||
[cloud-trace-ref]: https://godoc.org/cloud.google.com/go/trace/apiv1
|
||||
|
||||
[cloud-dialogflow]: https://cloud.google.com/dialogflow-enterprise/
|
||||
[cloud-dialogflow-docs]: https://cloud.google.com/dialogflow-enterprise/docs/
|
||||
[cloud-dialogflow-ref]: https://godoc.org/cloud.google.com/go/dialogflow/apiv2
|
||||
|
||||
[cloud-containeranalysis]: https://cloud.google.com/container-registry/docs/container-analysis
|
||||
[cloud-containeranalysis-docs]: https://cloud.google.com/container-analysis/api/reference/rest/
|
||||
[cloud-containeranalysis-ref]: https://godoc.org/cloud.google.com/go/devtools/containeranalysis/apiv1beta1
|
||||
|
||||
[cloud-asset]: https://cloud.google.com/security-command-center/docs/how-to-asset-inventory
|
||||
[cloud-asset-docs]: https://cloud.google.com/security-command-center/docs/how-to-asset-inventory
|
||||
[cloud-asset-ref]: https://godoc.org/cloud.google.com/go/asset/apiv1
|
||||
|
||||
[cloud-tasks]: https://cloud.google.com/tasks/
|
||||
[cloud-tasks-ref]: https://godoc.org/cloud.google.com/go/cloudtasks/apiv2beta3
|
9
vendor/cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/gosym/pclinetest.h
generated
vendored
Normal file
9
vendor/cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/gosym/pclinetest.h
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
// +build ignore
|
||||
|
||||
// Empty include file to generate z symbols
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// EOF
|
472
vendor/cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/gosym/pclntab.go
generated
vendored
Normal file
472
vendor/cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/gosym/pclntab.go
generated
vendored
Normal file
|
@ -0,0 +1,472 @@
|
|||
// Copyright 2018 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
/*
|
||||
* Line tables
|
||||
*/
|
||||
|
||||
package gosym
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A LineTable is a data structure mapping program counters to line numbers.
|
||||
//
|
||||
// In Go 1.1 and earlier, each function (represented by a Func) had its own LineTable,
|
||||
// and the line number corresponded to a numbering of all source lines in the
|
||||
// program, across all files. That absolute line number would then have to be
|
||||
// converted separately to a file name and line number within the file.
|
||||
//
|
||||
// In Go 1.2, the format of the data changed so that there is a single LineTable
|
||||
// for the entire program, shared by all Funcs, and there are no absolute line
|
||||
// numbers, just line numbers within specific files.
|
||||
//
|
||||
// For the most part, LineTable's methods should be treated as an internal
|
||||
// detail of the package; callers should use the methods on Table instead.
|
||||
type LineTable struct {
|
||||
Data []byte
|
||||
PC uint64
|
||||
Line int
|
||||
|
||||
// Go 1.2 state
|
||||
mu sync.Mutex
|
||||
go12 int // is this in Go 1.2 format? -1 no, 0 unknown, 1 yes
|
||||
binary binary.ByteOrder
|
||||
quantum uint32
|
||||
ptrsize uint32
|
||||
functab []byte
|
||||
nfunctab uint32
|
||||
filetab []byte
|
||||
nfiletab uint32
|
||||
fileMap map[string]uint32
|
||||
}
|
||||
|
||||
// NOTE(rsc): This is wrong for GOARCH=arm, which uses a quantum of 4,
|
||||
// but we have no idea whether we're using arm or not. This only
|
||||
// matters in the old (pre-Go 1.2) symbol table format, so it's not worth
|
||||
// fixing.
|
||||
const oldQuantum = 1
|
||||
|
||||
func (t *LineTable) parse(targetPC uint64, targetLine int) (b []byte, pc uint64, line int) {
|
||||
// The PC/line table can be thought of as a sequence of
|
||||
// <pc update>* <line update>
|
||||
// batches. Each update batch results in a (pc, line) pair,
|
||||
// where line applies to every PC from pc up to but not
|
||||
// including the pc of the next pair.
|
||||
//
|
||||
// Here we process each update individually, which simplifies
|
||||
// the code, but makes the corner cases more confusing.
|
||||
b, pc, line = t.Data, t.PC, t.Line
|
||||
for pc <= targetPC && line != targetLine && len(b) > 0 {
|
||||
code := b[0]
|
||||
b = b[1:]
|
||||
switch {
|
||||
case code == 0:
|
||||
if len(b) < 4 {
|
||||
b = b[0:0]
|
||||
break
|
||||
}
|
||||
val := binary.BigEndian.Uint32(b)
|
||||
b = b[4:]
|
||||
line += int(val)
|
||||
case code <= 64:
|
||||
line += int(code)
|
||||
case code <= 128:
|
||||
line -= int(code - 64)
|
||||
default:
|
||||
pc += oldQuantum * uint64(code-128)
|
||||
continue
|
||||
}
|
||||
pc += oldQuantum
|
||||
}
|
||||
return b, pc, line
|
||||
}
|
||||
|
||||
func (t *LineTable) slice(pc uint64) *LineTable {
|
||||
data, pc, line := t.parse(pc, -1)
|
||||
return &LineTable{Data: data, PC: pc, Line: line}
|
||||
}
|
||||
|
||||
// PCToLine returns the line number for the given program counter.
|
||||
// Callers should use Table's PCToLine method instead.
|
||||
func (t *LineTable) PCToLine(pc uint64) int {
|
||||
if t.isGo12() {
|
||||
return t.go12PCToLine(pc)
|
||||
}
|
||||
_, _, line := t.parse(pc, -1)
|
||||
return line
|
||||
}
|
||||
|
||||
// LineToPC returns the program counter for the given line number,
|
||||
// considering only program counters before maxpc.
|
||||
// Callers should use Table's LineToPC method instead.
|
||||
func (t *LineTable) LineToPC(line int, maxpc uint64) uint64 {
|
||||
if t.isGo12() {
|
||||
return 0
|
||||
}
|
||||
_, pc, line1 := t.parse(maxpc, line)
|
||||
if line1 != line {
|
||||
return 0
|
||||
}
|
||||
// Subtract quantum from PC to account for post-line increment
|
||||
return pc - oldQuantum
|
||||
}
|
||||
|
||||
// NewLineTable returns a new PC/line table
|
||||
// corresponding to the encoded data.
|
||||
// Text must be the start address of the
|
||||
// corresponding text segment.
|
||||
func NewLineTable(data []byte, text uint64) *LineTable {
|
||||
return &LineTable{Data: data, PC: text, Line: 0}
|
||||
}
|
||||
|
||||
// Go 1.2 symbol table format.
|
||||
// See golang.org/s/go12symtab.
|
||||
//
|
||||
// A general note about the methods here: rather than try to avoid
|
||||
// index out of bounds errors, we trust Go to detect them, and then
|
||||
// we recover from the panics and treat them as indicative of a malformed
|
||||
// or incomplete table.
|
||||
//
|
||||
// The methods called by symtab.go, which begin with "go12" prefixes,
|
||||
// are expected to have that recovery logic.
|
||||
|
||||
// isGo12 reports whether this is a Go 1.2 (or later) symbol table.
|
||||
func (t *LineTable) isGo12() bool {
|
||||
t.go12Init()
|
||||
return t.go12 == 1
|
||||
}
|
||||
|
||||
const go12magic = 0xfffffffb
|
||||
|
||||
// uintptr returns the pointer-sized value encoded at b.
|
||||
// The pointer size is dictated by the table being read.
|
||||
func (t *LineTable) uintptr(b []byte) uint64 {
|
||||
if t.ptrsize == 4 {
|
||||
return uint64(t.binary.Uint32(b))
|
||||
}
|
||||
return t.binary.Uint64(b)
|
||||
}
|
||||
|
||||
// go12init initializes the Go 1.2 metadata if t is a Go 1.2 symbol table.
|
||||
func (t *LineTable) go12Init() {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
if t.go12 != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// If we panic parsing, assume it's not a Go 1.2 symbol table.
|
||||
recover()
|
||||
}()
|
||||
|
||||
// Check header: 4-byte magic, two zeros, pc quantum, pointer size.
|
||||
t.go12 = -1 // not Go 1.2 until proven otherwise
|
||||
if len(t.Data) < 16 || t.Data[4] != 0 || t.Data[5] != 0 ||
|
||||
(t.Data[6] != 1 && t.Data[6] != 4) || // pc quantum
|
||||
(t.Data[7] != 4 && t.Data[7] != 8) { // pointer size
|
||||
return
|
||||
}
|
||||
|
||||
switch uint32(go12magic) {
|
||||
case binary.LittleEndian.Uint32(t.Data):
|
||||
t.binary = binary.LittleEndian
|
||||
case binary.BigEndian.Uint32(t.Data):
|
||||
t.binary = binary.BigEndian
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
||||
t.quantum = uint32(t.Data[6])
|
||||
t.ptrsize = uint32(t.Data[7])
|
||||
|
||||
t.nfunctab = uint32(t.uintptr(t.Data[8:]))
|
||||
t.functab = t.Data[8+t.ptrsize:]
|
||||
functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
|
||||
fileoff := t.binary.Uint32(t.functab[functabsize:])
|
||||
t.functab = t.functab[:functabsize]
|
||||
t.filetab = t.Data[fileoff:]
|
||||
t.nfiletab = t.binary.Uint32(t.filetab)
|
||||
t.filetab = t.filetab[:t.nfiletab*4]
|
||||
|
||||
t.go12 = 1 // so far so good
|
||||
}
|
||||
|
||||
// go12Funcs returns a slice of Funcs derived from the Go 1.2 pcln table.
|
||||
func (t *LineTable) go12Funcs() []Func {
|
||||
// Assume it is malformed and return nil on error.
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
|
||||
n := len(t.functab) / int(t.ptrsize) / 2
|
||||
funcs := make([]Func, n)
|
||||
for i := range funcs {
|
||||
f := &funcs[i]
|
||||
f.Entry = uint64(t.uintptr(t.functab[2*i*int(t.ptrsize):]))
|
||||
f.End = uint64(t.uintptr(t.functab[(2*i+2)*int(t.ptrsize):]))
|
||||
info := t.Data[t.uintptr(t.functab[(2*i+1)*int(t.ptrsize):]):]
|
||||
f.LineTable = t
|
||||
f.FrameSize = int(t.binary.Uint32(info[t.ptrsize+2*4:]))
|
||||
f.Sym = &Sym{
|
||||
Value: f.Entry,
|
||||
Type: 'T',
|
||||
Name: t.string(t.binary.Uint32(info[t.ptrsize:])),
|
||||
GoType: 0,
|
||||
Func: f,
|
||||
}
|
||||
}
|
||||
return funcs
|
||||
}
|
||||
|
||||
// findFunc returns the func corresponding to the given program counter.
|
||||
func (t *LineTable) findFunc(pc uint64) []byte {
|
||||
if pc < t.uintptr(t.functab) || pc >= t.uintptr(t.functab[len(t.functab)-int(t.ptrsize):]) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// The function table is a list of 2*nfunctab+1 uintptrs,
|
||||
// alternating program counters and offsets to func structures.
|
||||
f := t.functab
|
||||
nf := t.nfunctab
|
||||
for nf > 0 {
|
||||
m := nf / 2
|
||||
fm := f[2*t.ptrsize*m:]
|
||||
if t.uintptr(fm) <= pc && pc < t.uintptr(fm[2*t.ptrsize:]) {
|
||||
return t.Data[t.uintptr(fm[t.ptrsize:]):]
|
||||
} else if pc < t.uintptr(fm) {
|
||||
nf = m
|
||||
} else {
|
||||
f = f[(m+1)*2*t.ptrsize:]
|
||||
nf -= m + 1
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// readvarint reads, removes, and returns a varint from *pp.
|
||||
func (t *LineTable) readvarint(pp *[]byte) uint32 {
|
||||
var v, shift uint32
|
||||
p := *pp
|
||||
for shift = 0; ; shift += 7 {
|
||||
b := p[0]
|
||||
p = p[1:]
|
||||
v |= (uint32(b) & 0x7F) << shift
|
||||
if b&0x80 == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
*pp = p
|
||||
return v
|
||||
}
|
||||
|
||||
// string returns a Go string found at off.
|
||||
func (t *LineTable) string(off uint32) string {
|
||||
for i := off; ; i++ {
|
||||
if t.Data[i] == 0 {
|
||||
return string(t.Data[off:i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step advances to the next pc, value pair in the encoded table.
|
||||
func (t *LineTable) step(p *[]byte, pc *uint64, val *int32, first bool) bool {
|
||||
uvdelta := t.readvarint(p)
|
||||
if uvdelta == 0 && !first {
|
||||
return false
|
||||
}
|
||||
if uvdelta&1 != 0 {
|
||||
uvdelta = ^(uvdelta >> 1)
|
||||
} else {
|
||||
uvdelta >>= 1
|
||||
}
|
||||
vdelta := int32(uvdelta)
|
||||
pcdelta := t.readvarint(p) * t.quantum
|
||||
*pc += uint64(pcdelta)
|
||||
*val += vdelta
|
||||
return true
|
||||
}
|
||||
|
||||
// pcvalue reports the value associated with the target pc.
|
||||
// off is the offset to the beginning of the pc-value table,
|
||||
// and entry is the start PC for the corresponding function.
|
||||
func (t *LineTable) pcvalue(off uint32, entry, targetpc uint64) int32 {
|
||||
if off == 0 {
|
||||
return -1
|
||||
}
|
||||
p := t.Data[off:]
|
||||
|
||||
val := int32(-1)
|
||||
pc := entry
|
||||
for t.step(&p, &pc, &val, pc == entry) {
|
||||
if targetpc < pc {
|
||||
return val
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// findFileLine scans one function in the binary looking for a
|
||||
// program counter in the given file on the given line.
|
||||
// It does so by running the pc-value tables mapping program counter
|
||||
// to file number. Since most functions come from a single file, these
|
||||
// are usually short and quick to scan. If a file match is found, then the
|
||||
// code goes to the expense of looking for a simultaneous line number match.
|
||||
func (t *LineTable) findFileLine(entry uint64, filetab, linetab uint32, filenum, line int32) uint64 {
|
||||
if filetab == 0 || linetab == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
fp := t.Data[filetab:]
|
||||
fl := t.Data[linetab:]
|
||||
fileVal := int32(-1)
|
||||
filePC := entry
|
||||
lineVal := int32(-1)
|
||||
linePC := entry
|
||||
fileStartPC := filePC
|
||||
for t.step(&fp, &filePC, &fileVal, filePC == entry) {
|
||||
if fileVal == filenum && fileStartPC < filePC {
|
||||
// fileVal is in effect starting at fileStartPC up to
|
||||
// but not including filePC, and it's the file we want.
|
||||
// Run the PC table looking for a matching line number
|
||||
// or until we reach filePC.
|
||||
lineStartPC := linePC
|
||||
for linePC < filePC && t.step(&fl, &linePC, &lineVal, linePC == entry) {
|
||||
// lineVal is in effect until linePC, and lineStartPC < filePC.
|
||||
if lineVal == line {
|
||||
if fileStartPC <= lineStartPC {
|
||||
return lineStartPC
|
||||
}
|
||||
if fileStartPC < linePC {
|
||||
return fileStartPC
|
||||
}
|
||||
}
|
||||
lineStartPC = linePC
|
||||
}
|
||||
}
|
||||
fileStartPC = filePC
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// go12PCToLine maps program counter to line number for the Go 1.2 pcln table.
|
||||
func (t *LineTable) go12PCToLine(pc uint64) (line int) {
|
||||
return t.go12PCToVal(pc, t.ptrsize+5*4)
|
||||
}
|
||||
|
||||
// go12PCToSPAdj maps program counter to Stack Pointer adjustment for the Go 1.2 pcln table.
|
||||
func (t *LineTable) go12PCToSPAdj(pc uint64) (spadj int) {
|
||||
return t.go12PCToVal(pc, t.ptrsize+3*4)
|
||||
}
|
||||
|
||||
func (t *LineTable) go12PCToVal(pc uint64, fOffset uint32) (val int) {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
val = -1
|
||||
}
|
||||
}()
|
||||
|
||||
f := t.findFunc(pc)
|
||||
if f == nil {
|
||||
return -1
|
||||
}
|
||||
entry := t.uintptr(f)
|
||||
linetab := t.binary.Uint32(f[fOffset:])
|
||||
return int(t.pcvalue(linetab, entry, pc))
|
||||
}
|
||||
|
||||
// go12PCToFile maps program counter to file name for the Go 1.2 pcln table.
|
||||
func (t *LineTable) go12PCToFile(pc uint64) (file string) {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
file = ""
|
||||
}
|
||||
}()
|
||||
|
||||
f := t.findFunc(pc)
|
||||
if f == nil {
|
||||
return ""
|
||||
}
|
||||
entry := t.uintptr(f)
|
||||
filetab := t.binary.Uint32(f[t.ptrsize+4*4:])
|
||||
fno := t.pcvalue(filetab, entry, pc)
|
||||
if fno <= 0 {
|
||||
return ""
|
||||
}
|
||||
return t.string(t.binary.Uint32(t.filetab[4*fno:]))
|
||||
}
|
||||
|
||||
// go12LineToPC maps a (file, line) pair to a program counter for the Go 1.2 pcln table.
|
||||
func (t *LineTable) go12LineToPC(file string, line int) (pc uint64) {
|
||||
defer func() {
|
||||
if recover() != nil {
|
||||
pc = 0
|
||||
}
|
||||
}()
|
||||
|
||||
t.initFileMap()
|
||||
filenum := t.fileMap[file]
|
||||
if filenum == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Scan all functions.
|
||||
// If this turns out to be a bottleneck, we could build a map[int32][]int32
|
||||
// mapping file number to a list of functions with code from that file.
|
||||
for i := uint32(0); i < t.nfunctab; i++ {
|
||||
f := t.Data[t.uintptr(t.functab[2*t.ptrsize*i+t.ptrsize:]):]
|
||||
entry := t.uintptr(f)
|
||||
filetab := t.binary.Uint32(f[t.ptrsize+4*4:])
|
||||
linetab := t.binary.Uint32(f[t.ptrsize+5*4:])
|
||||
pc := t.findFileLine(entry, filetab, linetab, int32(filenum), int32(line))
|
||||
if pc != 0 {
|
||||
return pc
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// initFileMap initializes the map from file name to file number.
|
||||
func (t *LineTable) initFileMap() {
|
||||
t.mu.Lock()
|
||||
defer t.mu.Unlock()
|
||||
|
||||
if t.fileMap != nil {
|
||||
return
|
||||
}
|
||||
m := make(map[string]uint32)
|
||||
|
||||
for i := uint32(1); i < t.nfiletab; i++ {
|
||||
s := t.string(t.binary.Uint32(t.filetab[4*i:]))
|
||||
m[s] = i
|
||||
}
|
||||
t.fileMap = m
|
||||
}
|
||||
|
||||
// go12MapFiles adds to m a key for every file in the Go 1.2 LineTable.
|
||||
// Every key maps to obj. That's not a very interesting map, but it provides
|
||||
// a way for callers to obtain the list of files in the program.
|
||||
func (t *LineTable) go12MapFiles(m map[string]*Obj, obj *Obj) {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
|
||||
t.initFileMap()
|
||||
for file := range t.fileMap {
|
||||
m[file] = obj
|
||||
}
|
||||
}
|
731
vendor/cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/gosym/symtab.go
generated
vendored
Normal file
731
vendor/cloud.google.com/go/cmd/go-cloud-debug-agent/internal/debug/gosym/symtab.go
generated
vendored
Normal file
|
@ -0,0 +1,731 @@
|
|||
// Copyright 2018 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package gosym implements access to the Go symbol
|
||||
// and line number tables embedded in Go binaries generated
|
||||
// by the gc compilers.
|
||||
package gosym
|
||||
|
||||
// The table format is a variant of the format used in Plan 9's a.out
|
||||
// format, documented at http://plan9.bell-labs.com/magic/man2html/6/a.out.
|
||||
// The best reference for the differences between the Plan 9 format
|
||||
// and the Go format is the runtime source, specifically ../../runtime/symtab.c.
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/*
|
||||
* Symbols
|
||||
*/
|
||||
|
||||
// A Sym represents a single symbol table entry.
|
||||
type Sym struct {
|
||||
Value uint64
|
||||
Type byte
|
||||
Name string
|
||||
GoType uint64
|
||||
// If this symbol if a function symbol, the corresponding Func
|
||||
Func *Func
|
||||
}
|
||||
|
||||
// Static reports whether this symbol is static (not visible outside its file).
|
||||
func (s *Sym) Static() bool { return s.Type >= 'a' }
|
||||
|
||||
// PackageName returns the package part of the symbol name,
|
||||
// or the empty string if there is none.
|
||||
func (s *Sym) PackageName() string {
|
||||
if i := strings.Index(s.Name, "."); i != -1 {
|
||||
return s.Name[0:i]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// ReceiverName returns the receiver type name of this symbol,
|
||||
// or the empty string if there is none.
|
||||
func (s *Sym) ReceiverName() string {
|
||||
l := strings.Index(s.Name, ".")
|
||||
r := strings.LastIndex(s.Name, ".")
|
||||
if l == -1 || r == -1 || l == r {
|
||||
return ""
|
||||
}
|
||||
return s.Name[l+1 : r]
|
||||
}
|
||||
|
||||
// BaseName returns the symbol name without the package or receiver name.
|
||||
func (s *Sym) BaseName() string {
|
||||
if i := strings.LastIndex(s.Name, "."); i != -1 {
|
||||
return s.Name[i+1:]
|
||||
}
|
||||
return s.Name
|
||||
}
|
||||
|
||||
// A Func collects information about a single function.
|
||||
type Func struct {
|
||||
Entry uint64
|
||||
*Sym
|
||||
End uint64
|
||||
Params []*Sym
|
||||
Locals []*Sym
|
||||
FrameSize int
|
||||
LineTable *LineTable
|
||||
Obj *Obj
|
||||
}
|
||||
|
||||
// An Obj represents a collection of functions in a symbol table.
|
||||
//
|
||||
// The exact method of division of a binary into separate Objs is an internal detail
|
||||
// of the symbol table format.
|
||||
//
|
||||
// In early versions of Go each source file became a different Obj.
|
||||
//
|
||||
// In Go 1 and Go 1.1, each package produced one Obj for all Go sources
|
||||
// and one Obj per C source file.
|
||||
//
|
||||
// In Go 1.2, there is a single Obj for the entire program.
|
||||
type Obj struct {
|
||||
// Funcs is a list of functions in the Obj.
|
||||
Funcs []Func
|
||||
|
||||
// In Go 1.1 and earlier, Paths is a list of symbols corresponding
|
||||
// to the source file names that produced the Obj.
|
||||
// In Go 1.2, Paths is nil.
|
||||
// Use the keys of Table.Files to obtain a list of source files.
|
||||
Paths []Sym // meta
|
||||
}
|
||||
|
||||
/*
|
||||
* Symbol tables
|
||||
*/
|
||||
|
||||
// Table represents a Go symbol table. It stores all of the
|
||||
// symbols decoded from the program and provides methods to translate
|
||||
// between symbols, names, and addresses.
|
||||
type Table struct {
|
||||
Syms []Sym
|
||||
Funcs []Func
|
||||
Files map[string]*Obj // nil for Go 1.2 and later binaries
|
||||
Objs []Obj // nil for Go 1.2 and later binaries
|
||||
|
||||
go12line *LineTable // Go 1.2 line number table
|
||||
}
|
||||
|
||||
type sym struct {
|
||||
value uint64
|
||||
gotype uint64
|
||||
typ byte
|
||||
name []byte
|
||||
}
|
||||
|
||||
var (
|
||||
littleEndianSymtab = []byte{0xFD, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00}
|
||||
bigEndianSymtab = []byte{0xFF, 0xFF, 0xFF, 0xFD, 0x00, 0x00, 0x00}
|
||||
oldLittleEndianSymtab = []byte{0xFE, 0xFF, 0xFF, 0xFF, 0x00, 0x00}
|
||||
)
|
||||
|
||||
func walksymtab(data []byte, fn func(sym) error) error {
|
||||
if len(data) == 0 { // missing symtab is okay
|
||||
return nil
|
||||
}
|
||||
var order binary.ByteOrder = binary.BigEndian
|
||||
newTable := false
|
||||
switch {
|
||||
case bytes.HasPrefix(data, oldLittleEndianSymtab):
|
||||
// Same as Go 1.0, but little endian.
|
||||
// Format was used during interim development between Go 1.0 and Go 1.1.
|
||||
// Should not be widespread, but easy to support.
|
||||
data = data[6:]
|
||||
order = binary.LittleEndian
|
||||
case bytes.HasPrefix(data, bigEndianSymtab):
|
||||
newTable = true
|
||||
case bytes.HasPrefix(data, littleEndianSymtab):
|
||||
newTable = true
|
||||
order = binary.LittleEndian
|
||||
}
|
||||
var ptrsz int
|
||||
if newTable {
|
||||
if len(data) < 8 {
|
||||
return &DecodingError{len(data), "unexpected EOF", nil}
|
||||
}
|
||||
ptrsz = int(data[7])
|
||||
if ptrsz != 4 && ptrsz != 8 {
|
||||
return &DecodingError{7, "invalid pointer size", ptrsz}
|
||||
}
|
||||
data = data[8:]
|
||||
}
|
||||
var s sym
|
||||
p := data
|
||||
for len(p) >= 4 {
|
||||
var typ byte
|
||||
if newTable {
|
||||
// Symbol type, value, Go type.
|
||||
typ = p[0] & 0x3F
|
||||
wideValue := p[0]&0x40 != 0
|
||||
goType := p[0]&0x80 != 0
|
||||
if typ < 26 {
|
||||
typ += 'A'
|
||||
} else {
|
||||
typ += 'a' - 26
|
||||
}
|
||||
s.typ = typ
|
||||
p = p[1:]
|
||||
if wideValue {
|
||||
if len(p) < ptrsz {
|
||||
return &DecodingError{len(data), "unexpected EOF", nil}
|
||||
}
|
||||
// fixed-width value
|
||||
if ptrsz == 8 {
|
||||
s.value = order.Uint64(p[0:8])
|
||||
p = p[8:]
|
||||
} else {
|
||||
s.value = uint64(order.Uint32(p[0:4]))
|
||||
p = p[4:]
|
||||
}
|
||||
} else {
|
||||
// varint value
|
||||
s.value = 0
|
||||
shift := uint(0)
|
||||
for len(p) > 0 && p[0]&0x80 != 0 {
|
||||
s.value |= uint64(p[0]&0x7F) << shift
|
||||
shift += 7
|
||||
p = p[1:]
|
||||
}
|
||||
if len(p) == 0 {
|
||||
return &DecodingError{len(data), "unexpected EOF", nil}
|
||||
}
|
||||
s.value |= uint64(p[0]) << shift
|
||||
p = p[1:]
|
||||
}
|
||||
if goType {
|
||||
if len(p) < ptrsz {
|
||||
return &DecodingError{len(data), "unexpected EOF", nil}
|
||||
}
|
||||
// fixed-width go type
|
||||
if ptrsz == 8 {
|
||||
s.gotype = order.Uint64(p[0:8])
|
||||
p = p[8:]
|
||||
} else {
|
||||
s.gotype = uint64(order.Uint32(p[0:4]))
|
||||
p = p[4:]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Value, symbol type.
|
||||
s.value = uint64(order.Uint32(p[0:4]))
|
||||
if len(p) < 5 {
|
||||
return &DecodingError{len(data), "unexpected EOF", nil}
|
||||
}
|
||||
typ = p[4]
|
||||
if typ&0x80 == 0 {
|
||||
return &DecodingError{len(data) - len(p) + 4, "bad symbol type", typ}
|
||||
}
|
||||
typ &^= 0x80
|
||||
s.typ = typ
|
||||
p = p[5:]
|
||||
}
|
||||
|
||||
// Name.
|
||||
var i int
|
||||
var nnul int
|
||||
for i = 0; i < len(p); i++ {
|
||||
if p[i] == 0 {
|
||||
nnul = 1
|
||||
break
|
||||
}
|
||||
}
|
||||
switch typ {
|
||||
case 'z', 'Z':
|
||||
p = p[i+nnul:]
|
||||
for i = 0; i+2 <= len(p); i += 2 {
|
||||
if p[i] == 0 && p[i+1] == 0 {
|
||||
nnul = 2
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(p) < i+nnul {
|
||||
return &DecodingError{len(data), "unexpected EOF", nil}
|
||||
}
|
||||
s.name = p[0:i]
|
||||
i += nnul
|
||||
p = p[i:]
|
||||
|
||||
if !newTable {
|
||||
if len(p) < 4 {
|
||||
return &DecodingError{len(data), "unexpected EOF", nil}
|
||||
}
|
||||
// Go type.
|
||||
s.gotype = uint64(order.Uint32(p[:4]))
|
||||
p = p[4:]
|
||||
}
|
||||
fn(s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewTable decodes the Go symbol table in data,
|
||||
// returning an in-memory representation.
|
||||
func NewTable(symtab []byte, pcln *LineTable) (*Table, error) {
|
||||
var n int
|
||||
err := walksymtab(symtab, func(s sym) error {
|
||||
n++
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var t Table
|
||||
if pcln.isGo12() {
|
||||
t.go12line = pcln
|
||||
}
|
||||
fname := make(map[uint16]string)
|
||||
t.Syms = make([]Sym, 0, n)
|
||||
nf := 0
|
||||
nz := 0
|
||||
lasttyp := uint8(0)
|
||||
err = walksymtab(symtab, func(s sym) error {
|
||||
n := len(t.Syms)
|
||||
t.Syms = t.Syms[0 : n+1]
|
||||
ts := &t.Syms[n]
|
||||
ts.Type = s.typ
|
||||
ts.Value = uint64(s.value)
|
||||
ts.GoType = uint64(s.gotype)
|
||||
switch s.typ {
|
||||
default:
|
||||
// rewrite name to use . instead of · (c2 b7)
|
||||
w := 0
|
||||
b := s.name
|
||||
for i := 0; i < len(b); i++ {
|
||||
if b[i] == 0xc2 && i+1 < len(b) && b[i+1] == 0xb7 {
|
||||
i++
|
||||
b[i] = '.'
|
||||
}
|
||||
b[w] = b[i]
|
||||
w++
|
||||
}
|
||||
ts.Name = string(s.name[0:w])
|
||||
case 'z', 'Z':
|
||||
if lasttyp != 'z' && lasttyp != 'Z' {
|
||||
nz++
|
||||
}
|
||||
for i := 0; i < len(s.name); i += 2 {
|
||||
eltIdx := binary.BigEndian.Uint16(s.name[i : i+2])
|
||||
elt, ok := fname[eltIdx]
|
||||
if !ok {
|
||||
return &DecodingError{-1, "bad filename code", eltIdx}
|
||||
}
|
||||
if n := len(ts.Name); n > 0 && ts.Name[n-1] != '/' {
|
||||
ts.Name += "/"
|
||||
}
|
||||
ts.Name += elt
|
||||
}
|
||||
}
|
||||
switch s.typ {
|
||||
case 'T', 't', 'L', 'l':
|
||||
nf++
|
||||
case 'f':
|
||||
fname[uint16(s.value)] = ts.Name
|
||||
}
|
||||
lasttyp = s.typ
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t.Funcs = make([]Func, 0, nf)
|
||||
t.Files = make(map[string]*Obj)
|
||||
|
||||
var obj *Obj
|
||||
if t.go12line != nil {
|
||||
// Put all functions into one Obj.
|
||||
t.Objs = make([]Obj, 1)
|
||||
obj = &t.Objs[0]
|
||||
t.go12line.go12MapFiles(t.Files, obj)
|
||||
} else {
|
||||
t.Objs = make([]Obj, 0, nz)
|
||||
}
|
||||
|
||||
// Count text symbols and attach frame sizes, parameters, and
|
||||
// locals to them. Also, find object file boundaries.
|
||||
lastf := 0
|
||||
for i := 0; i < len(t.Syms); i++ {
|
||||
sym := &t.Syms[i]
|
||||
switch sym.Type {
|
||||
case 'Z', 'z': // path symbol
|
||||
if t.go12line != nil {
|
||||
// Go 1.2 binaries have the file information elsewhere. Ignore.
|
||||
break
|
||||
}
|
||||
// Finish the current object
|
||||
if obj != nil {
|
||||
obj.Funcs = t.Funcs[lastf:]
|
||||
}
|
||||
lastf = len(t.Funcs)
|
||||
|
||||
// Start new object
|
||||
n := len(t.Objs)
|
||||
t.Objs = t.Objs[0 : n+1]
|
||||
obj = &t.Objs[n]
|
||||
|
||||
// Count & copy path symbols
|
||||
var end int
|
||||
for end = i + 1; end < len(t.Syms); end++ {
|
||||
if c := t.Syms[end].Type; c != 'Z' && c != 'z' {
|
||||
break
|
||||
}
|
||||
}
|
||||
obj.Paths = t.Syms[i:end]
|
||||
i = end - 1 // loop will i++
|
||||
|
||||
// Record file names
|
||||
depth := 0
|
||||
for j := range obj.Paths {
|
||||
s := &obj.Paths[j]
|
||||
if s.Name == "" {
|
||||
depth--
|
||||
} else {
|
||||
if depth == 0 {
|
||||
t.Files[s.Name] = obj
|
||||
}
|
||||
depth++
|
||||
}
|
||||
}
|
||||
|
||||
case 'T', 't', 'L', 'l': // text symbol
|
||||
if n := len(t.Funcs); n > 0 {
|
||||
t.Funcs[n-1].End = sym.Value
|
||||
}
|
||||
if sym.Name == "etext" {
|
||||
continue
|
||||
}
|
||||
|
||||
// Count parameter and local (auto) syms
|
||||
var np, na int
|
||||
var end int
|
||||
countloop:
|
||||
for end = i + 1; end < len(t.Syms); end++ {
|
||||
switch t.Syms[end].Type {
|
||||
case 'T', 't', 'L', 'l', 'Z', 'z':
|
||||
break countloop
|
||||
case 'p':
|
||||
np++
|
||||
case 'a':
|
||||
na++
|
||||
}
|
||||
}
|
||||
|
||||
// Fill in the function symbol
|
||||
n := len(t.Funcs)
|
||||
t.Funcs = t.Funcs[0 : n+1]
|
||||
fn := &t.Funcs[n]
|
||||
sym.Func = fn
|
||||
fn.Params = make([]*Sym, 0, np)
|
||||
fn.Locals = make([]*Sym, 0, na)
|
||||
fn.Sym = sym
|
||||
fn.Entry = sym.Value
|
||||
fn.Obj = obj
|
||||
if t.go12line != nil {
|
||||
// All functions share the same line table.
|
||||
// It knows how to narrow down to a specific
|
||||
// function quickly.
|
||||
fn.LineTable = t.go12line
|
||||
} else if pcln != nil {
|
||||
fn.LineTable = pcln.slice(fn.Entry)
|
||||
pcln = fn.LineTable
|
||||
}
|
||||
for j := i; j < end; j++ {
|
||||
s := &t.Syms[j]
|
||||
switch s.Type {
|
||||
case 'm':
|
||||
fn.FrameSize = int(s.Value)
|
||||
case 'p':
|
||||
n := len(fn.Params)
|
||||
fn.Params = fn.Params[0 : n+1]
|
||||
fn.Params[n] = s
|
||||
case 'a':
|
||||
n := len(fn.Locals)
|
||||
fn.Locals = fn.Locals[0 : n+1]
|
||||
fn.Locals[n] = s
|
||||
}
|
||||
}
|
||||
i = end - 1 // loop will i++
|
||||
}
|
||||
}
|
||||
|
||||
if t.go12line != nil && nf == 0 {
|
||||
t.Funcs = t.go12line.go12Funcs()
|
||||
}
|
||||
if obj != nil {
|
||||
obj.Funcs = t.Funcs[lastf:]
|
||||
}
|
||||
return &t, nil
|
||||
}
|
||||
|
||||
// PCToFunc returns the function containing the program counter pc,
|
||||
// or nil if there is no such function.
|
||||
func (t *Table) PCToFunc(pc uint64) *Func {
|
||||
funcs := t.Funcs
|
||||
for len(funcs) > 0 {
|
||||
m := len(funcs) / 2
|
||||
fn := &funcs[m]
|
||||
switch {
|
||||
case pc < fn.Entry:
|
||||
funcs = funcs[0:m]
|
||||
case fn.Entry <= pc && pc < fn.End:
|
||||
return fn
|
||||
default:
|
||||
funcs = funcs[m+1:]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PCToLine looks up line number information for a program counter.
|
||||
// If there is no information, it returns fn == nil.
|
||||
func (t *Table) PCToLine(pc uint64) (file string, line int, fn *Func) {
|
||||
if fn = t.PCToFunc(pc); fn == nil {
|
||||
return
|
||||
}
|
||||
if t.go12line != nil {
|
||||
file = t.go12line.go12PCToFile(pc)
|
||||
line = t.go12line.go12PCToLine(pc)
|
||||
} else {
|
||||
file, line = fn.Obj.lineFromAline(fn.LineTable.PCToLine(pc))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PCToSPAdj returns the stack pointer adjustment for a program counter.
|
||||
func (t *Table) PCToSPAdj(pc uint64) (spadj int) {
|
||||
if fn := t.PCToFunc(pc); fn == nil {
|
||||
return 0
|
||||
}
|
||||
if t.go12line != nil {
|
||||
return t.go12line.go12PCToSPAdj(pc)
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// LineToPC looks up the first program counter on the given line in
|
||||
// the named file. It returns UnknownPathError or UnknownLineError if
|
||||
// there is an error looking up this line.
|
||||
func (t *Table) LineToPC(file string, line int) (pc uint64, fn *Func, err error) {
|
||||
obj, ok := t.Files[file]
|
||||
if !ok {
|
||||
return 0, nil, UnknownFileError(file)
|
||||
}
|
||||
|
||||
if t.go12line != nil {
|
||||
pc := t.go12line.go12LineToPC(file, line)
|
||||
if pc == 0 {
|
||||
return 0, nil, &UnknownLineError{file, line}
|
||||
}
|
||||
return pc, t.PCToFunc(pc), nil
|
||||
}
|
||||
|
||||
abs, err := obj.alineFromLine(file, line)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for i := range obj.Funcs {
|
||||
f := &obj.Funcs[i]
|
||||
pc := f.LineTable.LineToPC(abs, f.End)
|
||||
if pc != 0 {
|
||||
return pc, f, nil
|
||||
}
|
||||
}
|
||||
return 0, nil, &UnknownLineError{file, line}
|
||||
}
|
||||
|
||||
// LookupSym returns the text, data, or bss symbol with the given name,
|
||||
// or nil if no such symbol is found.
|
||||
func (t *Table) LookupSym(name string) *Sym {
|
||||
// TODO(austin) Maybe make a map
|
||||
for i := range t.Syms {
|
||||
s := &t.Syms[i]
|
||||
switch s.Type {
|
||||
case 'T', 't', 'L', 'l', 'D', 'd', 'B', 'b':
|
||||
if s.Name == name {
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// LookupFunc returns the text, data, or bss symbol with the given name,
|
||||
// or nil if no such symbol is found.
|
||||
func (t *Table) LookupFunc(name string) *Func {
|
||||
for i := range t.Funcs {
|
||||
f := &t.Funcs[i]
|
||||
if f.Sym.Name == name {
|
||||
return f
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// SymByAddr returns the text, data, or bss symbol starting at the given address.
|
||||
func (t *Table) SymByAddr(addr uint64) *Sym {
|
||||
for i := range t.Syms {
|
||||
s := &t.Syms[i]
|
||||
switch s.Type {
|
||||
case 'T', 't', 'L', 'l', 'D', 'd', 'B', 'b':
|
||||
if s.Value == addr {
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
* Object files
|
||||
*/
|
||||
|
||||
// This is legacy code for Go 1.1 and earlier, which used the
|
||||
// Plan 9 format for pc-line tables. This code was never quite
|
||||
// correct. It's probably very close, and it's usually correct, but
|
||||
// we never quite found all the corner cases.
|
||||
//
|
||||
// Go 1.2 and later use a simpler format, documented at golang.org/s/go12symtab.
|
||||
|
||||
func (o *Obj) lineFromAline(aline int) (string, int) {
|
||||
type stackEnt struct {
|
||||
path string
|
||||
start int
|
||||
offset int
|
||||
prev *stackEnt
|
||||
}
|
||||
|
||||
noPath := &stackEnt{"", 0, 0, nil}
|
||||
tos := noPath
|
||||
|
||||
pathloop:
|
||||
for _, s := range o.Paths {
|
||||
val := int(s.Value)
|
||||
switch {
|
||||
case val > aline:
|
||||
break pathloop
|
||||
|
||||
case val == 1:
|
||||
// Start a new stack
|
||||
tos = &stackEnt{s.Name, val, 0, noPath}
|
||||
|
||||
case s.Name == "":
|
||||
// Pop
|
||||
if tos == noPath {
|
||||
return "<malformed symbol table>", 0
|
||||
}
|
||||
tos.prev.offset += val - tos.start
|
||||
tos = tos.prev
|
||||
|
||||
default:
|
||||
// Push
|
||||
tos = &stackEnt{s.Name, val, 0, tos}
|
||||
}
|
||||
}
|
||||
|
||||
if tos == noPath {
|
||||
return "", 0
|
||||
}
|
||||
return tos.path, aline - tos.start - tos.offset + 1
|
||||
}
|
||||
|
||||
func (o *Obj) alineFromLine(path string, line int) (int, error) {
|
||||
if line < 1 {
|
||||
return 0, &UnknownLineError{path, line}
|
||||
}
|
||||
|
||||
for i, s := range o.Paths {
|
||||
// Find this path
|
||||
if s.Name != path {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find this line at this stack level
|
||||
depth := 0
|
||||
var incstart int
|
||||
line += int(s.Value)
|
||||
pathloop:
|
||||
for _, s := range o.Paths[i:] {
|
||||
val := int(s.Value)
|
||||
switch {
|
||||
case depth == 1 && val >= line:
|
||||
return line - 1, nil
|
||||
|
||||
case s.Name == "":
|
||||
depth--
|
||||
if depth == 0 {
|
||||
break pathloop
|
||||
} else if depth == 1 {
|
||||
line += val - incstart
|
||||
}
|
||||
|
||||
default:
|
||||
if depth == 1 {
|
||||
incstart = val
|
||||
}
|
||||
depth++
|
||||
}
|
||||
}
|
||||
return 0, &UnknownLineError{path, line}
|
||||
}
|
||||
return 0, UnknownFileError(path)
|
||||
}
|
||||
|
||||
/*
|
||||
* Errors
|
||||
*/
|
||||
|
||||
// UnknownFileError represents a failure to find the specific file in
|
||||
// the symbol table.
|
||||
type UnknownFileError string
|
||||
|
||||
func (e UnknownFileError) Error() string { return "unknown file: " + string(e) }
|
||||
|
||||
// UnknownLineError represents a failure to map a line to a program
|
||||
// counter, either because the line is beyond the bounds of the file
|
||||
// or because there is no code on the given line.
|
||||
type UnknownLineError struct {
|
||||
File string
|
||||
Line int
|
||||
}
|
||||
|
||||
func (e *UnknownLineError) Error() string {
|
||||
return "no code at " + e.File + ":" + strconv.Itoa(e.Line)
|
||||
}
|
||||
|
||||
// DecodingError represents an error during the decoding of
|
||||
// the symbol table.
|
||||
type DecodingError struct {
|
||||
off int
|
||||
msg string
|
||||
val interface{}
|
||||
}
|
||||
|
||||
func (e *DecodingError) Error() string {
|
||||
msg := e.msg
|
||||
if e.val != nil {
|
||||
msg += fmt.Sprintf(" '%v'", e.val)
|
||||
}
|
||||
msg += fmt.Sprintf(" at byte %#x", e.off)
|
||||
return msg
|
||||
}
|
|
@ -0,0 +1,501 @@
|
|||
// Copyright 2014 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Package metadata provides access to Google Compute Engine (GCE)
|
||||
// metadata and API service accounts.
|
||||
//
|
||||
// This package is a wrapper around the GCE metadata service,
|
||||
// as documented at https://developers.google.com/compute/docs/metadata.
|
||||
package metadata // import "cloud.google.com/go/compute/metadata"
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// metadataIP is the documented metadata server IP address.
|
||||
metadataIP = "169.254.169.254"
|
||||
|
||||
// metadataHostEnv is the environment variable specifying the
|
||||
// GCE metadata hostname. If empty, the default value of
|
||||
// metadataIP ("169.254.169.254") is used instead.
|
||||
// This is variable name is not defined by any spec, as far as
|
||||
// I know; it was made up for the Go package.
|
||||
metadataHostEnv = "GCE_METADATA_HOST"
|
||||
|
||||
userAgent = "gcloud-golang/0.1"
|
||||
)
|
||||
|
||||
type cachedValue struct {
|
||||
k string
|
||||
trim bool
|
||||
mu sync.Mutex
|
||||
v string
|
||||
}
|
||||
|
||||
var (
|
||||
projID = &cachedValue{k: "project/project-id", trim: true}
|
||||
projNum = &cachedValue{k: "project/numeric-project-id", trim: true}
|
||||
instID = &cachedValue{k: "instance/id", trim: true}
|
||||
)
|
||||
|
||||
var (
|
||||
defaultClient = &Client{hc: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
ResponseHeaderTimeout: 2 * time.Second,
|
||||
},
|
||||
}}
|
||||
subscribeClient = &Client{hc: &http.Client{
|
||||
Transport: &http.Transport{
|
||||
Dial: (&net.Dialer{
|
||||
Timeout: 2 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
}).Dial,
|
||||
},
|
||||
}}
|
||||
)
|
||||
|
||||
// NotDefinedError is returned when requested metadata is not defined.
|
||||
//
|
||||
// The underlying string is the suffix after "/computeMetadata/v1/".
|
||||
//
|
||||
// This error is not returned if the value is defined to be the empty
|
||||
// string.
|
||||
type NotDefinedError string
|
||||
|
||||
func (suffix NotDefinedError) Error() string {
|
||||
return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
|
||||
}
|
||||
|
||||
func (c *cachedValue) get(cl *Client) (v string, err error) {
|
||||
defer c.mu.Unlock()
|
||||
c.mu.Lock()
|
||||
if c.v != "" {
|
||||
return c.v, nil
|
||||
}
|
||||
if c.trim {
|
||||
v, err = cl.getTrimmed(c.k)
|
||||
} else {
|
||||
v, err = cl.Get(c.k)
|
||||
}
|
||||
if err == nil {
|
||||
c.v = v
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
onGCEOnce sync.Once
|
||||
onGCE bool
|
||||
)
|
||||
|
||||
// OnGCE reports whether this process is running on Google Compute Engine.
|
||||
func OnGCE() bool {
|
||||
onGCEOnce.Do(initOnGCE)
|
||||
return onGCE
|
||||
}
|
||||
|
||||
func initOnGCE() {
|
||||
onGCE = testOnGCE()
|
||||
}
|
||||
|
||||
func testOnGCE() bool {
|
||||
// The user explicitly said they're on GCE, so trust them.
|
||||
if os.Getenv(metadataHostEnv) != "" {
|
||||
return true
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
resc := make(chan bool, 2)
|
||||
|
||||
// Try two strategies in parallel.
|
||||
// See https://github.com/GoogleCloudPlatform/google-cloud-go/issues/194
|
||||
go func() {
|
||||
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
res, err := defaultClient.hc.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
resc <- false
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
resc <- res.Header.Get("Metadata-Flavor") == "Google"
|
||||
}()
|
||||
|
||||
go func() {
|
||||
addrs, err := net.LookupHost("metadata.google.internal")
|
||||
if err != nil || len(addrs) == 0 {
|
||||
resc <- false
|
||||
return
|
||||
}
|
||||
resc <- strsContains(addrs, metadataIP)
|
||||
}()
|
||||
|
||||
tryHarder := systemInfoSuggestsGCE()
|
||||
if tryHarder {
|
||||
res := <-resc
|
||||
if res {
|
||||
// The first strategy succeeded, so let's use it.
|
||||
return true
|
||||
}
|
||||
// Wait for either the DNS or metadata server probe to
|
||||
// contradict the other one and say we are running on
|
||||
// GCE. Give it a lot of time to do so, since the system
|
||||
// info already suggests we're running on a GCE BIOS.
|
||||
timer := time.NewTimer(5 * time.Second)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case res = <-resc:
|
||||
return res
|
||||
case <-timer.C:
|
||||
// Too slow. Who knows what this system is.
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// There's no hint from the system info that we're running on
|
||||
// GCE, so use the first probe's result as truth, whether it's
|
||||
// true or false. The goal here is to optimize for speed for
|
||||
// users who are NOT running on GCE. We can't assume that
|
||||
// either a DNS lookup or an HTTP request to a blackholed IP
|
||||
// address is fast. Worst case this should return when the
|
||||
// metaClient's Transport.ResponseHeaderTimeout or
|
||||
// Transport.Dial.Timeout fires (in two seconds).
|
||||
return <-resc
|
||||
}
|
||||
|
||||
// systemInfoSuggestsGCE reports whether the local system (without
|
||||
// doing network requests) suggests that we're running on GCE. If this
|
||||
// returns true, testOnGCE tries a bit harder to reach its metadata
|
||||
// server.
|
||||
func systemInfoSuggestsGCE() bool {
|
||||
if runtime.GOOS != "linux" {
|
||||
// We don't have any non-Linux clues available, at least yet.
|
||||
return false
|
||||
}
|
||||
slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
|
||||
name := strings.TrimSpace(string(slurp))
|
||||
return name == "Google" || name == "Google Compute Engine"
|
||||
}
|
||||
|
||||
// Subscribe calls Client.Subscribe on a client designed for subscribing (one with no
|
||||
// ResponseHeaderTimeout).
|
||||
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
||||
return subscribeClient.Subscribe(suffix, fn)
|
||||
}
|
||||
|
||||
// Get calls Client.Get on the default client.
|
||||
func Get(suffix string) (string, error) { return defaultClient.Get(suffix) }
|
||||
|
||||
// ProjectID returns the current instance's project ID string.
|
||||
func ProjectID() (string, error) { return defaultClient.ProjectID() }
|
||||
|
||||
// NumericProjectID returns the current instance's numeric project ID.
|
||||
func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() }
|
||||
|
||||
// InternalIP returns the instance's primary internal IP address.
|
||||
func InternalIP() (string, error) { return defaultClient.InternalIP() }
|
||||
|
||||
// ExternalIP returns the instance's primary external (public) IP address.
|
||||
func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
|
||||
|
||||
// Hostname returns the instance's hostname. This will be of the form
|
||||
// "<instanceID>.c.<projID>.internal".
|
||||
func Hostname() (string, error) { return defaultClient.Hostname() }
|
||||
|
||||
// InstanceTags returns the list of user-defined instance tags,
|
||||
// assigned when initially creating a GCE instance.
|
||||
func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() }
|
||||
|
||||
// InstanceID returns the current VM's numeric instance ID.
|
||||
func InstanceID() (string, error) { return defaultClient.InstanceID() }
|
||||
|
||||
// InstanceName returns the current VM's instance ID string.
|
||||
func InstanceName() (string, error) { return defaultClient.InstanceName() }
|
||||
|
||||
// Zone returns the current VM's zone, such as "us-central1-b".
|
||||
func Zone() (string, error) { return defaultClient.Zone() }
|
||||
|
||||
// InstanceAttributes calls Client.InstanceAttributes on the default client.
|
||||
func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() }
|
||||
|
||||
// ProjectAttributes calls Client.ProjectAttributes on the default client.
|
||||
func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() }
|
||||
|
||||
// InstanceAttributeValue calls Client.InstanceAttributeValue on the default client.
|
||||
func InstanceAttributeValue(attr string) (string, error) {
|
||||
return defaultClient.InstanceAttributeValue(attr)
|
||||
}
|
||||
|
||||
// ProjectAttributeValue calls Client.ProjectAttributeValue on the default client.
|
||||
func ProjectAttributeValue(attr string) (string, error) {
|
||||
return defaultClient.ProjectAttributeValue(attr)
|
||||
}
|
||||
|
||||
// Scopes calls Client.Scopes on the default client.
|
||||
func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) }
|
||||
|
||||
func strsContains(ss []string, s string) bool {
|
||||
for _, v := range ss {
|
||||
if v == s {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// A Client provides metadata.
|
||||
type Client struct {
|
||||
hc *http.Client
|
||||
}
|
||||
|
||||
// NewClient returns a Client that can be used to fetch metadata. All HTTP requests
|
||||
// will use the given http.Client instead of the default client.
|
||||
func NewClient(c *http.Client) *Client {
|
||||
return &Client{hc: c}
|
||||
}
|
||||
|
||||
// getETag returns a value from the metadata service as well as the associated ETag.
|
||||
// This func is otherwise equivalent to Get.
|
||||
func (c *Client) getETag(suffix string) (value, etag string, err error) {
|
||||
// Using a fixed IP makes it very difficult to spoof the metadata service in
|
||||
// a container, which is an important use-case for local testing of cloud
|
||||
// deployments. To enable spoofing of the metadata service, the environment
|
||||
// variable GCE_METADATA_HOST is first inspected to decide where metadata
|
||||
// requests shall go.
|
||||
host := os.Getenv(metadataHostEnv)
|
||||
if host == "" {
|
||||
// Using 169.254.169.254 instead of "metadata" here because Go
|
||||
// binaries built with the "netgo" tag and without cgo won't
|
||||
// know the search suffix for "metadata" is
|
||||
// ".google.internal", and this IP address is documented as
|
||||
// being stable anyway.
|
||||
host = metadataIP
|
||||
}
|
||||
url := "http://" + host + "/computeMetadata/v1/" + suffix
|
||||
req, _ := http.NewRequest("GET", url, nil)
|
||||
req.Header.Set("Metadata-Flavor", "Google")
|
||||
req.Header.Set("User-Agent", userAgent)
|
||||
res, err := c.hc.Do(req)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
if res.StatusCode == http.StatusNotFound {
|
||||
return "", "", NotDefinedError(suffix)
|
||||
}
|
||||
if res.StatusCode != 200 {
|
||||
return "", "", fmt.Errorf("status code %d trying to fetch %s", res.StatusCode, url)
|
||||
}
|
||||
all, err := ioutil.ReadAll(res.Body)
|
||||
if err != nil {
|
||||
return "", "", err
|
||||
}
|
||||
return string(all), res.Header.Get("Etag"), nil
|
||||
}
|
||||
|
||||
// Get returns a value from the metadata service.
|
||||
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
||||
//
|
||||
// If the GCE_METADATA_HOST environment variable is not defined, a default of
|
||||
// 169.254.169.254 will be used instead.
|
||||
//
|
||||
// If the requested metadata is not defined, the returned error will
|
||||
// be of type NotDefinedError.
|
||||
func (c *Client) Get(suffix string) (string, error) {
|
||||
val, _, err := c.getETag(suffix)
|
||||
return val, err
|
||||
}
|
||||
|
||||
func (c *Client) getTrimmed(suffix string) (s string, err error) {
|
||||
s, err = c.Get(suffix)
|
||||
s = strings.TrimSpace(s)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *Client) lines(suffix string) ([]string, error) {
|
||||
j, err := c.Get(suffix)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
s := strings.Split(strings.TrimSpace(j), "\n")
|
||||
for i := range s {
|
||||
s[i] = strings.TrimSpace(s[i])
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// ProjectID returns the current instance's project ID string.
|
||||
func (c *Client) ProjectID() (string, error) { return projID.get(c) }
|
||||
|
||||
// NumericProjectID returns the current instance's numeric project ID.
|
||||
func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) }
|
||||
|
||||
// InstanceID returns the current VM's numeric instance ID.
|
||||
func (c *Client) InstanceID() (string, error) { return instID.get(c) }
|
||||
|
||||
// InternalIP returns the instance's primary internal IP address.
|
||||
func (c *Client) InternalIP() (string, error) {
|
||||
return c.getTrimmed("instance/network-interfaces/0/ip")
|
||||
}
|
||||
|
||||
// ExternalIP returns the instance's primary external (public) IP address.
|
||||
func (c *Client) ExternalIP() (string, error) {
|
||||
return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
|
||||
}
|
||||
|
||||
// Hostname returns the instance's hostname. This will be of the form
|
||||
// "<instanceID>.c.<projID>.internal".
|
||||
func (c *Client) Hostname() (string, error) {
|
||||
return c.getTrimmed("instance/hostname")
|
||||
}
|
||||
|
||||
// InstanceTags returns the list of user-defined instance tags,
|
||||
// assigned when initially creating a GCE instance.
|
||||
func (c *Client) InstanceTags() ([]string, error) {
|
||||
var s []string
|
||||
j, err := c.Get("instance/tags")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return s, nil
|
||||
}
|
||||
|
||||
// InstanceName returns the current VM's instance ID string.
|
||||
func (c *Client) InstanceName() (string, error) {
|
||||
host, err := c.Hostname()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return strings.Split(host, ".")[0], nil
|
||||
}
|
||||
|
||||
// Zone returns the current VM's zone, such as "us-central1-b".
|
||||
func (c *Client) Zone() (string, error) {
|
||||
zone, err := c.getTrimmed("instance/zone")
|
||||
// zone is of the form "projects/<projNum>/zones/<zoneName>".
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return zone[strings.LastIndex(zone, "/")+1:], nil
|
||||
}
|
||||
|
||||
// InstanceAttributes returns the list of user-defined attributes,
|
||||
// assigned when initially creating a GCE VM instance. The value of an
|
||||
// attribute can be obtained with InstanceAttributeValue.
|
||||
func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") }
|
||||
|
||||
// ProjectAttributes returns the list of user-defined attributes
|
||||
// applying to the project as a whole, not just this VM. The value of
|
||||
// an attribute can be obtained with ProjectAttributeValue.
|
||||
func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") }
|
||||
|
||||
// InstanceAttributeValue returns the value of the provided VM
|
||||
// instance attribute.
|
||||
//
|
||||
// If the requested attribute is not defined, the returned error will
|
||||
// be of type NotDefinedError.
|
||||
//
|
||||
// InstanceAttributeValue may return ("", nil) if the attribute was
|
||||
// defined to be the empty string.
|
||||
func (c *Client) InstanceAttributeValue(attr string) (string, error) {
|
||||
return c.Get("instance/attributes/" + attr)
|
||||
}
|
||||
|
||||
// ProjectAttributeValue returns the value of the provided
|
||||
// project attribute.
|
||||
//
|
||||
// If the requested attribute is not defined, the returned error will
|
||||
// be of type NotDefinedError.
|
||||
//
|
||||
// ProjectAttributeValue may return ("", nil) if the attribute was
|
||||
// defined to be the empty string.
|
||||
func (c *Client) ProjectAttributeValue(attr string) (string, error) {
|
||||
return c.Get("project/attributes/" + attr)
|
||||
}
|
||||
|
||||
// Scopes returns the service account scopes for the given account.
|
||||
// The account may be empty or the string "default" to use the instance's
|
||||
// main account.
|
||||
func (c *Client) Scopes(serviceAccount string) ([]string, error) {
|
||||
if serviceAccount == "" {
|
||||
serviceAccount = "default"
|
||||
}
|
||||
return c.lines("instance/service-accounts/" + serviceAccount + "/scopes")
|
||||
}
|
||||
|
||||
// Subscribe subscribes to a value from the metadata service.
|
||||
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
|
||||
// The suffix may contain query parameters.
|
||||
//
|
||||
// Subscribe calls fn with the latest metadata value indicated by the provided
|
||||
// suffix. If the metadata value is deleted, fn is called with the empty string
|
||||
// and ok false. Subscribe blocks until fn returns a non-nil error or the value
|
||||
// is deleted. Subscribe returns the error value returned from the last call to
|
||||
// fn, which may be nil when ok == false.
|
||||
func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) error {
|
||||
const failedSubscribeSleep = time.Second * 5
|
||||
|
||||
// First check to see if the metadata value exists at all.
|
||||
val, lastETag, err := c.getETag(suffix)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := fn(val, true); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ok := true
|
||||
if strings.ContainsRune(suffix, '?') {
|
||||
suffix += "&wait_for_change=true&last_etag="
|
||||
} else {
|
||||
suffix += "?wait_for_change=true&last_etag="
|
||||
}
|
||||
for {
|
||||
val, etag, err := c.getETag(suffix + url.QueryEscape(lastETag))
|
||||
if err != nil {
|
||||
if _, deleted := err.(NotDefinedError); !deleted {
|
||||
time.Sleep(failedSubscribeSleep)
|
||||
continue // Retry on other errors.
|
||||
}
|
||||
ok = false
|
||||
}
|
||||
lastETag = etag
|
||||
|
||||
if err := fn(val, ok); err != nil || !ok {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright 2016 Docker, Inc.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,187 @@
|
|||
# Compose on Kubernetes
|
||||
|
||||
[![CircleCI](https://circleci.com/gh/docker/compose-on-kubernetes/tree/master.svg?style=svg)](https://circleci.com/gh/docker/compose-on-kubernetes/tree/master)
|
||||
|
||||
Compose on Kubernetes allows you to deploy Docker Compose files onto a
|
||||
Kubernetes cluster.
|
||||
|
||||
# Table of contents
|
||||
|
||||
- [Get started](#get-started)
|
||||
- [Developing Compose on Kubernetes](#developing-compose-on-kubernetes)
|
||||
|
||||
More documentation can be found in the [docs/](./docs) directory. This includes:
|
||||
- [Architecture](./docs/architecture.md)
|
||||
- [Mapping of stack to Kubernetes objects](./docs/mapping.md)
|
||||
- [Compatibility matrix](./docs/compatibility.md)
|
||||
|
||||
# Get started
|
||||
|
||||
Compose on Kubernetes comes installed on
|
||||
[Docker Desktop](https://www.docker.com/products/docker-desktop) and
|
||||
[Docker Enterprise](https://www.docker.com/products/docker-enterprise).
|
||||
|
||||
On Docker Desktop you will need to activate Kubernetes in the settings to use
|
||||
Compose on Kubernetes.
|
||||
|
||||
## Check that Compose on Kubernetes is installed
|
||||
|
||||
You can check that Compose on Kubernetes is installed by checking for the
|
||||
availability of the API using the command:
|
||||
|
||||
```console
|
||||
$ kubectl api-versions | grep compose
|
||||
compose.docker.com/v1beta1
|
||||
compose.docker.com/v1beta2
|
||||
```
|
||||
|
||||
## Deploy a stack
|
||||
|
||||
To deploy a stack, you can use the Docker CLI:
|
||||
|
||||
```console
|
||||
$ cat docker-compose.yml
|
||||
version: '3.3'
|
||||
|
||||
services:
|
||||
|
||||
db:
|
||||
build: db
|
||||
image: dockersamples/k8s-wordsmith-db
|
||||
|
||||
words:
|
||||
build: words
|
||||
image: dockersamples/k8s-wordsmith-api
|
||||
deploy:
|
||||
replicas: 5
|
||||
|
||||
web:
|
||||
build: web
|
||||
image: dockersamples/k8s-wordsmith-web
|
||||
ports:
|
||||
- "33000:80"
|
||||
|
||||
$ docker stack deploy --orchestrator=kubernetes -c docker-compose.yml hellokube
|
||||
```
|
||||
|
||||
# Developing Compose on Kubernetes
|
||||
|
||||
See the [contributing](./CONTRIBUTING.md) guides for how to contribute code.
|
||||
|
||||
## Pre-requisites
|
||||
|
||||
- `make`
|
||||
- [Docker Desktop](https://www.docker.com/products/docker-desktop) (Mac or Windows) with engine version 18.09 or later
|
||||
- Enable Buildkit by setting `DOCKER_BUILDKIT=1` in your environment
|
||||
- Enable Kubernetes in Docker Desktop settings
|
||||
|
||||
### For live debugging
|
||||
|
||||
- Debugger capable of remote debugging with Delve API version 2
|
||||
- Goland run-configs are pre-configured
|
||||
|
||||
## Debug quick start
|
||||
|
||||
### Debug install
|
||||
|
||||
To build and install a debug version of Compose on Kubernetes onto Docker
|
||||
Desktop, you can use the following command:
|
||||
|
||||
```console
|
||||
$ make -f debug.Makefile install-debug-images
|
||||
```
|
||||
|
||||
This command:
|
||||
- Builds the images with debug symbols
|
||||
- Runs the debug installer:
|
||||
- Installs debug versions of API server and Compose controller in the `docker` namespace
|
||||
- Creates two debugging _LoadBalancer_ services (unused in this mode)
|
||||
|
||||
You can verify that Compose on Kubernetes is running with `kubectl` as follows:
|
||||
|
||||
```console
|
||||
$ kubectl get all -n docker
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/compose-7c4dfcff76-jgwst 1/1 Running 0 59s
|
||||
pod/compose-api-759f8dbb4b-2z5n2 2/2 Running 0 59s
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/compose-api ClusterIP 10.98.42.151 <none> 443/TCP 59s
|
||||
service/compose-api-server-remote-debug LoadBalancer 10.101.198.179 localhost 40001:31693/TCP 59s
|
||||
service/compose-controller-remote-debug LoadBalancer 10.101.158.160 localhost 40000:31167/TCP 59s
|
||||
|
||||
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
|
||||
deployment.apps/compose 1 1 1 1 59s
|
||||
deployment.apps/compose-api 1 1 1 1 59s
|
||||
|
||||
NAME DESIRED CURRENT READY AGE
|
||||
replicaset.apps/compose-7c4dfcff76 1 1 1 59s
|
||||
replicaset.apps/compose-api-759f8dbb4b 1 1 1 59s
|
||||
```
|
||||
|
||||
If you describe one of the deployments, you should see `*-debug:latest` in the
|
||||
image name.
|
||||
|
||||
### Live debugging install
|
||||
|
||||
To build and install a live debugging version of Compose on Kubernetes onto
|
||||
Docker Desktop, you can use the following command:
|
||||
|
||||
```console
|
||||
$ make -f debug.Makefile install-live-debug-images
|
||||
```
|
||||
|
||||
This command:
|
||||
- Builds the images with debug symbols
|
||||
- Sets the image entrypoint to run a [Delve server](https://github.com/derekparker/delve)
|
||||
- Runs the debug installer
|
||||
- Installs debug version of API server and Compose controller in the `docker` namespace
|
||||
- Creates two debugging _LoadBalancer_ services
|
||||
- `localhost:40000`: Compose controller
|
||||
- `localhost:40001`: API server
|
||||
- The API server and Compose controller only start once a debugger is attached
|
||||
|
||||
To attach a debugger you have multiple options:
|
||||
- Use [GoLand](https://www.jetbrains.com/go/): configuration can be found in `.idea` of the repository
|
||||
- Select the `Debug all` config, setup breakpoints and start the debugger
|
||||
- Set your Delve compatible debugger to point to use `locahost:40000` and `localhost:40001`
|
||||
- Using a terminal: `dlv connect localhost:40000` then type `continue` and hit enter
|
||||
|
||||
To verify that the components are installed, you can use the following command:
|
||||
|
||||
```console
|
||||
$ kubectl get all -n docker
|
||||
```
|
||||
|
||||
To verify that the API server has started, ensure that it has started logging:
|
||||
```console
|
||||
$ kubectl logs -f -n docker deployment.apps/compose-api compose
|
||||
API server listening at: [::]:40000
|
||||
ERROR: logging before flag.Parse: I1207 15:25:13.760739 11 plugins.go:158] Loaded 2 mutating admission controller(s) successfully in the following order: NamespaceLifecycle,MutatingAdmissionWebhook.
|
||||
ERROR: logging before flag.Parse: I1207 15:25:13.763211 11 plugins.go:161] Loaded 1 validating admission controller(s) successfully in the following order: ValidatingAdmissionWebhook.
|
||||
ERROR: logging before flag.Parse: W1207 15:25:13.767429 11 client_config.go:552] Neither --kubeconfig nor --master was specified. Using the inClusterConfig. This might not work.
|
||||
ERROR: logging before flag.Parse: W1207 15:25:13.851500 11 genericapiserver.go:319] Skipping API compose.docker.com/storage because it has no resources.
|
||||
ERROR: logging before flag.Parse: I1207 15:25:13.998154 11 serve.go:116] Serving securely on [::]:9443
|
||||
```
|
||||
|
||||
To verify that the Compose controller has started, ensure that it is logging:
|
||||
```console
|
||||
kubectl logs -f -n docker deployment.apps/compose
|
||||
API server listening at: [::]:40000
|
||||
Version: v0.4.16-dirty
|
||||
Git commit: b2e3a6b-dirty
|
||||
OS/Arch: linux/amd64
|
||||
Built: Fri Dec 7 15:18:13 2018
|
||||
time="2018-12-07T15:25:19Z" level=info msg="Controller ready"
|
||||
```
|
||||
|
||||
## Reinstall default
|
||||
|
||||
To reinstall the default Compose on Kubernetes on Docker Desktop, simply restart
|
||||
your Kubernetes cluster. You can do this by deactivating and then reactivating
|
||||
Kubernetes or by restarting Docker Desktop.
|
||||
See the [contributing](./CONTRIBUTING.md) and [debugging](./DEBUGGING.md) guides.
|
||||
|
||||
# Deploying Compose on Kubernetes
|
||||
|
||||
- Guide for [Azure AKS](./docs/install-on-aks.md).
|
|
@ -0,0 +1,55 @@
|
|||
package apis
|
||||
|
||||
import (
|
||||
apiv1beta1 "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
apiv1beta2 "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
"github.com/pkg/errors"
|
||||
apimachinerymetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// StackVersion represents the detected Compose Component on Kubernetes side.
|
||||
type StackVersion string
|
||||
|
||||
const (
|
||||
// StackAPIV1Beta1 is returned if it's the most recent version available.
|
||||
StackAPIV1Beta1 = StackVersion("v1beta1")
|
||||
// StackAPIV1Beta2 is returned if it's the most recent version available.
|
||||
StackAPIV1Beta2 = StackVersion("v1beta2")
|
||||
)
|
||||
|
||||
// GetStackAPIVersion returns the most recent stack API installed.
|
||||
func GetStackAPIVersion(clientSet *kubernetes.Clientset) (StackVersion, error) {
|
||||
groups, err := clientSet.Discovery().ServerGroups()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return getAPIVersion(groups)
|
||||
}
|
||||
|
||||
func getAPIVersion(groups *metav1.APIGroupList) (StackVersion, error) {
|
||||
switch {
|
||||
case findVersion(apiv1beta2.SchemeGroupVersion, groups.Groups):
|
||||
return StackAPIV1Beta2, nil
|
||||
case findVersion(apiv1beta1.SchemeGroupVersion, groups.Groups):
|
||||
return StackAPIV1Beta1, nil
|
||||
default:
|
||||
return "", errors.Errorf("failed to find a Stack API version")
|
||||
}
|
||||
}
|
||||
|
||||
func findVersion(stackAPI schema.GroupVersion, groups []apimachinerymetav1.APIGroup) bool {
|
||||
for _, group := range groups {
|
||||
if group.Name == stackAPI.Group {
|
||||
for _, version := range group.Versions {
|
||||
if version.Version == stackAPI.Version {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
107
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/clientset.go
generated
vendored
Normal file
107
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/clientset.go
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
package clientset
|
||||
|
||||
import (
|
||||
composev1beta1 "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1"
|
||||
composev1beta2 "github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2"
|
||||
glog "github.com/golang/glog"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
)
|
||||
|
||||
// Interface defines the methods a compose kube client should have
|
||||
// FIXME(vdemeester) is it required ?
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
ComposeV1beta2() composev1beta2.ComposeV1beta2Interface
|
||||
ComposeV1beta1() composev1beta1.ComposeV1beta1Interface
|
||||
// Deprecated: please explicitly pick a version if possible.
|
||||
Compose() composev1beta1.ComposeV1beta1Interface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups. Each group has exactly one
|
||||
// version included in a Clientset.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
*composev1beta2.ComposeV1beta2Client
|
||||
*composev1beta1.ComposeV1beta1Client
|
||||
}
|
||||
|
||||
// ComposeV1beta2 retrieves the ComposeV1beta2Client
|
||||
func (c *Clientset) ComposeV1beta2() composev1beta2.ComposeV1beta2Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.ComposeV1beta2Client
|
||||
}
|
||||
|
||||
// ComposeV1beta1 retrieves the ComposeV1beta1Client
|
||||
func (c *Clientset) ComposeV1beta1() composev1beta1.ComposeV1beta1Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.ComposeV1beta1Client
|
||||
}
|
||||
|
||||
// Compose retrieves the default version of ComposeClient.
|
||||
// deprecated: please explicitly pick a version.
|
||||
func (c *Clientset) Compose() composev1beta1.ComposeV1beta1Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.ComposeV1beta1Client
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.ComposeV1beta2Client, err = composev1beta2.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cs.ComposeV1beta1Client, err = composev1beta1.NewForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy)
|
||||
if err != nil {
|
||||
glog.Errorf("failed to create the DiscoveryClient: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
var cs Clientset
|
||||
cs.ComposeV1beta2Client = composev1beta2.NewForConfigOrDie(c)
|
||||
cs.ComposeV1beta1Client = composev1beta1.NewForConfigOrDie(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c)
|
||||
return &cs
|
||||
}
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.ComposeV1beta2Client = composev1beta2.New(c)
|
||||
cs.ComposeV1beta1Client = composev1beta1.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
45
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/scheme/register.go
generated
vendored
Normal file
45
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/scheme/register.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package scheme
|
||||
|
||||
import (
|
||||
composev1beta1 "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
composev1beta2 "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
|
||||
// For GKE authentication
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
|
||||
)
|
||||
|
||||
// Variables required for registration
|
||||
var (
|
||||
Scheme = runtime.NewScheme()
|
||||
Codecs = serializer.NewCodecFactory(Scheme)
|
||||
ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
)
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
AddToScheme(Scheme)
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kuberentes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
func AddToScheme(scheme *runtime.Scheme) {
|
||||
composev1beta2.AddToScheme(scheme)
|
||||
composev1beta1.AddToScheme(scheme)
|
||||
|
||||
}
|
74
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1/compose_client.go
generated
vendored
Normal file
74
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1/compose_client.go
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
"github.com/docker/compose-on-kubernetes/api/client/clientset/scheme"
|
||||
v1beta1 "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// ComposeV1beta1Interface defines the methods a compose v1beta1 client has
|
||||
type ComposeV1beta1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
StacksGetter
|
||||
}
|
||||
|
||||
// ComposeV1beta1Client is used to interact with features provided by the compose.docker.com group.
|
||||
type ComposeV1beta1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
// Stacks returns a stack client
|
||||
func (c *ComposeV1beta1Client) Stacks(namespace string) StackInterface {
|
||||
return newStacks(c, namespace)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new ComposeV1beta1Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ComposeV1beta1Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ComposeV1beta1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new ComposeV1beta1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ComposeV1beta1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new ComposeV1beta1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *ComposeV1beta1Client {
|
||||
return &ComposeV1beta1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1beta1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ComposeV1beta1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
175
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1/stack.go
generated
vendored
Normal file
175
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta1/stack.go
generated
vendored
Normal file
|
@ -0,0 +1,175 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
scheme "github.com/docker/compose-on-kubernetes/api/client/clientset/scheme"
|
||||
v1beta1 "github.com/docker/compose-on-kubernetes/api/compose/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// StacksGetter has a method to return a StackInterface.
|
||||
// A group's client should implement this interface.
|
||||
type StacksGetter interface {
|
||||
Stacks(namespace string) StackInterface
|
||||
}
|
||||
|
||||
// StackInterface has methods to work with Stack resources.
|
||||
type StackInterface interface {
|
||||
Create(*v1beta1.Stack) (*v1beta1.Stack, error)
|
||||
Update(*v1beta1.Stack) (*v1beta1.Stack, error)
|
||||
UpdateStatus(*v1beta1.Stack) (*v1beta1.Stack, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1beta1.Stack, error)
|
||||
List(opts v1.ListOptions) (*v1beta1.StackList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*v1beta1.Stack, error)
|
||||
WithSkipValidation() StackInterface
|
||||
}
|
||||
|
||||
var _ StackInterface = &stacks{}
|
||||
|
||||
// stacks implements StackInterface
|
||||
type stacks struct {
|
||||
client rest.Interface
|
||||
ns string
|
||||
skipValidation bool
|
||||
}
|
||||
|
||||
// newStacks returns a Stacks
|
||||
func newStacks(c *ComposeV1beta1Client, namespace string) *stacks {
|
||||
return &stacks{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *stacks) handleSkipValidation(req *rest.Request) *rest.Request {
|
||||
if !c.skipValidation {
|
||||
return req
|
||||
}
|
||||
return req.Param("skip-validation", "1")
|
||||
}
|
||||
|
||||
// Create takes the representation of a stack and creates it. Returns the server's representation of the stack, and an error, if there is any.
|
||||
func (c *stacks) Create(stack *v1beta1.Stack) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.handleSkipValidation(c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Body(stack)).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a stack and updates it. Returns the server's representation of the stack, and an error, if there is any.
|
||||
func (c *stacks) Update(stack *v1beta1.Stack) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.handleSkipValidation(c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(stack.Name).
|
||||
Body(stack)).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclientstatus=false comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *stacks) UpdateStatus(stack *v1beta1.Stack) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.handleSkipValidation(c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(stack.Name).
|
||||
SubResource("status").
|
||||
Body(stack)).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Delete takes name of the stack and deletes it. Returns an error if one occurs.
|
||||
func (c *stacks) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.handleSkipValidation(c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(name).
|
||||
Body(options)).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *stacks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.handleSkipValidation(c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options)).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Get takes name of the stack, and returns the corresponding stack object, and an error if there is any.
|
||||
func (c *stacks) Get(name string, options v1.GetOptions) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Stacks that match those selectors.
|
||||
func (c *stacks) List(opts v1.ListOptions) (*v1beta1.StackList, error) {
|
||||
result := &v1beta1.StackList{}
|
||||
err := c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested stacks.
|
||||
func (c *stacks) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched stack.
|
||||
func (c *stacks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*v1beta1.Stack, error) {
|
||||
result := &v1beta1.Stack{}
|
||||
err := c.handleSkipValidation(c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data)).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// WithSkipValidation creates a new Stack Client interface with validation disabled
|
||||
func (c *stacks) WithSkipValidation() StackInterface {
|
||||
return &stacks{
|
||||
skipValidation: true,
|
||||
client: c.client,
|
||||
ns: c.ns,
|
||||
}
|
||||
}
|
74
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2/compose_client.go
generated
vendored
Normal file
74
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2/compose_client.go
generated
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/compose-on-kubernetes/api/client/clientset/scheme"
|
||||
v1beta2 "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// ComposeV1beta2Interface defines the methods a compose v1beta2 client has
|
||||
type ComposeV1beta2Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
StacksGetter
|
||||
}
|
||||
|
||||
// ComposeV1beta2Client is used to interact with features provided by the compose.docker.com group.
|
||||
type ComposeV1beta2Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
// Stacks returns a stack client
|
||||
func (c *ComposeV1beta2Client) Stacks(namespace string) StackInterface {
|
||||
return newStacks(c, namespace)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new ComposeV1beta2Client for the given config.
|
||||
func NewForConfig(c *rest.Config) (*ComposeV1beta2Client, error) {
|
||||
config := *c
|
||||
if err := setConfigDefaults(&config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client, err := rest.RESTClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ComposeV1beta2Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new ComposeV1beta2Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *ComposeV1beta2Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new ComposeV1beta2Client for the given RESTClient.
|
||||
func New(c rest.Interface) *ComposeV1beta2Client {
|
||||
return &ComposeV1beta2Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) error {
|
||||
gv := v1beta2.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *ComposeV1beta2Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
173
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2/stack.go
generated
vendored
Normal file
173
vendor/github.com/docker/compose-on-kubernetes/api/client/clientset/typed/compose/v1beta2/stack.go
generated
vendored
Normal file
|
@ -0,0 +1,173 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
scheme "github.com/docker/compose-on-kubernetes/api/client/clientset/scheme"
|
||||
v1beta2 "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
// StacksGetter has a method to return a StackInterface.
|
||||
// A group's client should implement this interface.
|
||||
type StacksGetter interface {
|
||||
Stacks(namespace string) StackInterface
|
||||
}
|
||||
|
||||
// StackInterface has methods to work with Stack resources.
|
||||
type StackInterface interface {
|
||||
Create(*v1beta2.Stack) (*v1beta2.Stack, error)
|
||||
Update(*v1beta2.Stack) (*v1beta2.Stack, error)
|
||||
UpdateStatus(*v1beta2.Stack) (*v1beta2.Stack, error)
|
||||
Delete(name string, options *v1.DeleteOptions) error
|
||||
DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error
|
||||
Get(name string, options v1.GetOptions) (*v1beta2.Stack, error)
|
||||
List(opts v1.ListOptions) (*v1beta2.StackList, error)
|
||||
Watch(opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*v1beta2.Stack, error)
|
||||
WithSkipValidation() StackInterface
|
||||
}
|
||||
|
||||
// stacks implements StackInterface
|
||||
type stacks struct {
|
||||
skipValidation bool
|
||||
client rest.Interface
|
||||
ns string
|
||||
}
|
||||
|
||||
// newStacks returns a Stacks
|
||||
func newStacks(c *ComposeV1beta2Client, namespace string) *stacks {
|
||||
return &stacks{
|
||||
client: c.RESTClient(),
|
||||
ns: namespace,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *stacks) handleSkipValidation(req *rest.Request) *rest.Request {
|
||||
if !c.skipValidation {
|
||||
return req
|
||||
}
|
||||
return req.Param("skip-validation", "1")
|
||||
}
|
||||
|
||||
// Create takes the representation of a stack and creates it. Returns the server's representation of the stack, and an error, if there is any.
|
||||
func (c *stacks) Create(stack *v1beta2.Stack) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.handleSkipValidation(c.client.Post().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Body(stack)).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a stack and updates it. Returns the server's representation of the stack, and an error, if there is any.
|
||||
func (c *stacks) Update(stack *v1beta2.Stack) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.handleSkipValidation(c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(stack.Name).
|
||||
Body(stack)).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// UpdateStatus was generated because the type contains a Status member.
|
||||
// Add a +genclientstatus=false comment above the type to avoid generating UpdateStatus().
|
||||
|
||||
func (c *stacks) UpdateStatus(stack *v1beta2.Stack) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.handleSkipValidation(c.client.Put().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(stack.Name).
|
||||
SubResource("status").
|
||||
Body(stack)).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Delete takes name of the stack and deletes it. Returns an error if one occurs.
|
||||
func (c *stacks) Delete(name string, options *v1.DeleteOptions) error {
|
||||
return c.handleSkipValidation(c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(name).
|
||||
Body(options)).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// DeleteCollection deletes a collection of objects.
|
||||
func (c *stacks) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
|
||||
return c.handleSkipValidation(c.client.Delete().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&listOptions, scheme.ParameterCodec).
|
||||
Body(options)).
|
||||
Do().
|
||||
Error()
|
||||
}
|
||||
|
||||
// Get takes name of the stack, and returns the corresponding stack object, and an error if there is any.
|
||||
func (c *stacks) Get(name string, options v1.GetOptions) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
Name(name).
|
||||
VersionedParams(&options, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// List takes label and field selectors, and returns the list of Stacks that match those selectors.
|
||||
func (c *stacks) List(opts v1.ListOptions) (*v1beta2.StackList, error) {
|
||||
result := &v1beta2.StackList{}
|
||||
err := c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the requested stacks.
|
||||
func (c *stacks) Watch(opts v1.ListOptions) (watch.Interface, error) {
|
||||
opts.Watch = true
|
||||
return c.client.Get().
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
VersionedParams(&opts, scheme.ParameterCodec).
|
||||
Watch()
|
||||
}
|
||||
|
||||
// Patch applies the patch and returns the patched stack.
|
||||
func (c *stacks) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (*v1beta2.Stack, error) {
|
||||
result := &v1beta2.Stack{}
|
||||
err := c.handleSkipValidation(c.client.Patch(pt).
|
||||
Namespace(c.ns).
|
||||
Resource("stacks").
|
||||
SubResource(subresources...).
|
||||
Name(name).
|
||||
Body(data)).
|
||||
Do().
|
||||
Into(result)
|
||||
return result, err
|
||||
}
|
||||
|
||||
// WithSkipValidation creates a new Stack Client interface with validation disabled
|
||||
func (c *stacks) WithSkipValidation() StackInterface {
|
||||
return &stacks{
|
||||
skipValidation: true,
|
||||
client: c.client,
|
||||
ns: c.ns,
|
||||
}
|
||||
}
|
25
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/compose/interface.go
generated
vendored
Normal file
25
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/compose/interface.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
package compose
|
||||
|
||||
import (
|
||||
"github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2"
|
||||
"github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
V1beta2() v1beta2.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory) Interface {
|
||||
return &group{f}
|
||||
}
|
||||
|
||||
// V1beta2 returns a new v1beta2.Interface.
|
||||
func (g *group) V1beta2() v1beta2.Interface {
|
||||
return v1beta2.New(g.SharedInformerFactory)
|
||||
}
|
25
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2/interface.go
generated
vendored
Normal file
25
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2/interface.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// Stacks returns a StackInformer.
|
||||
Stacks() StackInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory) Interface {
|
||||
return &version{f}
|
||||
}
|
||||
|
||||
// Stacks returns a StackInformer.
|
||||
func (v *version) Stacks() StackInformer {
|
||||
return &stackInformer{factory: v.SharedInformerFactory}
|
||||
}
|
51
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2/stack.go
generated
vendored
Normal file
51
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/compose/v1beta2/stack.go
generated
vendored
Normal file
|
@ -0,0 +1,51 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/compose-on-kubernetes/api/client/clientset"
|
||||
"github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces"
|
||||
"github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2"
|
||||
compose_v1beta2 "github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// StackInformer provides access to a shared informer and lister for
|
||||
// Stacks.
|
||||
type StackInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() v1beta2.StackLister
|
||||
}
|
||||
|
||||
type stackInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
}
|
||||
|
||||
func newStackInformer(client clientset.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
sharedIndexInformer := cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
return client.ComposeV1beta2().Stacks(v1.NamespaceAll).List(options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
return client.ComposeV1beta2().Stacks(v1.NamespaceAll).Watch(options)
|
||||
},
|
||||
},
|
||||
&compose_v1beta2.Stack{},
|
||||
resyncPeriod,
|
||||
cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc},
|
||||
)
|
||||
|
||||
return sharedIndexInformer
|
||||
}
|
||||
|
||||
func (f *stackInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&compose_v1beta2.Stack{}, newStackInformer)
|
||||
}
|
||||
|
||||
func (f *stackInformer) Lister() v1beta2.StackLister {
|
||||
return v1beta2.NewStackLister(f.Informer().GetIndexer())
|
||||
}
|
101
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/factory.go
generated
vendored
Normal file
101
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/factory.go
generated
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
package informers
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/docker/compose-on-kubernetes/api/client/clientset"
|
||||
"github.com/docker/compose-on-kubernetes/api/client/informers/compose"
|
||||
"github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client clientset.Interface
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory
|
||||
func NewSharedInformerFactory(client clientset.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return &sharedInformerFactory{
|
||||
client: client,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
}
|
||||
}
|
||||
|
||||
// Start initializes all requested informers.
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
go informer.Run(stopCh)
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCacheSync waits for all started informers' cache were synced.
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InternalInformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
informer = newFunc(f.client, f.defaultResync)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
Compose() compose.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Compose() compose.Interface {
|
||||
return compose.New(f)
|
||||
}
|
44
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/generic.go
generated
vendored
Normal file
44
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/generic.go
generated
vendored
Normal file
|
@ -0,0 +1,44 @@
|
|||
package informers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=Compose, Version=V1beta1
|
||||
case v1beta2.SchemeGroupVersion.WithResource("stacks"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Compose().V1beta2().Stacks().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
18
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces/factory_interfaces.go
generated
vendored
Normal file
18
vendor/github.com/docker/compose-on-kubernetes/api/client/informers/internalinterfaces/factory_interfaces.go
generated
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
package internalinterfaces
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/compose-on-kubernetes/api/client/clientset"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// NewInformerFunc defines a Informer constructor (from a clientset and a duration)
|
||||
type NewInformerFunc func(clientset.Interface, time.Duration) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
9
vendor/github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2/expansion_generated.go
generated
vendored
Normal file
9
vendor/github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2/expansion_generated.go
generated
vendored
Normal file
|
@ -0,0 +1,9 @@
|
|||
package v1beta2
|
||||
|
||||
// StackListerExpansion allows custom methods to be added to
|
||||
// StackLister.
|
||||
type StackListerExpansion interface{}
|
||||
|
||||
// StackNamespaceListerExpansion allows custom methods to be added to
|
||||
// StackNamespaceLister.
|
||||
type StackNamespaceListerExpansion interface{}
|
78
vendor/github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2/stack.go
generated
vendored
Normal file
78
vendor/github.com/docker/compose-on-kubernetes/api/client/listers/compose/v1beta2/stack.go
generated
vendored
Normal file
|
@ -0,0 +1,78 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/compose-on-kubernetes/api/compose/v1beta2"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// StackLister helps list Stacks.
|
||||
type StackLister interface {
|
||||
// List lists all Stacks in the indexer.
|
||||
List(selector labels.Selector) ([]*v1beta2.Stack, error)
|
||||
// Stacks returns an object that can list and get Stacks.
|
||||
Stacks(namespace string) StackNamespaceLister
|
||||
StackListerExpansion
|
||||
}
|
||||
|
||||
// stackLister implements the StackLister interface.
|
||||
type stackLister struct {
|
||||
indexer cache.Indexer
|
||||
}
|
||||
|
||||
// NewStackLister returns a new StackLister.
|
||||
func NewStackLister(indexer cache.Indexer) StackLister {
|
||||
return &stackLister{indexer: indexer}
|
||||
}
|
||||
|
||||
// List lists all Stacks in the indexer.
|
||||
func (s *stackLister) List(selector labels.Selector) ([]*v1beta2.Stack, error) {
|
||||
stacks := []*v1beta2.Stack{}
|
||||
err := cache.ListAll(s.indexer, selector, func(m interface{}) {
|
||||
stacks = append(stacks, m.(*v1beta2.Stack))
|
||||
})
|
||||
return stacks, err
|
||||
}
|
||||
|
||||
// Stacks returns an object that can list and get Stacks.
|
||||
func (s *stackLister) Stacks(namespace string) StackNamespaceLister {
|
||||
return stackNamespaceLister{indexer: s.indexer, namespace: namespace}
|
||||
}
|
||||
|
||||
// StackNamespaceLister helps list and get Stacks.
|
||||
type StackNamespaceLister interface {
|
||||
// List lists all Stacks in the indexer for a given namespace.
|
||||
List(selector labels.Selector) ([]*v1beta2.Stack, error)
|
||||
// Get retrieves the Stack from the indexer for a given namespace and name.
|
||||
Get(name string) (*v1beta2.Stack, error)
|
||||
StackNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// stackNamespaceLister implements the StackNamespaceLister
|
||||
// interface.
|
||||
type stackNamespaceLister struct {
|
||||
indexer cache.Indexer
|
||||
namespace string
|
||||
}
|
||||
|
||||
// List lists all Stacks in the indexer for a given namespace.
|
||||
func (s stackNamespaceLister) List(selector labels.Selector) ([]*v1beta2.Stack, error) {
|
||||
stacks := []*v1beta2.Stack{}
|
||||
err := cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
|
||||
stacks = append(stacks, m.(*v1beta2.Stack))
|
||||
})
|
||||
return stacks, err
|
||||
}
|
||||
|
||||
// Get retrieves the Stack from the indexer for a given namespace and name.
|
||||
func (s stackNamespaceLister) Get(name string) (*v1beta2.Stack, error) {
|
||||
obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !exists {
|
||||
return nil, errors.NewNotFound(v1beta2.GroupResource("stack"), name)
|
||||
}
|
||||
return obj.(*v1beta2.Stack), nil
|
||||
}
|
25
vendor/github.com/docker/compose-on-kubernetes/api/compose/clone/maps.go
generated
vendored
Normal file
25
vendor/github.com/docker/compose-on-kubernetes/api/compose/clone/maps.go
generated
vendored
Normal file
|
@ -0,0 +1,25 @@
|
|||
package clone
|
||||
|
||||
// MapOfStringToSliceOfString deep copy a map[string][]string
|
||||
func MapOfStringToSliceOfString(source map[string][]string) map[string][]string {
|
||||
if source == nil {
|
||||
return nil
|
||||
}
|
||||
res := make(map[string][]string, len(source))
|
||||
for k, v := range source {
|
||||
res[k] = SliceOfString(v)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// MapOfStringToInt deep copy a map[string]int
|
||||
func MapOfStringToInt(source map[string]int) map[string]int {
|
||||
if source == nil {
|
||||
return nil
|
||||
}
|
||||
res := make(map[string]int, len(source))
|
||||
for k, v := range source {
|
||||
res[k] = v
|
||||
}
|
||||
return res
|
||||
}
|
11
vendor/github.com/docker/compose-on-kubernetes/api/compose/clone/slices.go
generated
vendored
Normal file
11
vendor/github.com/docker/compose-on-kubernetes/api/compose/clone/slices.go
generated
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
package clone
|
||||
|
||||
// SliceOfString deep copy a slice of strings
|
||||
func SliceOfString(source []string) []string {
|
||||
if source == nil {
|
||||
return nil
|
||||
}
|
||||
res := make([]string, len(source))
|
||||
copy(res, source)
|
||||
return res
|
||||
}
|
3
vendor/github.com/docker/compose-on-kubernetes/api/compose/impersonation/doc.go
generated
vendored
Normal file
3
vendor/github.com/docker/compose-on-kubernetes/api/compose/impersonation/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
// Package impersonation holds data structures for enabling user impersonation within Conpose for Kubernetes
|
||||
// +k8s:openapi-gen=true
|
||||
package impersonation
|
26
vendor/github.com/docker/compose-on-kubernetes/api/compose/impersonation/impersonationconfig.go
generated
vendored
Normal file
26
vendor/github.com/docker/compose-on-kubernetes/api/compose/impersonation/impersonationconfig.go
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
package impersonation
|
||||
|
||||
import "github.com/docker/compose-on-kubernetes/api/compose/clone"
|
||||
|
||||
// Config contains the data required to impersonate a user.
|
||||
type Config struct {
|
||||
// UserName is the username to impersonate on each request.
|
||||
UserName string
|
||||
// Groups are the groups to impersonate on each request.
|
||||
Groups []string
|
||||
// Extra is a free-form field which can be used to link some authentication information
|
||||
// to authorization information. This field allows you to impersonate it.
|
||||
Extra map[string][]string
|
||||
}
|
||||
|
||||
// Clone clones the impersonation config
|
||||
func (ic *Config) Clone() *Config {
|
||||
if ic == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(Config)
|
||||
result.UserName = ic.UserName
|
||||
result.Groups = clone.SliceOfString(ic.Groups)
|
||||
result.Extra = clone.MapOfStringToSliceOfString(ic.Extra)
|
||||
return result
|
||||
}
|
10
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/doc.go
generated
vendored
Normal file
10
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,10 @@
|
|||
// Api versions allow the api contract for a resource to be changed while keeping
|
||||
// backward compatibility by support multiple concurrent versions
|
||||
// of the same resource
|
||||
|
||||
// Package v1beta1 is the first version of the Stack spec, containing only a compose file
|
||||
// +k8s:openapi-gen=true
|
||||
// +k8s:deepcopy-gen=package,register
|
||||
// +k8s:defaulter-gen=TypeMeta
|
||||
// +groupName=compose.docker.com
|
||||
package v1beta1
|
31
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/owner.go
generated
vendored
Normal file
31
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/owner.go
generated
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
"github.com/docker/compose-on-kubernetes/api/compose/impersonation"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// Owner defines the owner of a stack. It is used to impersonate the controller calls
|
||||
// to kubernetes api.
|
||||
type Owner struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Owner impersonation.Config `json:"owner,omitempty"`
|
||||
}
|
||||
|
||||
func (o *Owner) clone() *Owner {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(Owner)
|
||||
result.TypeMeta = o.TypeMeta
|
||||
result.ObjectMeta = o.ObjectMeta
|
||||
result.Owner = *result.Owner.Clone()
|
||||
return result
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the owner
|
||||
func (o *Owner) DeepCopyObject() runtime.Object {
|
||||
return o.clone()
|
||||
}
|
4
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/parsing.go
generated
vendored
Normal file
4
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/parsing.go
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
package v1beta1
|
||||
|
||||
// MaxComposeVersion is the most recent version of compose file Schema supported in v1beta1
|
||||
const MaxComposeVersion = "3.5"
|
39
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/register.go
generated
vendored
Normal file
39
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/register.go
generated
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the group name used to register these objects
|
||||
const GroupName = "compose.docker.com"
|
||||
|
||||
// Alias variables for the registration
|
||||
var (
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta1"}
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(addKnownTypes)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Stack{},
|
||||
&StackList{},
|
||||
&Owner{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Resource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func Resource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
87
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/stack.go
generated
vendored
Normal file
87
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta1/stack.go
generated
vendored
Normal file
|
@ -0,0 +1,87 @@
|
|||
package v1beta1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// StackList defines a list of stacks
|
||||
type StackList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
Items []Stack `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the stack list
|
||||
func (s *StackList) DeepCopyObject() runtime.Object {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(StackList)
|
||||
result.TypeMeta = s.TypeMeta
|
||||
result.ListMeta = s.ListMeta
|
||||
if s.Items == nil {
|
||||
return result
|
||||
}
|
||||
result.Items = make([]Stack, len(s.Items))
|
||||
for ix, s := range s.Items {
|
||||
result.Items[ix] = *s.clone()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// Stack defines a stack object to be register in the kubernetes API
|
||||
type Stack struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec StackSpec `json:"spec,omitempty"`
|
||||
Status StackStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// StackSpec defines the desired state of Stack
|
||||
type StackSpec struct {
|
||||
ComposeFile string `json:"composeFile,omitempty"`
|
||||
}
|
||||
|
||||
// StackPhase defines the status phase in which the stack is.
|
||||
type StackPhase string
|
||||
|
||||
// These are valid conditions of a stack.
|
||||
const (
|
||||
// StackAvailable means the stack is available.
|
||||
StackAvailable StackPhase = "Available"
|
||||
// StackProgressing means the deployment is progressing.
|
||||
StackProgressing StackPhase = "Progressing"
|
||||
// StackFailure is added in a stack when one of its members fails to be created
|
||||
// or deleted.
|
||||
StackFailure StackPhase = "Failure"
|
||||
)
|
||||
|
||||
// StackStatus defines the observed state of Stack
|
||||
type StackStatus struct {
|
||||
// Current condition of the stack.
|
||||
Phase StackPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=StackPhase"`
|
||||
// A human readable message indicating details about the stack.
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
|
||||
}
|
||||
|
||||
func (s *Stack) clone() *Stack {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
// in v1beta1, Stack has no pointer, slice or map. Plain old struct copy is ok
|
||||
result := *s
|
||||
return &result
|
||||
}
|
||||
|
||||
// Clone implements the Cloner interface for kubernetes
|
||||
func (s *Stack) Clone() *Stack {
|
||||
return s.clone()
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the stack
|
||||
func (s *Stack) DeepCopyObject() runtime.Object {
|
||||
return s.clone()
|
||||
}
|
26
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/composefile_stack_types.go
generated
vendored
Normal file
26
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/composefile_stack_types.go
generated
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// ComposeFile is the content of a stack's compose file if any
|
||||
type ComposeFile struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
ComposeFile string `json:"composeFile,omitempty"`
|
||||
}
|
||||
|
||||
func (c *ComposeFile) clone() *ComposeFile {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
res := *c
|
||||
return &res
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the ComposeFile
|
||||
func (c *ComposeFile) DeepCopyObject() runtime.Object {
|
||||
return c.clone()
|
||||
}
|
660
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/deepcopy_generated.go
generated
vendored
Normal file
660
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/deepcopy_generated.go
generated
vendored
Normal file
|
@ -0,0 +1,660 @@
|
|||
// +build !ignore_autogenerated
|
||||
|
||||
/*
|
||||
Copyright The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Code generated by C:\gohome\bin\deepcopy-gen.exe. DO NOT EDIT.
|
||||
|
||||
package v1beta2
|
||||
|
||||
import (
|
||||
time "time"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ConfigObjConfig) DeepCopyInto(out *ConfigObjConfig) {
|
||||
*out = *in
|
||||
out.External = in.External
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigObjConfig.
|
||||
func (in *ConfigObjConfig) DeepCopy() *ConfigObjConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ConfigObjConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Constraint) DeepCopyInto(out *Constraint) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Constraint.
|
||||
func (in *Constraint) DeepCopy() *Constraint {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Constraint)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Constraints) DeepCopyInto(out *Constraints) {
|
||||
*out = *in
|
||||
if in.OperatingSystem != nil {
|
||||
in, out := &in.OperatingSystem, &out.OperatingSystem
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(Constraint)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Architecture != nil {
|
||||
in, out := &in.Architecture, &out.Architecture
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(Constraint)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Hostname != nil {
|
||||
in, out := &in.Hostname, &out.Hostname
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(Constraint)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.MatchLabels != nil {
|
||||
in, out := &in.MatchLabels, &out.MatchLabels
|
||||
*out = make(map[string]Constraint, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Constraints.
|
||||
func (in *Constraints) DeepCopy() *Constraints {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Constraints)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *DeployConfig) DeepCopyInto(out *DeployConfig) {
|
||||
*out = *in
|
||||
if in.Replicas != nil {
|
||||
in, out := &in.Replicas, &out.Replicas
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(uint64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.UpdateConfig != nil {
|
||||
in, out := &in.UpdateConfig, &out.UpdateConfig
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(UpdateConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
in.Resources.DeepCopyInto(&out.Resources)
|
||||
if in.RestartPolicy != nil {
|
||||
in, out := &in.RestartPolicy, &out.RestartPolicy
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(RestartPolicy)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
in.Placement.DeepCopyInto(&out.Placement)
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DeployConfig.
|
||||
func (in *DeployConfig) DeepCopy() *DeployConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(DeployConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *External) DeepCopyInto(out *External) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new External.
|
||||
func (in *External) DeepCopy() *External {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(External)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FileObjectConfig) DeepCopyInto(out *FileObjectConfig) {
|
||||
*out = *in
|
||||
out.External = in.External
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileObjectConfig.
|
||||
func (in *FileObjectConfig) DeepCopy() *FileObjectConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FileObjectConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FileReferenceConfig) DeepCopyInto(out *FileReferenceConfig) {
|
||||
*out = *in
|
||||
if in.Mode != nil {
|
||||
in, out := &in.Mode, &out.Mode
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(uint32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FileReferenceConfig.
|
||||
func (in *FileReferenceConfig) DeepCopy() *FileReferenceConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FileReferenceConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HealthCheckConfig) DeepCopyInto(out *HealthCheckConfig) {
|
||||
*out = *in
|
||||
if in.Test != nil {
|
||||
in, out := &in.Test, &out.Test
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Timeout != nil {
|
||||
in, out := &in.Timeout, &out.Timeout
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(time.Duration)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Interval != nil {
|
||||
in, out := &in.Interval, &out.Interval
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(time.Duration)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Retries != nil {
|
||||
in, out := &in.Retries, &out.Retries
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(uint64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HealthCheckConfig.
|
||||
func (in *HealthCheckConfig) DeepCopy() *HealthCheckConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HealthCheckConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Placement) DeepCopyInto(out *Placement) {
|
||||
*out = *in
|
||||
if in.Constraints != nil {
|
||||
in, out := &in.Constraints, &out.Constraints
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(Constraints)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Placement.
|
||||
func (in *Placement) DeepCopy() *Placement {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Placement)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Resource) DeepCopyInto(out *Resource) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resource.
|
||||
func (in *Resource) DeepCopy() *Resource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Resource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *Resources) DeepCopyInto(out *Resources) {
|
||||
*out = *in
|
||||
if in.Limits != nil {
|
||||
in, out := &in.Limits, &out.Limits
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(Resource)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Reservations != nil {
|
||||
in, out := &in.Reservations, &out.Reservations
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(Resource)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources.
|
||||
func (in *Resources) DeepCopy() *Resources {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(Resources)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *RestartPolicy) DeepCopyInto(out *RestartPolicy) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestartPolicy.
|
||||
func (in *RestartPolicy) DeepCopy() *RestartPolicy {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(RestartPolicy)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *SecretConfig) DeepCopyInto(out *SecretConfig) {
|
||||
*out = *in
|
||||
out.External = in.External
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretConfig.
|
||||
func (in *SecretConfig) DeepCopy() *SecretConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(SecretConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceConfig) DeepCopyInto(out *ServiceConfig) {
|
||||
*out = *in
|
||||
if in.CapAdd != nil {
|
||||
in, out := &in.CapAdd, &out.CapAdd
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.CapDrop != nil {
|
||||
in, out := &in.CapDrop, &out.CapDrop
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Command != nil {
|
||||
in, out := &in.Command, &out.Command
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Configs != nil {
|
||||
in, out := &in.Configs, &out.Configs
|
||||
*out = make([]ServiceConfigObjConfig, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
in.Deploy.DeepCopyInto(&out.Deploy)
|
||||
if in.Entrypoint != nil {
|
||||
in, out := &in.Entrypoint, &out.Entrypoint
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Environment != nil {
|
||||
in, out := &in.Environment, &out.Environment
|
||||
*out = make(map[string]*string, len(*in))
|
||||
for key, val := range *in {
|
||||
if val == nil {
|
||||
(*out)[key] = nil
|
||||
} else {
|
||||
outVal := *val
|
||||
(*out)[key] = &outVal
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.ExtraHosts != nil {
|
||||
in, out := &in.ExtraHosts, &out.ExtraHosts
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.HealthCheck != nil {
|
||||
in, out := &in.HealthCheck, &out.HealthCheck
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(HealthCheckConfig)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
if in.Labels != nil {
|
||||
in, out := &in.Labels, &out.Labels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
if in.Ports != nil {
|
||||
in, out := &in.Ports, &out.Ports
|
||||
*out = make([]ServicePortConfig, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.Secrets != nil {
|
||||
in, out := &in.Secrets, &out.Secrets
|
||||
*out = make([]ServiceSecretConfig, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.StopGracePeriod != nil {
|
||||
in, out := &in.StopGracePeriod, &out.StopGracePeriod
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(time.Duration)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Tmpfs != nil {
|
||||
in, out := &in.Tmpfs, &out.Tmpfs
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.User != nil {
|
||||
in, out := &in.User, &out.User
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(int64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
if in.Volumes != nil {
|
||||
in, out := &in.Volumes, &out.Volumes
|
||||
*out = make([]ServiceVolumeConfig, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceConfig.
|
||||
func (in *ServiceConfig) DeepCopy() *ServiceConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceConfigObjConfig) DeepCopyInto(out *ServiceConfigObjConfig) {
|
||||
*out = *in
|
||||
if in.Mode != nil {
|
||||
in, out := &in.Mode, &out.Mode
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(uint32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceConfigObjConfig.
|
||||
func (in *ServiceConfigObjConfig) DeepCopy() *ServiceConfigObjConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceConfigObjConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServicePortConfig) DeepCopyInto(out *ServicePortConfig) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServicePortConfig.
|
||||
func (in *ServicePortConfig) DeepCopy() *ServicePortConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServicePortConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceSecretConfig) DeepCopyInto(out *ServiceSecretConfig) {
|
||||
*out = *in
|
||||
if in.Mode != nil {
|
||||
in, out := &in.Mode, &out.Mode
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(uint32)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSecretConfig.
|
||||
func (in *ServiceSecretConfig) DeepCopy() *ServiceSecretConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceSecretConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceVolumeConfig) DeepCopyInto(out *ServiceVolumeConfig) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceVolumeConfig.
|
||||
func (in *ServiceVolumeConfig) DeepCopy() *ServiceVolumeConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceVolumeConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *StackSpec) DeepCopyInto(out *StackSpec) {
|
||||
*out = *in
|
||||
if in.Services != nil {
|
||||
in, out := &in.Services, &out.Services
|
||||
*out = make([]ServiceConfig, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.Secrets != nil {
|
||||
in, out := &in.Secrets, &out.Secrets
|
||||
*out = make(map[string]SecretConfig, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(SecretConfig)
|
||||
val.DeepCopyInto(newVal)
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
}
|
||||
if in.Configs != nil {
|
||||
in, out := &in.Configs, &out.Configs
|
||||
*out = make(map[string]ConfigObjConfig, len(*in))
|
||||
for key, val := range *in {
|
||||
newVal := new(ConfigObjConfig)
|
||||
val.DeepCopyInto(newVal)
|
||||
(*out)[key] = *newVal
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StackSpec.
|
||||
func (in *StackSpec) DeepCopy() *StackSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(StackSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *UpdateConfig) DeepCopyInto(out *UpdateConfig) {
|
||||
*out = *in
|
||||
if in.Parallelism != nil {
|
||||
in, out := &in.Parallelism, &out.Parallelism
|
||||
if *in == nil {
|
||||
*out = nil
|
||||
} else {
|
||||
*out = new(uint64)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpdateConfig.
|
||||
func (in *UpdateConfig) DeepCopy() *UpdateConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(UpdateConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
7
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/doc.go
generated
vendored
Normal file
7
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
// Api versions allow the api contract for a resource to be changed while keeping
|
||||
// backward compatibility by support multiple concurrent versions
|
||||
// of the same resource
|
||||
|
||||
// Package v1beta2 is the second version of the stack, containing a structured spec
|
||||
// +k8s:openapi-gen=true
|
||||
package v1beta2
|
30
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/owner.go
generated
vendored
Normal file
30
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/owner.go
generated
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/compose-on-kubernetes/api/compose/impersonation"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// Owner describes the user who created the stack
|
||||
type Owner struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Owner impersonation.Config `json:"owner,omitempty"`
|
||||
}
|
||||
|
||||
func (o *Owner) clone() *Owner {
|
||||
if o == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(Owner)
|
||||
result.TypeMeta = o.TypeMeta
|
||||
result.ObjectMeta = o.ObjectMeta
|
||||
result.Owner = *result.Owner.Clone()
|
||||
return result
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the owner
|
||||
func (o *Owner) DeepCopyObject() runtime.Object {
|
||||
return o.clone()
|
||||
}
|
42
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/register.go
generated
vendored
Normal file
42
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/register.go
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// GroupName is the name of the compose group
|
||||
const GroupName = "compose.docker.com"
|
||||
|
||||
var (
|
||||
// SchemeGroupVersion is group version used to register these objects
|
||||
SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1beta2"}
|
||||
// SchemeBuilder is the scheme builder
|
||||
SchemeBuilder runtime.SchemeBuilder
|
||||
localSchemeBuilder = &SchemeBuilder
|
||||
// AddToScheme adds to scheme
|
||||
AddToScheme = localSchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func init() {
|
||||
localSchemeBuilder.Register(addKnownTypes)
|
||||
}
|
||||
|
||||
// Adds the list of known types to api.Scheme.
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&Stack{},
|
||||
&StackList{},
|
||||
&Owner{},
|
||||
&ComposeFile{},
|
||||
&Scale{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GroupResource takes an unqualified resource and returns a Group qualified GroupResource
|
||||
func GroupResource(resource string) schema.GroupResource {
|
||||
return SchemeGroupVersion.WithResource(resource).GroupResource()
|
||||
}
|
29
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/scale.go
generated
vendored
Normal file
29
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/scale.go
generated
vendored
Normal file
|
@ -0,0 +1,29 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"github.com/docker/compose-on-kubernetes/api/compose/clone"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// Scale contains the current/desired replica count for services in a stack.
|
||||
type Scale struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
Spec map[string]int `json:"spec,omitempty"`
|
||||
Status map[string]int `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
func (s *Scale) clone() *Scale {
|
||||
return &Scale{
|
||||
TypeMeta: s.TypeMeta,
|
||||
ObjectMeta: s.ObjectMeta,
|
||||
Spec: clone.MapOfStringToInt(s.Spec),
|
||||
Status: clone.MapOfStringToInt(s.Status),
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the scale
|
||||
func (s *Scale) DeepCopyObject() runtime.Object {
|
||||
return s.clone()
|
||||
}
|
270
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/stack.go
generated
vendored
Normal file
270
vendor/github.com/docker/compose-on-kubernetes/api/compose/v1beta2/stack.go
generated
vendored
Normal file
|
@ -0,0 +1,270 @@
|
|||
package v1beta2
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// StackList is a list of stacks
|
||||
type StackList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
|
||||
Items []Stack `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// Stack is v1beta2's representation of a Stack
|
||||
type Stack struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty"`
|
||||
|
||||
Spec *StackSpec `json:"spec,omitempty"`
|
||||
Status *StackStatus `json:"status,omitempty"`
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the stack
|
||||
func (s *Stack) DeepCopyObject() runtime.Object {
|
||||
return s.clone()
|
||||
}
|
||||
|
||||
// DeepCopyObject clones the stack list
|
||||
func (s *StackList) DeepCopyObject() runtime.Object {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(StackList)
|
||||
result.TypeMeta = s.TypeMeta
|
||||
result.ListMeta = s.ListMeta
|
||||
if s.Items == nil {
|
||||
return result
|
||||
}
|
||||
result.Items = make([]Stack, len(s.Items))
|
||||
for ix, s := range s.Items {
|
||||
result.Items[ix] = *s.clone()
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Stack) clone() *Stack {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := new(Stack)
|
||||
result.TypeMeta = s.TypeMeta
|
||||
result.ObjectMeta = s.ObjectMeta
|
||||
result.Spec = s.Spec.DeepCopy()
|
||||
result.Status = s.Status.clone()
|
||||
return result
|
||||
}
|
||||
|
||||
// StackSpec defines the desired state of Stack
|
||||
// +k8s:deepcopy-gen=true
|
||||
type StackSpec struct {
|
||||
Services []ServiceConfig `json:"services,omitempty"`
|
||||
Secrets map[string]SecretConfig `json:"secrets,omitempty"`
|
||||
Configs map[string]ConfigObjConfig `json:"configs,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceConfig is the configuration of one service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type ServiceConfig struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
|
||||
CapAdd []string `json:"cap_add,omitempty"`
|
||||
CapDrop []string `json:"cap_drop,omitempty"`
|
||||
Command []string `json:"command,omitempty"`
|
||||
Configs []ServiceConfigObjConfig `json:"configs,omitempty"`
|
||||
Deploy DeployConfig `json:"deploy,omitempty"`
|
||||
Entrypoint []string `json:"entrypoint,omitempty"`
|
||||
Environment map[string]*string `json:"environment,omitempty"`
|
||||
ExtraHosts []string `json:"extra_hosts,omitempty"`
|
||||
Hostname string `json:"hostname,omitempty"`
|
||||
HealthCheck *HealthCheckConfig `json:"health_check,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Ipc string `json:"ipc,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Pid string `json:"pid,omitempty"`
|
||||
Ports []ServicePortConfig `json:"ports,omitempty"`
|
||||
Privileged bool `json:"privileged,omitempty"`
|
||||
ReadOnly bool `json:"read_only,omitempty"`
|
||||
Secrets []ServiceSecretConfig `json:"secrets,omitempty"`
|
||||
StdinOpen bool `json:"stdin_open,omitempty"`
|
||||
StopGracePeriod *time.Duration `json:"stop_grace_period,omitempty"`
|
||||
Tmpfs []string `json:"tmpfs,omitempty"`
|
||||
Tty bool `json:"tty,omitempty"`
|
||||
User *int64 `json:"user,omitempty"`
|
||||
Volumes []ServiceVolumeConfig `json:"volumes,omitempty"`
|
||||
WorkingDir string `json:"working_dir,omitempty"`
|
||||
}
|
||||
|
||||
// ServicePortConfig is the port configuration for a service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type ServicePortConfig struct {
|
||||
Mode string `json:"mode,omitempty"`
|
||||
Target uint32 `json:"target,omitempty"`
|
||||
Published uint32 `json:"published,omitempty"`
|
||||
Protocol string `json:"protocol,omitempty"`
|
||||
}
|
||||
|
||||
// FileObjectConfig is a config type for a file used by a service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type FileObjectConfig struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
File string `json:"file,omitempty"`
|
||||
External External `json:"external,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
// SecretConfig for a secret
|
||||
// +k8s:deepcopy-gen=true
|
||||
type SecretConfig FileObjectConfig
|
||||
|
||||
// ConfigObjConfig is the config for the swarm "Config" object
|
||||
// +k8s:deepcopy-gen=true
|
||||
type ConfigObjConfig FileObjectConfig
|
||||
|
||||
// External identifies a Volume or Network as a reference to a resource that is
|
||||
// not managed, and should already exist.
|
||||
// External.name is deprecated and replaced by Volume.name
|
||||
// +k8s:deepcopy-gen=true
|
||||
type External struct {
|
||||
Name string `json:"name,omitempty"`
|
||||
External bool `json:"external,omitempty"`
|
||||
}
|
||||
|
||||
// FileReferenceConfig for a reference to a swarm file object
|
||||
// +k8s:deepcopy-gen=true
|
||||
type FileReferenceConfig struct {
|
||||
Source string `json:"source,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
UID string `json:"uid,omitempty"`
|
||||
GID string `json:"gid,omitempty"`
|
||||
Mode *uint32 `json:"mode,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceConfigObjConfig is the config obj configuration for a service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type ServiceConfigObjConfig FileReferenceConfig
|
||||
|
||||
// ServiceSecretConfig is the secret configuration for a service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type ServiceSecretConfig FileReferenceConfig
|
||||
|
||||
// DeployConfig is the deployment configuration for a service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type DeployConfig struct {
|
||||
Mode string `json:"mode,omitempty"`
|
||||
Replicas *uint64 `json:"replicas,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
UpdateConfig *UpdateConfig `json:"update_config,omitempty"`
|
||||
Resources Resources `json:"resources,omitempty"`
|
||||
RestartPolicy *RestartPolicy `json:"restart_policy,omitempty"`
|
||||
Placement Placement `json:"placement,omitempty"`
|
||||
}
|
||||
|
||||
// UpdateConfig is the service update configuration
|
||||
// +k8s:deepcopy-gen=true
|
||||
type UpdateConfig struct {
|
||||
Parallelism *uint64 `json:"paralellism,omitempty"`
|
||||
}
|
||||
|
||||
// Resources the resource limits and reservations
|
||||
// +k8s:deepcopy-gen=true
|
||||
type Resources struct {
|
||||
Limits *Resource `json:"limits,omitempty"`
|
||||
Reservations *Resource `json:"reservations,omitempty"`
|
||||
}
|
||||
|
||||
// Resource is a resource to be limited or reserved
|
||||
// +k8s:deepcopy-gen=true
|
||||
type Resource struct {
|
||||
NanoCPUs string `json:"cpus,omitempty"`
|
||||
MemoryBytes int64 `json:"memory,omitempty"`
|
||||
}
|
||||
|
||||
// RestartPolicy is the service restart policy
|
||||
// +k8s:deepcopy-gen=true
|
||||
type RestartPolicy struct {
|
||||
Condition string `json:"condition,omitempty"`
|
||||
}
|
||||
|
||||
// Placement constraints for the service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type Placement struct {
|
||||
Constraints *Constraints `json:"constraints,omitempty"`
|
||||
}
|
||||
|
||||
// Constraints lists constraints that can be set on the service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type Constraints struct {
|
||||
OperatingSystem *Constraint
|
||||
Architecture *Constraint
|
||||
Hostname *Constraint
|
||||
MatchLabels map[string]Constraint
|
||||
}
|
||||
|
||||
// Constraint defines a constraint and it's operator (== or !=)
|
||||
// +k8s:deepcopy-gen=true
|
||||
type Constraint struct {
|
||||
Value string
|
||||
Operator string
|
||||
}
|
||||
|
||||
// HealthCheckConfig the healthcheck configuration for a service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type HealthCheckConfig struct {
|
||||
Test []string `json:"test,omitempty"`
|
||||
Timeout *time.Duration `json:"timeout,omitempty"`
|
||||
Interval *time.Duration `json:"interval,omitempty"`
|
||||
Retries *uint64 `json:"retries,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceVolumeConfig are references to a volume used by a service
|
||||
// +k8s:deepcopy-gen=true
|
||||
type ServiceVolumeConfig struct {
|
||||
Type string `json:"type,omitempty"`
|
||||
Source string `json:"source,omitempty"`
|
||||
Target string `json:"target,omitempty"`
|
||||
ReadOnly bool `json:"read_only,omitempty"`
|
||||
}
|
||||
|
||||
// StackPhase is the deployment phase of a stack
|
||||
type StackPhase string
|
||||
|
||||
// These are valid conditions of a stack.
|
||||
const (
|
||||
// StackAvailable means the stack is available.
|
||||
StackAvailable StackPhase = "Available"
|
||||
// StackProgressing means the deployment is progressing.
|
||||
StackProgressing StackPhase = "Progressing"
|
||||
// StackFailure is added in a stack when one of its members fails to be created
|
||||
// or deleted.
|
||||
StackFailure StackPhase = "Failure"
|
||||
// StackReconciliationPending means the stack has not yet been reconciled
|
||||
StackReconciliationPending StackPhase = "ReconciliationPending"
|
||||
)
|
||||
|
||||
// StackStatus defines the observed state of Stack
|
||||
type StackStatus struct {
|
||||
// Current condition of the stack.
|
||||
// +optional
|
||||
Phase StackPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=StackPhase"`
|
||||
// A human readable message indicating details about the stack.
|
||||
// +optional
|
||||
Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
|
||||
}
|
||||
|
||||
func (s *StackStatus) clone() *StackStatus {
|
||||
if s == nil {
|
||||
return nil
|
||||
}
|
||||
result := *s
|
||||
return &result
|
||||
}
|
||||
|
||||
// Clone clones a Stack
|
||||
func (s *Stack) Clone() *Stack {
|
||||
return s.clone()
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package apis
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/docker/docker/pkg/homedir"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
// NewKubernetesConfig resolves the path to the desired Kubernetes configuration file based on
|
||||
// the KUBECONFIG environment variable and command line flags.
|
||||
func NewKubernetesConfig(configPath string) clientcmd.ClientConfig {
|
||||
kubeConfig := configPath
|
||||
if kubeConfig == "" {
|
||||
if config := os.Getenv("KUBECONFIG"); config != "" {
|
||||
kubeConfig = config
|
||||
} else {
|
||||
kubeConfig = filepath.Join(homedir.Get(), ".kube/config")
|
||||
}
|
||||
}
|
||||
|
||||
return clientcmd.NewNonInteractiveDeferredLoadingClientConfig(
|
||||
&clientcmd.ClientConfigLoadingRules{ExplicitPath: kubeConfig},
|
||||
&clientcmd.ConfigOverrides{})
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
//
|
||||
// +domain=docker.com
|
||||
|
||||
package apis
|
45
vendor/github.com/docker/compose-on-kubernetes/api/labels/labels.go
generated
vendored
Normal file
45
vendor/github.com/docker/compose-on-kubernetes/api/labels/labels.go
generated
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
package labels
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// ForServiceName is the label for the service name.
|
||||
ForServiceName = "com.docker.service.name"
|
||||
// ForStackName is the label for the stack name.
|
||||
ForStackName = "com.docker.stack.namespace"
|
||||
// ForServiceID is the label for the service id.
|
||||
ForServiceID = "com.docker.service.id"
|
||||
)
|
||||
|
||||
// ForService gives the labels to select a given service in a stack.
|
||||
func ForService(stackName, serviceName string) map[string]string {
|
||||
labels := map[string]string{}
|
||||
|
||||
if serviceName != "" {
|
||||
labels[ForServiceName] = serviceName
|
||||
}
|
||||
if stackName != "" {
|
||||
labels[ForStackName] = stackName
|
||||
}
|
||||
if serviceName != "" && stackName != "" {
|
||||
labels[ForServiceID] = stackName + "-" + serviceName
|
||||
}
|
||||
|
||||
return labels
|
||||
}
|
||||
|
||||
// SelectorForStack gives the labelSelector to use for a given stack.
|
||||
// Specific service names can be passed to narrow down the selection.
|
||||
func SelectorForStack(stackName string, serviceNames ...string) string {
|
||||
switch len(serviceNames) {
|
||||
case 0:
|
||||
return fmt.Sprintf("%s=%s", ForStackName, stackName)
|
||||
case 1:
|
||||
return fmt.Sprintf("%s=%s,%s=%s", ForStackName, stackName, ForServiceName, serviceNames[0])
|
||||
default:
|
||||
return fmt.Sprintf("%s=%s,%s in (%s)", ForStackName, stackName, ForServiceName, strings.Join(serviceNames, ","))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
Copyright (c) 2009 The Go Authors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
* Neither the name of Google Inc. nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -0,0 +1,77 @@
|
|||
# OAuth2 for Go
|
||||
|
||||
[![Build Status](https://travis-ci.org/golang/oauth2.svg?branch=master)](https://travis-ci.org/golang/oauth2)
|
||||
[![GoDoc](https://godoc.org/golang.org/x/oauth2?status.svg)](https://godoc.org/golang.org/x/oauth2)
|
||||
|
||||
oauth2 package contains a client implementation for OAuth 2.0 spec.
|
||||
|
||||
## Installation
|
||||
|
||||
~~~~
|
||||
go get golang.org/x/oauth2
|
||||
~~~~
|
||||
|
||||
Or you can manually git clone the repository to
|
||||
`$(go env GOPATH)/src/golang.org/x/oauth2`.
|
||||
|
||||
See godoc for further documentation and examples.
|
||||
|
||||
* [godoc.org/golang.org/x/oauth2](http://godoc.org/golang.org/x/oauth2)
|
||||
* [godoc.org/golang.org/x/oauth2/google](http://godoc.org/golang.org/x/oauth2/google)
|
||||
|
||||
|
||||
## App Engine
|
||||
|
||||
In change 96e89be (March 2015), we removed the `oauth2.Context2` type in favor
|
||||
of the [`context.Context`](https://golang.org/x/net/context#Context) type from
|
||||
the `golang.org/x/net/context` package
|
||||
|
||||
This means it's no longer possible to use the "Classic App Engine"
|
||||
`appengine.Context` type with the `oauth2` package. (You're using
|
||||
Classic App Engine if you import the package `"appengine"`.)
|
||||
|
||||
To work around this, you may use the new `"google.golang.org/appengine"`
|
||||
package. This package has almost the same API as the `"appengine"` package,
|
||||
but it can be fetched with `go get` and used on "Managed VMs" and well as
|
||||
Classic App Engine.
|
||||
|
||||
See the [new `appengine` package's readme](https://github.com/golang/appengine#updating-a-go-app-engine-app)
|
||||
for information on updating your app.
|
||||
|
||||
If you don't want to update your entire app to use the new App Engine packages,
|
||||
you may use both sets of packages in parallel, using only the new packages
|
||||
with the `oauth2` package.
|
||||
|
||||
```go
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
newappengine "google.golang.org/appengine"
|
||||
newurlfetch "google.golang.org/appengine/urlfetch"
|
||||
|
||||
"appengine"
|
||||
)
|
||||
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
var c appengine.Context = appengine.NewContext(r)
|
||||
c.Infof("Logging a message with the old package")
|
||||
|
||||
var ctx context.Context = newappengine.NewContext(r)
|
||||
client := &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Source: google.AppEngineTokenSource(ctx, "scope"),
|
||||
Base: &newurlfetch.Transport{Context: ctx},
|
||||
},
|
||||
}
|
||||
client.Get("...")
|
||||
}
|
||||
```
|
||||
|
||||
## Report Issues / Send Patches
|
||||
|
||||
This repository uses Gerrit for code changes. To learn how to submit changes to
|
||||
this repository, see https://golang.org/doc/contribute.html.
|
||||
|
||||
The main issue tracker for the oauth2 repository is located at
|
||||
https://github.com/golang/oauth2/issues.
|
|
@ -0,0 +1,89 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
package google
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// appengineFlex is set at init time by appengineflex_hook.go. If true, we are on App Engine Flex.
|
||||
var appengineFlex bool
|
||||
|
||||
// Set at init time by appengine_hook.go. If nil, we're not on App Engine.
|
||||
var appengineTokenFunc func(c context.Context, scopes ...string) (token string, expiry time.Time, err error)
|
||||
|
||||
// Set at init time by appengine_hook.go. If nil, we're not on App Engine.
|
||||
var appengineAppIDFunc func(c context.Context) string
|
||||
|
||||
// AppEngineTokenSource returns a token source that fetches tokens
|
||||
// issued to the current App Engine application's service account.
|
||||
// If you are implementing a 3-legged OAuth 2.0 flow on App Engine
|
||||
// that involves user accounts, see oauth2.Config instead.
|
||||
//
|
||||
// The provided context must have come from appengine.NewContext.
|
||||
func AppEngineTokenSource(ctx context.Context, scope ...string) oauth2.TokenSource {
|
||||
if appengineTokenFunc == nil {
|
||||
panic("google: AppEngineTokenSource can only be used on App Engine.")
|
||||
}
|
||||
scopes := append([]string{}, scope...)
|
||||
sort.Strings(scopes)
|
||||
return &appEngineTokenSource{
|
||||
ctx: ctx,
|
||||
scopes: scopes,
|
||||
key: strings.Join(scopes, " "),
|
||||
}
|
||||
}
|
||||
|
||||
// aeTokens helps the fetched tokens to be reused until their expiration.
|
||||
var (
|
||||
aeTokensMu sync.Mutex
|
||||
aeTokens = make(map[string]*tokenLock) // key is space-separated scopes
|
||||
)
|
||||
|
||||
type tokenLock struct {
|
||||
mu sync.Mutex // guards t; held while fetching or updating t
|
||||
t *oauth2.Token
|
||||
}
|
||||
|
||||
type appEngineTokenSource struct {
|
||||
ctx context.Context
|
||||
scopes []string
|
||||
key string // to aeTokens map; space-separated scopes
|
||||
}
|
||||
|
||||
func (ts *appEngineTokenSource) Token() (*oauth2.Token, error) {
|
||||
if appengineTokenFunc == nil {
|
||||
panic("google: AppEngineTokenSource can only be used on App Engine.")
|
||||
}
|
||||
|
||||
aeTokensMu.Lock()
|
||||
tok, ok := aeTokens[ts.key]
|
||||
if !ok {
|
||||
tok = &tokenLock{}
|
||||
aeTokens[ts.key] = tok
|
||||
}
|
||||
aeTokensMu.Unlock()
|
||||
|
||||
tok.mu.Lock()
|
||||
defer tok.mu.Unlock()
|
||||
if tok.t.Valid() {
|
||||
return tok.t, nil
|
||||
}
|
||||
access, exp, err := appengineTokenFunc(ts.ctx, ts.scopes...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tok.t = &oauth2.Token{
|
||||
AccessToken: access,
|
||||
Expiry: exp,
|
||||
}
|
||||
return tok.t, nil
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
// 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 appengine appenginevm
|
||||
|
||||
package google
|
||||
|
||||
import "google.golang.org/appengine"
|
||||
|
||||
func init() {
|
||||
appengineTokenFunc = appengine.AccessToken
|
||||
appengineAppIDFunc = appengine.AppID
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
// 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 appenginevm
|
||||
|
||||
package google
|
||||
|
||||
func init() {
|
||||
appengineFlex = true // Flex doesn't support appengine.AccessToken; depend on metadata server.
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
// 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.
|
||||
|
||||
package google
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// DefaultClient returns an HTTP Client that uses the
|
||||
// DefaultTokenSource to obtain authentication credentials.
|
||||
func DefaultClient(ctx context.Context, scope ...string) (*http.Client, error) {
|
||||
ts, err := DefaultTokenSource(ctx, scope...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return oauth2.NewClient(ctx, ts), nil
|
||||
}
|
||||
|
||||
// DefaultTokenSource returns the token source for
|
||||
// "Application Default Credentials".
|
||||
// It is a shortcut for FindDefaultCredentials(ctx, scope).TokenSource.
|
||||
func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) {
|
||||
creds, err := FindDefaultCredentials(ctx, scope...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return creds.TokenSource, nil
|
||||
}
|
||||
|
||||
// Common implementation for FindDefaultCredentials.
|
||||
func findDefaultCredentials(ctx context.Context, scopes []string) (*DefaultCredentials, error) {
|
||||
// First, try the environment variable.
|
||||
const envVar = "GOOGLE_APPLICATION_CREDENTIALS"
|
||||
if filename := os.Getenv(envVar); filename != "" {
|
||||
creds, err := readCredentialsFile(ctx, filename, scopes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err)
|
||||
}
|
||||
return creds, nil
|
||||
}
|
||||
|
||||
// Second, try a well-known file.
|
||||
filename := wellKnownFile()
|
||||
if creds, err := readCredentialsFile(ctx, filename, scopes); err == nil {
|
||||
return creds, nil
|
||||
} else if !os.IsNotExist(err) {
|
||||
return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err)
|
||||
}
|
||||
|
||||
// Third, if we're on Google App Engine use those credentials.
|
||||
if appengineTokenFunc != nil && !appengineFlex {
|
||||
return &DefaultCredentials{
|
||||
ProjectID: appengineAppIDFunc(ctx),
|
||||
TokenSource: AppEngineTokenSource(ctx, scopes...),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Fourth, if we're on Google Compute Engine use the metadata server.
|
||||
if metadata.OnGCE() {
|
||||
id, _ := metadata.ProjectID()
|
||||
return &DefaultCredentials{
|
||||
ProjectID: id,
|
||||
TokenSource: ComputeTokenSource(""),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// None are found; return helpful error.
|
||||
const url = "https://developers.google.com/accounts/docs/application-default-credentials"
|
||||
return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url)
|
||||
}
|
||||
|
||||
// Common implementation for CredentialsFromJSON.
|
||||
func credentialsFromJSON(ctx context.Context, jsonData []byte, scopes []string) (*DefaultCredentials, error) {
|
||||
var f credentialsFile
|
||||
if err := json.Unmarshal(jsonData, &f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ts, err := f.tokenSource(ctx, append([]string(nil), scopes...))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &DefaultCredentials{
|
||||
ProjectID: f.ProjectID,
|
||||
TokenSource: ts,
|
||||
JSON: jsonData,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func wellKnownFile() string {
|
||||
const f = "application_default_credentials.json"
|
||||
if runtime.GOOS == "windows" {
|
||||
return filepath.Join(os.Getenv("APPDATA"), "gcloud", f)
|
||||
}
|
||||
return filepath.Join(guessUnixHomeDir(), ".config", "gcloud", f)
|
||||
}
|
||||
|
||||
func readCredentialsFile(ctx context.Context, filename string, scopes []string) (*DefaultCredentials, error) {
|
||||
b, err := ioutil.ReadFile(filename)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return CredentialsFromJSON(ctx, b, scopes...)
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
// Copyright 2018 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 go1.9
|
||||
|
||||
// Package google provides support for making OAuth2 authorized and authenticated
|
||||
// HTTP requests to Google APIs. It supports the Web server flow, client-side
|
||||
// credentials, service accounts, Google Compute Engine service accounts, and Google
|
||||
// App Engine service accounts.
|
||||
//
|
||||
// A brief overview of the package follows. For more information, please read
|
||||
// https://developers.google.com/accounts/docs/OAuth2
|
||||
// and
|
||||
// https://developers.google.com/accounts/docs/application-default-credentials.
|
||||
//
|
||||
// OAuth2 Configs
|
||||
//
|
||||
// Two functions in this package return golang.org/x/oauth2.Config values from Google credential
|
||||
// data. Google supports two JSON formats for OAuth2 credentials: one is handled by ConfigFromJSON,
|
||||
// the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or
|
||||
// create an http.Client.
|
||||
//
|
||||
//
|
||||
// Credentials
|
||||
//
|
||||
// The Credentials type represents Google credentials, including Application Default
|
||||
// Credentials.
|
||||
//
|
||||
// Use FindDefaultCredentials to obtain Application Default Credentials.
|
||||
// FindDefaultCredentials looks in some well-known places for a credentials file, and
|
||||
// will call AppEngineTokenSource or ComputeTokenSource as needed.
|
||||
//
|
||||
// DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials,
|
||||
// then use the credentials to construct an http.Client or an oauth2.TokenSource.
|
||||
//
|
||||
// Use CredentialsFromJSON to obtain credentials from either of the two JSON formats
|
||||
// described in OAuth2 Configs, above. The TokenSource in the returned value is the
|
||||
// same as the one obtained from the oauth2.Config returned from ConfigFromJSON or
|
||||
// JWTConfigFromJSON, but the Credentials may contain additional information
|
||||
// that is useful is some circumstances.
|
||||
package google // import "golang.org/x/oauth2/google"
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright 2018 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 !go1.9
|
||||
|
||||
// Package google provides support for making OAuth2 authorized and authenticated
|
||||
// HTTP requests to Google APIs. It supports the Web server flow, client-side
|
||||
// credentials, service accounts, Google Compute Engine service accounts, and Google
|
||||
// App Engine service accounts.
|
||||
//
|
||||
// A brief overview of the package follows. For more information, please read
|
||||
// https://developers.google.com/accounts/docs/OAuth2
|
||||
// and
|
||||
// https://developers.google.com/accounts/docs/application-default-credentials.
|
||||
//
|
||||
// OAuth2 Configs
|
||||
//
|
||||
// Two functions in this package return golang.org/x/oauth2.Config values from Google credential
|
||||
// data. Google supports two JSON formats for OAuth2 credentials: one is handled by ConfigFromJSON,
|
||||
// the other by JWTConfigFromJSON. The returned Config can be used to obtain a TokenSource or
|
||||
// create an http.Client.
|
||||
//
|
||||
//
|
||||
// Credentials
|
||||
//
|
||||
// The DefaultCredentials type represents Google Application Default Credentials, as
|
||||
// well as other forms of credential.
|
||||
//
|
||||
// Use FindDefaultCredentials to obtain Application Default Credentials.
|
||||
// FindDefaultCredentials looks in some well-known places for a credentials file, and
|
||||
// will call AppEngineTokenSource or ComputeTokenSource as needed.
|
||||
//
|
||||
// DefaultClient and DefaultTokenSource are convenience methods. They first call FindDefaultCredentials,
|
||||
// then use the credentials to construct an http.Client or an oauth2.TokenSource.
|
||||
//
|
||||
// Use CredentialsFromJSON to obtain credentials from either of the two JSON
|
||||
// formats described in OAuth2 Configs, above. (The DefaultCredentials returned may
|
||||
// not be "Application Default Credentials".) The TokenSource in the returned value
|
||||
// is the same as the one obtained from the oauth2.Config returned from
|
||||
// ConfigFromJSON or JWTConfigFromJSON, but the DefaultCredentials may contain
|
||||
// additional information that is useful is some circumstances.
|
||||
package google // import "golang.org/x/oauth2/google"
|
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2018 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 go1.9
|
||||
|
||||
package google
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// Credentials holds Google credentials, including "Application Default Credentials".
|
||||
// For more details, see:
|
||||
// https://developers.google.com/accounts/docs/application-default-credentials
|
||||
type Credentials struct {
|
||||
ProjectID string // may be empty
|
||||
TokenSource oauth2.TokenSource
|
||||
|
||||
// JSON contains the raw bytes from a JSON credentials file.
|
||||
// This field may be nil if authentication is provided by the
|
||||
// environment and not with a credentials file, e.g. when code is
|
||||
// running on Google Cloud Platform.
|
||||
JSON []byte
|
||||
}
|
||||
|
||||
// DefaultCredentials is the old name of Credentials.
|
||||
//
|
||||
// Deprecated: use Credentials instead.
|
||||
type DefaultCredentials = Credentials
|
||||
|
||||
// FindDefaultCredentials searches for "Application Default Credentials".
|
||||
//
|
||||
// It looks for credentials in the following places,
|
||||
// preferring the first location found:
|
||||
//
|
||||
// 1. A JSON file whose path is specified by the
|
||||
// GOOGLE_APPLICATION_CREDENTIALS environment variable.
|
||||
// 2. A JSON file in a location known to the gcloud command-line tool.
|
||||
// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json.
|
||||
// On other systems, $HOME/.config/gcloud/application_default_credentials.json.
|
||||
// 3. On Google App Engine it uses the appengine.AccessToken function.
|
||||
// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches
|
||||
// credentials from the metadata server.
|
||||
// (In this final case any provided scopes are ignored.)
|
||||
func FindDefaultCredentials(ctx context.Context, scopes ...string) (*Credentials, error) {
|
||||
return findDefaultCredentials(ctx, scopes)
|
||||
}
|
||||
|
||||
// CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can
|
||||
// represent either a Google Developers Console client_credentials.json file (as in
|
||||
// ConfigFromJSON) or a Google Developers service account key file (as in
|
||||
// JWTConfigFromJSON).
|
||||
func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*Credentials, error) {
|
||||
return credentialsFromJSON(ctx, jsonData, scopes)
|
||||
}
|
|
@ -0,0 +1,192 @@
|
|||
// Copyright 2014 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.
|
||||
|
||||
package google
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/jwt"
|
||||
)
|
||||
|
||||
// Endpoint is Google's OAuth 2.0 endpoint.
|
||||
var Endpoint = oauth2.Endpoint{
|
||||
AuthURL: "https://accounts.google.com/o/oauth2/auth",
|
||||
TokenURL: "https://accounts.google.com/o/oauth2/token",
|
||||
}
|
||||
|
||||
// JWTTokenURL is Google's OAuth 2.0 token URL to use with the JWT flow.
|
||||
const JWTTokenURL = "https://accounts.google.com/o/oauth2/token"
|
||||
|
||||
// ConfigFromJSON uses a Google Developers Console client_credentials.json
|
||||
// file to construct a config.
|
||||
// client_credentials.json can be downloaded from
|
||||
// https://console.developers.google.com, under "Credentials". Download the Web
|
||||
// application credentials in the JSON format and provide the contents of the
|
||||
// file as jsonKey.
|
||||
func ConfigFromJSON(jsonKey []byte, scope ...string) (*oauth2.Config, error) {
|
||||
type cred struct {
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
RedirectURIs []string `json:"redirect_uris"`
|
||||
AuthURI string `json:"auth_uri"`
|
||||
TokenURI string `json:"token_uri"`
|
||||
}
|
||||
var j struct {
|
||||
Web *cred `json:"web"`
|
||||
Installed *cred `json:"installed"`
|
||||
}
|
||||
if err := json.Unmarshal(jsonKey, &j); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var c *cred
|
||||
switch {
|
||||
case j.Web != nil:
|
||||
c = j.Web
|
||||
case j.Installed != nil:
|
||||
c = j.Installed
|
||||
default:
|
||||
return nil, fmt.Errorf("oauth2/google: no credentials found")
|
||||
}
|
||||
if len(c.RedirectURIs) < 1 {
|
||||
return nil, errors.New("oauth2/google: missing redirect URL in the client_credentials.json")
|
||||
}
|
||||
return &oauth2.Config{
|
||||
ClientID: c.ClientID,
|
||||
ClientSecret: c.ClientSecret,
|
||||
RedirectURL: c.RedirectURIs[0],
|
||||
Scopes: scope,
|
||||
Endpoint: oauth2.Endpoint{
|
||||
AuthURL: c.AuthURI,
|
||||
TokenURL: c.TokenURI,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// JWTConfigFromJSON uses a Google Developers service account JSON key file to read
|
||||
// the credentials that authorize and authenticate the requests.
|
||||
// Create a service account on "Credentials" for your project at
|
||||
// https://console.developers.google.com to download a JSON key file.
|
||||
func JWTConfigFromJSON(jsonKey []byte, scope ...string) (*jwt.Config, error) {
|
||||
var f credentialsFile
|
||||
if err := json.Unmarshal(jsonKey, &f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if f.Type != serviceAccountKey {
|
||||
return nil, fmt.Errorf("google: read JWT from JSON credentials: 'type' field is %q (expected %q)", f.Type, serviceAccountKey)
|
||||
}
|
||||
scope = append([]string(nil), scope...) // copy
|
||||
return f.jwtConfig(scope), nil
|
||||
}
|
||||
|
||||
// JSON key file types.
|
||||
const (
|
||||
serviceAccountKey = "service_account"
|
||||
userCredentialsKey = "authorized_user"
|
||||
)
|
||||
|
||||
// credentialsFile is the unmarshalled representation of a credentials file.
|
||||
type credentialsFile struct {
|
||||
Type string `json:"type"` // serviceAccountKey or userCredentialsKey
|
||||
|
||||
// Service Account fields
|
||||
ClientEmail string `json:"client_email"`
|
||||
PrivateKeyID string `json:"private_key_id"`
|
||||
PrivateKey string `json:"private_key"`
|
||||
TokenURL string `json:"token_uri"`
|
||||
ProjectID string `json:"project_id"`
|
||||
|
||||
// User Credential fields
|
||||
// (These typically come from gcloud auth.)
|
||||
ClientSecret string `json:"client_secret"`
|
||||
ClientID string `json:"client_id"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
}
|
||||
|
||||
func (f *credentialsFile) jwtConfig(scopes []string) *jwt.Config {
|
||||
cfg := &jwt.Config{
|
||||
Email: f.ClientEmail,
|
||||
PrivateKey: []byte(f.PrivateKey),
|
||||
PrivateKeyID: f.PrivateKeyID,
|
||||
Scopes: scopes,
|
||||
TokenURL: f.TokenURL,
|
||||
}
|
||||
if cfg.TokenURL == "" {
|
||||
cfg.TokenURL = JWTTokenURL
|
||||
}
|
||||
return cfg
|
||||
}
|
||||
|
||||
func (f *credentialsFile) tokenSource(ctx context.Context, scopes []string) (oauth2.TokenSource, error) {
|
||||
switch f.Type {
|
||||
case serviceAccountKey:
|
||||
cfg := f.jwtConfig(scopes)
|
||||
return cfg.TokenSource(ctx), nil
|
||||
case userCredentialsKey:
|
||||
cfg := &oauth2.Config{
|
||||
ClientID: f.ClientID,
|
||||
ClientSecret: f.ClientSecret,
|
||||
Scopes: scopes,
|
||||
Endpoint: Endpoint,
|
||||
}
|
||||
tok := &oauth2.Token{RefreshToken: f.RefreshToken}
|
||||
return cfg.TokenSource(ctx, tok), nil
|
||||
case "":
|
||||
return nil, errors.New("missing 'type' field in credentials")
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown credential type: %q", f.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// ComputeTokenSource returns a token source that fetches access tokens
|
||||
// from Google Compute Engine (GCE)'s metadata server. It's only valid to use
|
||||
// this token source if your program is running on a GCE instance.
|
||||
// If no account is specified, "default" is used.
|
||||
// Further information about retrieving access tokens from the GCE metadata
|
||||
// server can be found at https://cloud.google.com/compute/docs/authentication.
|
||||
func ComputeTokenSource(account string) oauth2.TokenSource {
|
||||
return oauth2.ReuseTokenSource(nil, computeSource{account: account})
|
||||
}
|
||||
|
||||
type computeSource struct {
|
||||
account string
|
||||
}
|
||||
|
||||
func (cs computeSource) Token() (*oauth2.Token, error) {
|
||||
if !metadata.OnGCE() {
|
||||
return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE")
|
||||
}
|
||||
acct := cs.account
|
||||
if acct == "" {
|
||||
acct = "default"
|
||||
}
|
||||
tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var res struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresInSec int `json:"expires_in"`
|
||||
TokenType string `json:"token_type"`
|
||||
}
|
||||
err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err)
|
||||
}
|
||||
if res.ExpiresInSec == 0 || res.AccessToken == "" {
|
||||
return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata")
|
||||
}
|
||||
return &oauth2.Token{
|
||||
AccessToken: res.AccessToken,
|
||||
TokenType: res.TokenType,
|
||||
Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second),
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
// 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.
|
||||
|
||||
package google
|
||||
|
||||
import (
|
||||
"crypto/rsa"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/internal"
|
||||
"golang.org/x/oauth2/jws"
|
||||
)
|
||||
|
||||
// JWTAccessTokenSourceFromJSON uses a Google Developers service account JSON
|
||||
// key file to read the credentials that authorize and authenticate the
|
||||
// requests, and returns a TokenSource that does not use any OAuth2 flow but
|
||||
// instead creates a JWT and sends that as the access token.
|
||||
// The audience is typically a URL that specifies the scope of the credentials.
|
||||
//
|
||||
// Note that this is not a standard OAuth flow, but rather an
|
||||
// optimization supported by a few Google services.
|
||||
// Unless you know otherwise, you should use JWTConfigFromJSON instead.
|
||||
func JWTAccessTokenSourceFromJSON(jsonKey []byte, audience string) (oauth2.TokenSource, error) {
|
||||
cfg, err := JWTConfigFromJSON(jsonKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("google: could not parse JSON key: %v", err)
|
||||
}
|
||||
pk, err := internal.ParseKey(cfg.PrivateKey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("google: could not parse key: %v", err)
|
||||
}
|
||||
ts := &jwtAccessTokenSource{
|
||||
email: cfg.Email,
|
||||
audience: audience,
|
||||
pk: pk,
|
||||
pkID: cfg.PrivateKeyID,
|
||||
}
|
||||
tok, err := ts.Token()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return oauth2.ReuseTokenSource(tok, ts), nil
|
||||
}
|
||||
|
||||
type jwtAccessTokenSource struct {
|
||||
email, audience string
|
||||
pk *rsa.PrivateKey
|
||||
pkID string
|
||||
}
|
||||
|
||||
func (ts *jwtAccessTokenSource) Token() (*oauth2.Token, error) {
|
||||
iat := time.Now()
|
||||
exp := iat.Add(time.Hour)
|
||||
cs := &jws.ClaimSet{
|
||||
Iss: ts.email,
|
||||
Sub: ts.email,
|
||||
Aud: ts.audience,
|
||||
Iat: iat.Unix(),
|
||||
Exp: exp.Unix(),
|
||||
}
|
||||
hdr := &jws.Header{
|
||||
Algorithm: "RS256",
|
||||
Typ: "JWT",
|
||||
KeyID: string(ts.pkID),
|
||||
}
|
||||
msg, err := jws.Encode(hdr, cs, ts.pk)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("google: could not encode JWT: %v", err)
|
||||
}
|
||||
return &oauth2.Token{AccessToken: msg, TokenType: "Bearer", Expiry: exp}, nil
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
// Copyright 2018 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 !go1.9
|
||||
|
||||
package google
|
||||
|
||||
import (
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
// DefaultCredentials holds Google credentials, including "Application Default Credentials".
|
||||
// For more details, see:
|
||||
// https://developers.google.com/accounts/docs/application-default-credentials
|
||||
type DefaultCredentials struct {
|
||||
ProjectID string // may be empty
|
||||
TokenSource oauth2.TokenSource
|
||||
|
||||
// JSON contains the raw bytes from a JSON credentials file.
|
||||
// This field may be nil if authentication is provided by the
|
||||
// environment and not with a credentials file, e.g. when code is
|
||||
// running on Google Cloud Platform.
|
||||
JSON []byte
|
||||
}
|
||||
|
||||
// FindDefaultCredentials searches for "Application Default Credentials".
|
||||
//
|
||||
// It looks for credentials in the following places,
|
||||
// preferring the first location found:
|
||||
//
|
||||
// 1. A JSON file whose path is specified by the
|
||||
// GOOGLE_APPLICATION_CREDENTIALS environment variable.
|
||||
// 2. A JSON file in a location known to the gcloud command-line tool.
|
||||
// On Windows, this is %APPDATA%/gcloud/application_default_credentials.json.
|
||||
// On other systems, $HOME/.config/gcloud/application_default_credentials.json.
|
||||
// 3. On Google App Engine it uses the appengine.AccessToken function.
|
||||
// 4. On Google Compute Engine and Google App Engine Managed VMs, it fetches
|
||||
// credentials from the metadata server.
|
||||
// (In this final case any provided scopes are ignored.)
|
||||
func FindDefaultCredentials(ctx context.Context, scopes ...string) (*DefaultCredentials, error) {
|
||||
return findDefaultCredentials(ctx, scopes)
|
||||
}
|
||||
|
||||
// CredentialsFromJSON obtains Google credentials from a JSON value. The JSON can
|
||||
// represent either a Google Developers Console client_credentials.json file (as in
|
||||
// ConfigFromJSON) or a Google Developers service account key file (as in
|
||||
// JWTConfigFromJSON).
|
||||
//
|
||||
// Note: despite the name, the returned credentials may not be Application Default Credentials.
|
||||
func CredentialsFromJSON(ctx context.Context, jsonData []byte, scopes ...string) (*DefaultCredentials, error) {
|
||||
return credentialsFromJSON(ctx, jsonData, scopes)
|
||||
}
|
|
@ -0,0 +1,201 @@
|
|||
// 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.
|
||||
|
||||
package google
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
type sdkCredentials struct {
|
||||
Data []struct {
|
||||
Credential struct {
|
||||
ClientID string `json:"client_id"`
|
||||
ClientSecret string `json:"client_secret"`
|
||||
AccessToken string `json:"access_token"`
|
||||
RefreshToken string `json:"refresh_token"`
|
||||
TokenExpiry *time.Time `json:"token_expiry"`
|
||||
} `json:"credential"`
|
||||
Key struct {
|
||||
Account string `json:"account"`
|
||||
Scope string `json:"scope"`
|
||||
} `json:"key"`
|
||||
}
|
||||
}
|
||||
|
||||
// An SDKConfig provides access to tokens from an account already
|
||||
// authorized via the Google Cloud SDK.
|
||||
type SDKConfig struct {
|
||||
conf oauth2.Config
|
||||
initialToken *oauth2.Token
|
||||
}
|
||||
|
||||
// NewSDKConfig creates an SDKConfig for the given Google Cloud SDK
|
||||
// account. If account is empty, the account currently active in
|
||||
// Google Cloud SDK properties is used.
|
||||
// Google Cloud SDK credentials must be created by running `gcloud auth`
|
||||
// before using this function.
|
||||
// The Google Cloud SDK is available at https://cloud.google.com/sdk/.
|
||||
func NewSDKConfig(account string) (*SDKConfig, error) {
|
||||
configPath, err := sdkConfigPath()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("oauth2/google: error getting SDK config path: %v", err)
|
||||
}
|
||||
credentialsPath := filepath.Join(configPath, "credentials")
|
||||
f, err := os.Open(credentialsPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("oauth2/google: failed to load SDK credentials: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
var c sdkCredentials
|
||||
if err := json.NewDecoder(f).Decode(&c); err != nil {
|
||||
return nil, fmt.Errorf("oauth2/google: failed to decode SDK credentials from %q: %v", credentialsPath, err)
|
||||
}
|
||||
if len(c.Data) == 0 {
|
||||
return nil, fmt.Errorf("oauth2/google: no credentials found in %q, run `gcloud auth login` to create one", credentialsPath)
|
||||
}
|
||||
if account == "" {
|
||||
propertiesPath := filepath.Join(configPath, "properties")
|
||||
f, err := os.Open(propertiesPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("oauth2/google: failed to load SDK properties: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
ini, err := parseINI(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("oauth2/google: failed to parse SDK properties %q: %v", propertiesPath, err)
|
||||
}
|
||||
core, ok := ini["core"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("oauth2/google: failed to find [core] section in %v", ini)
|
||||
}
|
||||
active, ok := core["account"]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("oauth2/google: failed to find %q attribute in %v", "account", core)
|
||||
}
|
||||
account = active
|
||||
}
|
||||
|
||||
for _, d := range c.Data {
|
||||
if account == "" || d.Key.Account == account {
|
||||
if d.Credential.AccessToken == "" && d.Credential.RefreshToken == "" {
|
||||
return nil, fmt.Errorf("oauth2/google: no token available for account %q", account)
|
||||
}
|
||||
var expiry time.Time
|
||||
if d.Credential.TokenExpiry != nil {
|
||||
expiry = *d.Credential.TokenExpiry
|
||||
}
|
||||
return &SDKConfig{
|
||||
conf: oauth2.Config{
|
||||
ClientID: d.Credential.ClientID,
|
||||
ClientSecret: d.Credential.ClientSecret,
|
||||
Scopes: strings.Split(d.Key.Scope, " "),
|
||||
Endpoint: Endpoint,
|
||||
RedirectURL: "oob",
|
||||
},
|
||||
initialToken: &oauth2.Token{
|
||||
AccessToken: d.Credential.AccessToken,
|
||||
RefreshToken: d.Credential.RefreshToken,
|
||||
Expiry: expiry,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
return nil, fmt.Errorf("oauth2/google: no such credentials for account %q", account)
|
||||
}
|
||||
|
||||
// Client returns an HTTP client using Google Cloud SDK credentials to
|
||||
// authorize requests. The token will auto-refresh as necessary. The
|
||||
// underlying http.RoundTripper will be obtained using the provided
|
||||
// context. The returned client and its Transport should not be
|
||||
// modified.
|
||||
func (c *SDKConfig) Client(ctx context.Context) *http.Client {
|
||||
return &http.Client{
|
||||
Transport: &oauth2.Transport{
|
||||
Source: c.TokenSource(ctx),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// TokenSource returns an oauth2.TokenSource that retrieve tokens from
|
||||
// Google Cloud SDK credentials using the provided context.
|
||||
// It will returns the current access token stored in the credentials,
|
||||
// and refresh it when it expires, but it won't update the credentials
|
||||
// with the new access token.
|
||||
func (c *SDKConfig) TokenSource(ctx context.Context) oauth2.TokenSource {
|
||||
return c.conf.TokenSource(ctx, c.initialToken)
|
||||
}
|
||||
|
||||
// Scopes are the OAuth 2.0 scopes the current account is authorized for.
|
||||
func (c *SDKConfig) Scopes() []string {
|
||||
return c.conf.Scopes
|
||||
}
|
||||
|
||||
func parseINI(ini io.Reader) (map[string]map[string]string, error) {
|
||||
result := map[string]map[string]string{
|
||||
"": {}, // root section
|
||||
}
|
||||
scanner := bufio.NewScanner(ini)
|
||||
currentSection := ""
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
if strings.HasPrefix(line, ";") {
|
||||
// comment.
|
||||
continue
|
||||
}
|
||||
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
||||
currentSection = strings.TrimSpace(line[1 : len(line)-1])
|
||||
result[currentSection] = map[string]string{}
|
||||
continue
|
||||
}
|
||||
parts := strings.SplitN(line, "=", 2)
|
||||
if len(parts) == 2 && parts[0] != "" {
|
||||
result[currentSection][strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
|
||||
}
|
||||
}
|
||||
if err := scanner.Err(); err != nil {
|
||||
return nil, fmt.Errorf("error scanning ini: %v", err)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// sdkConfigPath tries to guess where the gcloud config is located.
|
||||
// It can be overridden during tests.
|
||||
var sdkConfigPath = func() (string, error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
return filepath.Join(os.Getenv("APPDATA"), "gcloud"), nil
|
||||
}
|
||||
homeDir := guessUnixHomeDir()
|
||||
if homeDir == "" {
|
||||
return "", errors.New("unable to get current user home directory: os/user lookup failed; $HOME is empty")
|
||||
}
|
||||
return filepath.Join(homeDir, ".config", "gcloud"), nil
|
||||
}
|
||||
|
||||
func guessUnixHomeDir() string {
|
||||
// Prefer $HOME over user.Current due to glibc bug: golang.org/issue/13470
|
||||
if v := os.Getenv("HOME"); v != "" {
|
||||
return v
|
||||
}
|
||||
// Else, fall back to user.Current:
|
||||
if u, err := user.Current(); err == nil {
|
||||
return u.HomeDir
|
||||
}
|
||||
return ""
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Copyright 2018 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 appengine
|
||||
|
||||
package internal
|
||||
|
||||
import "google.golang.org/appengine/urlfetch"
|
||||
|
||||
func init() {
|
||||
appengineClientHook = urlfetch.Client
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
// Package internal contains support packages for oauth2 package.
|
||||
package internal
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue