temp commit
This commit is contained in:
141
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/bgpconfig.go
generated
vendored
Normal file
141
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/bgpconfig.go
generated
vendored
Normal file
@@ -0,0 +1,141 @@
|
||||
// Copyright (c) 2017 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
cerrors "github.com/projectcalico/libcalico-go/lib/errors"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// BGPConfigurationInterface has methods to work with BGPConfiguration resources.
|
||||
type BGPConfigurationInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.BGPConfiguration, opts options.SetOptions) (*apiv3.BGPConfiguration, error)
|
||||
Update(ctx context.Context, res *apiv3.BGPConfiguration, opts options.SetOptions) (*apiv3.BGPConfiguration, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.BGPConfiguration, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.BGPConfiguration, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.BGPConfigurationList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// bgpConfigurations implements BGPConfigurationInterface
|
||||
type bgpConfigurations struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a BGPConfiguration and creates it.
|
||||
// Returns the stored representation of the BGPConfiguration, and an error
|
||||
// if there is any.
|
||||
func (r bgpConfigurations) Create(ctx context.Context, res *apiv3.BGPConfiguration, opts options.SetOptions) (*apiv3.BGPConfiguration, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := r.ValidateDefaultOnlyFields(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindBGPConfiguration, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.BGPConfiguration), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a BGPConfiguration and updates it.
|
||||
// Returns the stored representation of the BGPConfiguration, and an error
|
||||
// if there is any.
|
||||
func (r bgpConfigurations) Update(ctx context.Context, res *apiv3.BGPConfiguration, opts options.SetOptions) (*apiv3.BGPConfiguration, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check that NodeToNodeMeshEnabled and ASNumber are set. Can only be set on "default".
|
||||
if err := r.ValidateDefaultOnlyFields(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindBGPConfiguration, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.BGPConfiguration), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the BGPConfiguration and deletes it. Returns an
|
||||
// error if one occurs.
|
||||
func (r bgpConfigurations) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.BGPConfiguration, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindBGPConfiguration, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.BGPConfiguration), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the BGPConfiguration, and returns the corresponding
|
||||
// BGPConfiguration object, and an error if there is any.
|
||||
func (r bgpConfigurations) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.BGPConfiguration, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindBGPConfiguration, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.BGPConfiguration), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of BGPConfiguration objects that match the supplied options.
|
||||
func (r bgpConfigurations) List(ctx context.Context, opts options.ListOptions) (*apiv3.BGPConfigurationList, error) {
|
||||
res := &apiv3.BGPConfigurationList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindBGPConfiguration, apiv3.KindBGPConfigurationList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the BGPConfiguration that
|
||||
// match the supplied options.
|
||||
func (r bgpConfigurations) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindBGPConfiguration, nil)
|
||||
}
|
||||
|
||||
func (r bgpConfigurations) ValidateDefaultOnlyFields(res *apiv3.BGPConfiguration) error {
|
||||
errFields := []cerrors.ErroredField{}
|
||||
if res.ObjectMeta.GetName() != "default" {
|
||||
if res.Spec.NodeToNodeMeshEnabled != nil {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "BGPConfiguration.Spec.NodeToNodeMeshEnabled",
|
||||
Reason: "Cannot set nodeToNodeMeshEnabled on a non default BGP Configuration.",
|
||||
})
|
||||
}
|
||||
|
||||
if res.Spec.ASNumber != nil {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "BGPConfiguration.Spec.ASNumber",
|
||||
Reason: "Cannot set ASNumber on a non default BGP Configuration.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(errFields) > 0 {
|
||||
return cerrors.ErrorValidation{
|
||||
ErroredFields: errFields,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
101
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/bgppeer.go
generated
vendored
Normal file
101
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/bgppeer.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2017 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// BGPPeerInterface has methods to work with BGPPeer resources.
|
||||
type BGPPeerInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.BGPPeer, opts options.SetOptions) (*apiv3.BGPPeer, error)
|
||||
Update(ctx context.Context, res *apiv3.BGPPeer, opts options.SetOptions) (*apiv3.BGPPeer, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.BGPPeer, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.BGPPeer, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.BGPPeerList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// bgpPeers implements BGPPeerInterface
|
||||
type bgpPeers struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a BGPPeer and creates it. Returns the stored
|
||||
// representation of the BGPPeer, and an error, if there is any.
|
||||
func (r bgpPeers) Create(ctx context.Context, res *apiv3.BGPPeer, opts options.SetOptions) (*apiv3.BGPPeer, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindBGPPeer, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.BGPPeer), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a BGPPeer and updates it. Returns the stored
|
||||
// representation of the BGPPeer, and an error, if there is any.
|
||||
func (r bgpPeers) Update(ctx context.Context, res *apiv3.BGPPeer, opts options.SetOptions) (*apiv3.BGPPeer, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindBGPPeer, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.BGPPeer), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the BGPPeer and deletes it. Returns an error if one occurs.
|
||||
func (r bgpPeers) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.BGPPeer, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindBGPPeer, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.BGPPeer), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the BGPPeer, and returns the corresponding BGPPeer object,
|
||||
// and an error if there is any.
|
||||
func (r bgpPeers) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.BGPPeer, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindBGPPeer, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.BGPPeer), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of BGPPeer objects that match the supplied options.
|
||||
func (r bgpPeers) List(ctx context.Context, opts options.ListOptions) (*apiv3.BGPPeerList, error) {
|
||||
res := &apiv3.BGPPeerList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindBGPPeer, apiv3.KindBGPPeerList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the BGPPeers that match the
|
||||
// supplied options.
|
||||
func (r bgpPeers) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindBGPPeer, nil)
|
||||
}
|
||||
339
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/client.go
generated
vendored
Normal file
339
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/client.go
generated
vendored
Normal file
@@ -0,0 +1,339 @@
|
||||
// Copyright (c) 2017-2019 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/satori/go.uuid"
|
||||
|
||||
"github.com/projectcalico/libcalico-go/lib/apiconfig"
|
||||
"github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/backend"
|
||||
bapi "github.com/projectcalico/libcalico-go/lib/backend/api"
|
||||
cerrors "github.com/projectcalico/libcalico-go/lib/errors"
|
||||
"github.com/projectcalico/libcalico-go/lib/ipam"
|
||||
"github.com/projectcalico/libcalico-go/lib/net"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
"github.com/projectcalico/libcalico-go/lib/set"
|
||||
)
|
||||
|
||||
// client implements the client.Interface.
|
||||
type client struct {
|
||||
// The config we were created with.
|
||||
config apiconfig.CalicoAPIConfig
|
||||
|
||||
// The backend client.
|
||||
backend bapi.Client
|
||||
|
||||
// The resources client used internally.
|
||||
resources resourceInterface
|
||||
}
|
||||
|
||||
// New returns a connected client. The ClientConfig can either be created explicitly,
|
||||
// or can be loaded from a config file or environment variables using the LoadClientConfig() function.
|
||||
func New(config apiconfig.CalicoAPIConfig) (Interface, error) {
|
||||
be, err := backend.NewClient(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client{
|
||||
config: config,
|
||||
backend: be,
|
||||
resources: &resources{backend: be},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewFromEnv loads the config from ENV variables and returns a connected client.
|
||||
func NewFromEnv() (Interface, error) {
|
||||
|
||||
config, err := apiconfig.LoadClientConfigFromEnvironment()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return New(*config)
|
||||
}
|
||||
|
||||
// Nodes returns an interface for managing node resources.
|
||||
func (c client) Nodes() NodeInterface {
|
||||
return nodes{client: c}
|
||||
}
|
||||
|
||||
// NetworkPolicies returns an interface for managing policy resources.
|
||||
func (c client) NetworkPolicies() NetworkPolicyInterface {
|
||||
return networkPolicies{client: c}
|
||||
}
|
||||
|
||||
// GlobalNetworkPolicies returns an interface for managing policy resources.
|
||||
func (c client) GlobalNetworkPolicies() GlobalNetworkPolicyInterface {
|
||||
return globalNetworkPolicies{client: c}
|
||||
}
|
||||
|
||||
// IPPools returns an interface for managing IP pool resources.
|
||||
func (c client) IPPools() IPPoolInterface {
|
||||
return ipPools{client: c}
|
||||
}
|
||||
|
||||
// Profiles returns an interface for managing profile resources.
|
||||
func (c client) Profiles() ProfileInterface {
|
||||
return profiles{client: c}
|
||||
}
|
||||
|
||||
// GlobalNetworkSets returns an interface for managing host endpoint resources.
|
||||
func (c client) GlobalNetworkSets() GlobalNetworkSetInterface {
|
||||
return globalNetworkSets{client: c}
|
||||
}
|
||||
|
||||
// NetworkSets returns an interface for managing host endpoint resources.
|
||||
func (c client) NetworkSets() NetworkSetInterface {
|
||||
return networkSets{client: c}
|
||||
}
|
||||
|
||||
// HostEndpoints returns an interface for managing host endpoint resources.
|
||||
func (c client) HostEndpoints() HostEndpointInterface {
|
||||
return hostEndpoints{client: c}
|
||||
}
|
||||
|
||||
// WorkloadEndpoints returns an interface for managing workload endpoint resources.
|
||||
func (c client) WorkloadEndpoints() WorkloadEndpointInterface {
|
||||
return workloadEndpoints{client: c}
|
||||
}
|
||||
|
||||
// BGPPeers returns an interface for managing BGP peer resources.
|
||||
func (c client) BGPPeers() BGPPeerInterface {
|
||||
return bgpPeers{client: c}
|
||||
}
|
||||
|
||||
// IPAM returns an interface for managing IP address assignment and releasing.
|
||||
func (c client) IPAM() ipam.Interface {
|
||||
return ipam.NewIPAMClient(c.backend, poolAccessor{client: &c})
|
||||
}
|
||||
|
||||
// BGPConfigurations returns an interface for managing the BGP configuration resources.
|
||||
func (c client) BGPConfigurations() BGPConfigurationInterface {
|
||||
return bgpConfigurations{client: c}
|
||||
}
|
||||
|
||||
// FelixConfigurations returns an interface for managing the Felix configuration resources.
|
||||
func (c client) FelixConfigurations() FelixConfigurationInterface {
|
||||
return felixConfigurations{client: c}
|
||||
}
|
||||
|
||||
// ClusterInformation returns an interface for managing the cluster information resource.
|
||||
func (c client) ClusterInformation() ClusterInformationInterface {
|
||||
return clusterInformation{client: c}
|
||||
}
|
||||
|
||||
type poolAccessor struct {
|
||||
client *client
|
||||
}
|
||||
|
||||
func (p poolAccessor) GetEnabledPools(ipVersion int) ([]v3.IPPool, error) {
|
||||
return p.getPools(func(pool *v3.IPPool) bool {
|
||||
if pool.Spec.Disabled {
|
||||
log.Debugf("Skipping disabled IP pool (%s)", pool.Name)
|
||||
return false
|
||||
}
|
||||
if _, cidr, err := net.ParseCIDR(pool.Spec.CIDR); err == nil && cidr.Version() == ipVersion {
|
||||
log.Debugf("Adding pool (%s) to the IPPool list", cidr.String())
|
||||
return true
|
||||
} else if err != nil {
|
||||
log.Warnf("Failed to parse the IPPool: %s. Ignoring that IPPool", pool.Spec.CIDR)
|
||||
} else {
|
||||
log.Debugf("Ignoring IPPool: %s. IP version is different.", pool.Spec.CIDR)
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
|
||||
func (p poolAccessor) getPools(filter func(pool *v3.IPPool) bool) ([]v3.IPPool, error) {
|
||||
pools, err := p.client.IPPools().List(context.Background(), options.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
log.Debugf("Got list of all IPPools: %v", pools)
|
||||
var filtered []v3.IPPool
|
||||
for _, pool := range pools.Items {
|
||||
if filter(&pool) {
|
||||
filtered = append(filtered, pool)
|
||||
}
|
||||
}
|
||||
return filtered, nil
|
||||
}
|
||||
|
||||
func (p poolAccessor) GetAllPools() ([]v3.IPPool, error) {
|
||||
return p.getPools(func(pool *v3.IPPool) bool {
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// EnsureInitialized is used to ensure the backend datastore is correctly
|
||||
// initialized for use by Calico. This method may be called multiple times, and
|
||||
// will have no effect if the datastore is already correctly initialized.
|
||||
//
|
||||
// Most Calico deployment scenarios will automatically implicitly invoke this
|
||||
// method and so a general consumer of this API can assume that the datastore
|
||||
// is already initialized.
|
||||
func (c client) EnsureInitialized(ctx context.Context, calicoVersion, clusterType string) error {
|
||||
// Perform datastore specific initialization first.
|
||||
if err := c.backend.EnsureInitialized(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := c.ensureClusterInformation(ctx, calicoVersion, clusterType); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
const globalClusterInfoName = "default"
|
||||
|
||||
// ensureClusterInformation ensures that the ClusterInformation fields i.e. ClusterType,
|
||||
// CalicoVersion and ClusterGUID are set. It creates/updates the ClusterInformation as needed.
|
||||
func (c client) ensureClusterInformation(ctx context.Context, calicoVersion, clusterType string) error {
|
||||
// Append "kdd" last if the datastoreType is 'kubernetes'.
|
||||
if c.config.Spec.DatastoreType == apiconfig.Kubernetes {
|
||||
// If clusterType is already set then append ",kdd" at the end.
|
||||
if clusterType != "" {
|
||||
// Trim the trailing ",", if any.
|
||||
clusterType = strings.TrimSuffix(clusterType, ",")
|
||||
// Append "kdd" very last thing in the list.
|
||||
clusterType = fmt.Sprintf("%s,%s", clusterType, "kdd")
|
||||
} else {
|
||||
clusterType = "kdd"
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
clusterInfo, err := c.ClusterInformation().Get(ctx, globalClusterInfoName, options.GetOptions{})
|
||||
if err != nil {
|
||||
// Create the default config if it doesn't already exist.
|
||||
if _, ok := err.(cerrors.ErrorResourceDoesNotExist); ok {
|
||||
newClusterInfo := v3.NewClusterInformation()
|
||||
newClusterInfo.Name = globalClusterInfoName
|
||||
newClusterInfo.Spec.CalicoVersion = calicoVersion
|
||||
newClusterInfo.Spec.ClusterType = clusterType
|
||||
newClusterInfo.Spec.ClusterGUID = fmt.Sprintf("%s", hex.EncodeToString(uuid.NewV4().Bytes()))
|
||||
datastoreReady := true
|
||||
newClusterInfo.Spec.DatastoreReady = &datastoreReady
|
||||
_, err = c.ClusterInformation().Create(ctx, newClusterInfo, options.SetOptions{})
|
||||
if err != nil {
|
||||
if _, ok := err.(cerrors.ErrorResourceAlreadyExists); ok {
|
||||
log.Info("Failed to create global ClusterInformation; another node got there first.")
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
}
|
||||
log.WithError(err).WithField("ClusterInformation", newClusterInfo).Errorf("Error creating cluster information config")
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
log.WithError(err).WithField("ClusterInformation", globalClusterInfoName).Errorf("Error getting cluster information config")
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
updateNeeded := false
|
||||
if calicoVersion != "" {
|
||||
// Only update the version if it's different from what we have.
|
||||
if clusterInfo.Spec.CalicoVersion != calicoVersion {
|
||||
clusterInfo.Spec.CalicoVersion = calicoVersion
|
||||
updateNeeded = true
|
||||
} else {
|
||||
log.WithField("CalicoVersion", clusterInfo.Spec.CalicoVersion).Debug("Calico version value already assigned")
|
||||
}
|
||||
}
|
||||
|
||||
if clusterInfo.Spec.ClusterGUID == "" {
|
||||
clusterInfo.Spec.ClusterGUID = fmt.Sprintf("%s", hex.EncodeToString(uuid.NewV4().Bytes()))
|
||||
updateNeeded = true
|
||||
} else {
|
||||
log.WithField("ClusterGUID", clusterInfo.Spec.ClusterGUID).Debug("Cluster GUID value already set")
|
||||
}
|
||||
|
||||
if clusterInfo.Spec.DatastoreReady == nil {
|
||||
// If the ready flag is nil, default it to true (but if it's explicitly false, leave
|
||||
// it as-is).
|
||||
datastoreReady := true
|
||||
clusterInfo.Spec.DatastoreReady = &datastoreReady
|
||||
updateNeeded = true
|
||||
} else {
|
||||
log.WithField("DatastoreReady", clusterInfo.Spec.DatastoreReady).Debug("DatastoreReady value already set")
|
||||
}
|
||||
|
||||
if clusterType != "" {
|
||||
if clusterInfo.Spec.ClusterType == "" {
|
||||
clusterInfo.Spec.ClusterType = clusterType
|
||||
updateNeeded = true
|
||||
|
||||
} else {
|
||||
allClusterTypes := strings.Split(clusterInfo.Spec.ClusterType, ",")
|
||||
existingClusterTypes := set.FromArray(allClusterTypes)
|
||||
localClusterTypes := strings.Split(clusterType, ",")
|
||||
|
||||
clusterTypeUpdateNeeded := false
|
||||
for _, lct := range localClusterTypes {
|
||||
if existingClusterTypes.Contains(lct) {
|
||||
continue
|
||||
}
|
||||
clusterTypeUpdateNeeded = true
|
||||
allClusterTypes = append(allClusterTypes, lct)
|
||||
}
|
||||
|
||||
if clusterTypeUpdateNeeded {
|
||||
clusterInfo.Spec.ClusterType = strings.Join(allClusterTypes, ",")
|
||||
updateNeeded = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if updateNeeded {
|
||||
_, err = c.ClusterInformation().Update(ctx, clusterInfo, options.SetOptions{})
|
||||
if _, ok := err.(cerrors.ErrorResourceUpdateConflict); ok {
|
||||
log.WithError(err).WithField("ClusterInformation", clusterInfo).Warning(
|
||||
"Conflict while updating cluster information, may retry")
|
||||
time.Sleep(1 * time.Second)
|
||||
continue
|
||||
} else if err != nil {
|
||||
log.WithError(err).WithField("ClusterInformation", clusterInfo).Errorf(
|
||||
"Error updating cluster information")
|
||||
return err
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Backend returns the backend client used by the v3 client. Not exposed on the main
|
||||
// client API, but available publicly for consumers that require access to the backend
|
||||
// client (e.g. for syncer support).
|
||||
func (c client) Backend() bapi.Client {
|
||||
return c.backend
|
||||
}
|
||||
108
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/clusterinfo.go
generated
vendored
Normal file
108
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/clusterinfo.go
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) 2017 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// ClusterInformationInterface has methods to work with ClusterInformation resources.
|
||||
type ClusterInformationInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.ClusterInformation, opts options.SetOptions) (*apiv3.ClusterInformation, error)
|
||||
Update(ctx context.Context, res *apiv3.ClusterInformation, opts options.SetOptions) (*apiv3.ClusterInformation, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.ClusterInformation, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.ClusterInformation, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.ClusterInformationList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// clusterInformation implements ClusterInformationInterface
|
||||
type clusterInformation struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a ClusterInformation and creates it.
|
||||
// Returns the stored representation of the ClusterInformation, and an error
|
||||
// if there is any.
|
||||
func (r clusterInformation) Create(ctx context.Context, res *apiv3.ClusterInformation, opts options.SetOptions) (*apiv3.ClusterInformation, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if res.ObjectMeta.GetName() != "default" {
|
||||
return nil, errors.New("Cannot create a Cluster Information resource with a name other than \"default\"")
|
||||
}
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindClusterInformation, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.ClusterInformation), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a ClusterInformation and updates it.
|
||||
// Returns the stored representation of the ClusterInformation, and an error
|
||||
// if there is any.
|
||||
func (r clusterInformation) Update(ctx context.Context, res *apiv3.ClusterInformation, opts options.SetOptions) (*apiv3.ClusterInformation, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindClusterInformation, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.ClusterInformation), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the ClusterInformation and deletes it. Returns an
|
||||
// error if one occurs.
|
||||
func (r clusterInformation) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.ClusterInformation, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindClusterInformation, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.ClusterInformation), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the ClusterInformation, and returns the corresponding
|
||||
// ClusterInformation object, and an error if there is any.
|
||||
func (r clusterInformation) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.ClusterInformation, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindClusterInformation, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.ClusterInformation), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of ClusterInformation objects that match the supplied options.
|
||||
func (r clusterInformation) List(ctx context.Context, opts options.ListOptions) (*apiv3.ClusterInformationList, error) {
|
||||
res := &apiv3.ClusterInformationList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindClusterInformation, apiv3.KindClusterInformationList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the ClusterInformation that
|
||||
// match the supplied options.
|
||||
func (r clusterInformation) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindClusterInformation, nil)
|
||||
}
|
||||
38
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/doc.go
generated
vendored
Normal file
38
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/doc.go
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2018 Tigera, 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 client implements the northbound client used to manage Calico configuration.
|
||||
|
||||
This client is the main entry point for applications that are managing or querying
|
||||
Calico configuration.
|
||||
|
||||
This client provides a typed interface for managing different resource types. The
|
||||
definitions for each resource type are defined in the following package:
|
||||
github.com/projectcalico/libcalico-go/lib/api
|
||||
|
||||
The client has a number of methods that return interfaces for managing:
|
||||
- BGP Peer resources
|
||||
- Policy resources
|
||||
- IP Pool resources
|
||||
- Global network sets resources
|
||||
- Host endpoint resources
|
||||
- Workload endpoint resources
|
||||
- Profile resources
|
||||
- IP Address Management (IPAM)
|
||||
|
||||
See [resource definitions](http://docs.projectcalico.org/latest/reference/calicoctl/resources/) for details about the set of management commands for each
|
||||
resource type.
|
||||
*/
|
||||
package clientv3
|
||||
104
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/felixconfig.go
generated
vendored
Normal file
104
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/felixconfig.go
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2017 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// FelixConfigurationInterface has methods to work with FelixConfiguration resources.
|
||||
type FelixConfigurationInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.FelixConfiguration, opts options.SetOptions) (*apiv3.FelixConfiguration, error)
|
||||
Update(ctx context.Context, res *apiv3.FelixConfiguration, opts options.SetOptions) (*apiv3.FelixConfiguration, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.FelixConfiguration, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.FelixConfiguration, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.FelixConfigurationList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// felixConfigurations implements FelixConfigurationInterface
|
||||
type felixConfigurations struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a FelixConfiguration and creates it.
|
||||
// Returns the stored representation of the FelixConfiguration, and an error
|
||||
// if there is any.
|
||||
func (r felixConfigurations) Create(ctx context.Context, res *apiv3.FelixConfiguration, opts options.SetOptions) (*apiv3.FelixConfiguration, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindFelixConfiguration, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.FelixConfiguration), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a FelixConfiguration and updates it.
|
||||
// Returns the stored representation of the FelixConfiguration, and an error
|
||||
// if there is any.
|
||||
func (r felixConfigurations) Update(ctx context.Context, res *apiv3.FelixConfiguration, opts options.SetOptions) (*apiv3.FelixConfiguration, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindFelixConfiguration, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.FelixConfiguration), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the FelixConfiguration and deletes it. Returns an
|
||||
// error if one occurs.
|
||||
func (r felixConfigurations) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.FelixConfiguration, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindFelixConfiguration, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.FelixConfiguration), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the FelixConfiguration, and returns the corresponding
|
||||
// FelixConfiguration object, and an error if there is any.
|
||||
func (r felixConfigurations) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.FelixConfiguration, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindFelixConfiguration, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.FelixConfiguration), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of FelixConfiguration objects that match the supplied options.
|
||||
func (r felixConfigurations) List(ctx context.Context, opts options.ListOptions) (*apiv3.FelixConfigurationList, error) {
|
||||
res := &apiv3.FelixConfigurationList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindFelixConfiguration, apiv3.KindFelixConfigurationList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the FelixConfiguration that
|
||||
// match the supplied options.
|
||||
func (r felixConfigurations) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindFelixConfiguration, nil)
|
||||
}
|
||||
206
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/globalnetworkpolicy.go
generated
vendored
Normal file
206
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/globalnetworkpolicy.go
generated
vendored
Normal file
@@ -0,0 +1,206 @@
|
||||
// Copyright (c) 2017-2018 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// GlobalNetworkPolicyInterface has methods to work with GlobalNetworkPolicy resources.
|
||||
type GlobalNetworkPolicyInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.GlobalNetworkPolicy, opts options.SetOptions) (*apiv3.GlobalNetworkPolicy, error)
|
||||
Update(ctx context.Context, res *apiv3.GlobalNetworkPolicy, opts options.SetOptions) (*apiv3.GlobalNetworkPolicy, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.GlobalNetworkPolicy, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.GlobalNetworkPolicy, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.GlobalNetworkPolicyList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// globalNetworkPolicies implements GlobalNetworkPolicyInterface
|
||||
type globalNetworkPolicies struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a GlobalNetworkPolicy and creates it. Returns the stored
|
||||
// representation of the GlobalNetworkPolicy, and an error, if there is any.
|
||||
func (r globalNetworkPolicies) Create(ctx context.Context, res *apiv3.GlobalNetworkPolicy, opts options.SetOptions) (*apiv3.GlobalNetworkPolicy, error) {
|
||||
if res != nil {
|
||||
// Since we're about to default some fields, take a (shallow) copy of the input data
|
||||
// before we do so.
|
||||
resCopy := *res
|
||||
res = &resCopy
|
||||
}
|
||||
defaultPolicyTypesField(res.Spec.Ingress, res.Spec.Egress, &res.Spec.Types)
|
||||
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Properly prefix the name
|
||||
res.GetObjectMeta().SetName(convertPolicyNameForStorage(res.GetObjectMeta().GetName()))
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindGlobalNetworkPolicy, res)
|
||||
if out != nil {
|
||||
// Remove the prefix out of the returned policy name.
|
||||
out.GetObjectMeta().SetName(convertPolicyNameFromStorage(out.GetObjectMeta().GetName()))
|
||||
return out.(*apiv3.GlobalNetworkPolicy), err
|
||||
}
|
||||
|
||||
// Remove the prefix out of the returned policy name.
|
||||
res.GetObjectMeta().SetName(convertPolicyNameFromStorage(res.GetObjectMeta().GetName()))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a GlobalNetworkPolicy and updates it. Returns the stored
|
||||
// representation of the GlobalNetworkPolicy, and an error, if there is any.
|
||||
func (r globalNetworkPolicies) Update(ctx context.Context, res *apiv3.GlobalNetworkPolicy, opts options.SetOptions) (*apiv3.GlobalNetworkPolicy, error) {
|
||||
if res != nil {
|
||||
// Since we're about to default some fields, take a (shallow) copy of the input data
|
||||
// before we do so.
|
||||
resCopy := *res
|
||||
res = &resCopy
|
||||
}
|
||||
defaultPolicyTypesField(res.Spec.Ingress, res.Spec.Egress, &res.Spec.Types)
|
||||
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Properly prefix the name
|
||||
res.GetObjectMeta().SetName(convertPolicyNameForStorage(res.GetObjectMeta().GetName()))
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindGlobalNetworkPolicy, res)
|
||||
if out != nil {
|
||||
// Remove the prefix out of the returned policy name.
|
||||
out.GetObjectMeta().SetName(convertPolicyNameFromStorage(out.GetObjectMeta().GetName()))
|
||||
return out.(*apiv3.GlobalNetworkPolicy), err
|
||||
}
|
||||
|
||||
// Remove the prefix out of the returned policy name.
|
||||
res.GetObjectMeta().SetName(convertPolicyNameFromStorage(res.GetObjectMeta().GetName()))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the GlobalNetworkPolicy and deletes it. Returns an error if one occurs.
|
||||
func (r globalNetworkPolicies) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.GlobalNetworkPolicy, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindGlobalNetworkPolicy, noNamespace, convertPolicyNameForStorage(name))
|
||||
if out != nil {
|
||||
// Remove the prefix out of the returned policy name.
|
||||
out.GetObjectMeta().SetName(convertPolicyNameFromStorage(out.GetObjectMeta().GetName()))
|
||||
return out.(*apiv3.GlobalNetworkPolicy), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the GlobalNetworkPolicy, and returns the corresponding GlobalNetworkPolicy object,
|
||||
// and an error if there is any.
|
||||
func (r globalNetworkPolicies) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.GlobalNetworkPolicy, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindGlobalNetworkPolicy, noNamespace, convertPolicyNameForStorage(name))
|
||||
if out != nil {
|
||||
// Remove the prefix out of the returned policy name.
|
||||
out.GetObjectMeta().SetName(convertPolicyNameFromStorage(out.GetObjectMeta().GetName()))
|
||||
return out.(*apiv3.GlobalNetworkPolicy), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of GlobalNetworkPolicy objects that match the supplied options.
|
||||
func (r globalNetworkPolicies) List(ctx context.Context, opts options.ListOptions) (*apiv3.GlobalNetworkPolicyList, error) {
|
||||
res := &apiv3.GlobalNetworkPolicyList{}
|
||||
// Add the name prefix if name is provided
|
||||
if opts.Name != "" {
|
||||
opts.Name = convertPolicyNameForStorage(opts.Name)
|
||||
}
|
||||
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindGlobalNetworkPolicy, apiv3.KindGlobalNetworkPolicyList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Remove the prefix off of each policy name
|
||||
for i, _ := range res.Items {
|
||||
name := res.Items[i].GetObjectMeta().GetName()
|
||||
res.Items[i].GetObjectMeta().SetName(convertPolicyNameFromStorage(name))
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the globalNetworkPolicies that match the
|
||||
// supplied options.
|
||||
func (r globalNetworkPolicies) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
// Add the name prefix if name is provided
|
||||
if opts.Name != "" {
|
||||
opts.Name = convertPolicyNameForStorage(opts.Name)
|
||||
}
|
||||
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindGlobalNetworkPolicy, &policyConverter{})
|
||||
}
|
||||
|
||||
func defaultPolicyTypesField(ingressRules, egressRules []apiv3.Rule, types *[]apiv3.PolicyType) {
|
||||
if len(*types) == 0 {
|
||||
// Default the Types field according to what inbound and outbound rules are present
|
||||
// in the policy.
|
||||
if len(egressRules) == 0 {
|
||||
// Policy has no egress rules, so apply this policy to ingress only. (Note:
|
||||
// intentionally including the case where the policy also has no ingress
|
||||
// rules.)
|
||||
*types = []apiv3.PolicyType{apiv3.PolicyTypeIngress}
|
||||
} else if len(ingressRules) == 0 {
|
||||
// Policy has egress rules but no ingress rules, so apply this policy to
|
||||
// egress only.
|
||||
*types = []apiv3.PolicyType{apiv3.PolicyTypeEgress}
|
||||
} else {
|
||||
// Policy has both ingress and egress rules, so apply this policy to both
|
||||
// ingress and egress.
|
||||
*types = []apiv3.PolicyType{apiv3.PolicyTypeIngress, apiv3.PolicyTypeEgress}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func convertPolicyNameForStorage(name string) string {
|
||||
// Do nothing on names prefixed with "knp."
|
||||
if strings.HasPrefix(name, "knp.") {
|
||||
return name
|
||||
}
|
||||
// Similarly for "ossg."
|
||||
if strings.HasPrefix(name, "ossg.") {
|
||||
return name
|
||||
}
|
||||
return "default." + name
|
||||
}
|
||||
|
||||
func convertPolicyNameFromStorage(name string) string {
|
||||
// Do nothing on names prefixed with "knp."
|
||||
if strings.HasPrefix(name, "knp.") {
|
||||
return name
|
||||
}
|
||||
// Similarly for "ossg."
|
||||
if strings.HasPrefix(name, "ossg.") {
|
||||
return name
|
||||
}
|
||||
parts := strings.SplitN(name, ".", 2)
|
||||
return parts[len(parts)-1]
|
||||
}
|
||||
|
||||
type policyConverter struct{}
|
||||
|
||||
func (pc *policyConverter) Convert(r resource) resource {
|
||||
r.GetObjectMeta().SetName(convertPolicyNameFromStorage(r.GetObjectMeta().GetName()))
|
||||
return r
|
||||
}
|
||||
101
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/globalnetworkset.go
generated
vendored
Normal file
101
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/globalnetworkset.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2018 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// GlobalNetworkSetInterface has methods to work with GlobalNetworkSet resources.
|
||||
type GlobalNetworkSetInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.GlobalNetworkSet, opts options.SetOptions) (*apiv3.GlobalNetworkSet, error)
|
||||
Update(ctx context.Context, res *apiv3.GlobalNetworkSet, opts options.SetOptions) (*apiv3.GlobalNetworkSet, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.GlobalNetworkSet, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.GlobalNetworkSet, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.GlobalNetworkSetList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// globalNetworkSets implements GlobalNetworkSetInterface
|
||||
type globalNetworkSets struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a GlobalNetworkSet and creates it. Returns the stored
|
||||
// representation of the GlobalNetworkSet, and an error, if there is any.
|
||||
func (r globalNetworkSets) Create(ctx context.Context, res *apiv3.GlobalNetworkSet, opts options.SetOptions) (*apiv3.GlobalNetworkSet, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindGlobalNetworkSet, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.GlobalNetworkSet), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a GlobalNetworkSet and updates it. Returns the stored
|
||||
// representation of the GlobalNetworkSet, and an error, if there is any.
|
||||
func (r globalNetworkSets) Update(ctx context.Context, res *apiv3.GlobalNetworkSet, opts options.SetOptions) (*apiv3.GlobalNetworkSet, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindGlobalNetworkSet, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.GlobalNetworkSet), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the GlobalNetworkSet and deletes it. Returns an error if one occurs.
|
||||
func (r globalNetworkSets) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.GlobalNetworkSet, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindGlobalNetworkSet, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.GlobalNetworkSet), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the GlobalNetworkSet, and returns the corresponding GlobalNetworkSet object,
|
||||
// and an error if there is any.
|
||||
func (r globalNetworkSets) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.GlobalNetworkSet, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindGlobalNetworkSet, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.GlobalNetworkSet), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of GlobalNetworkSet objects that match the supplied options.
|
||||
func (r globalNetworkSets) List(ctx context.Context, opts options.ListOptions) (*apiv3.GlobalNetworkSetList, error) {
|
||||
res := &apiv3.GlobalNetworkSetList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindGlobalNetworkSet, apiv3.KindGlobalNetworkSetList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the GlobalNetworkSets that match the
|
||||
// supplied options.
|
||||
func (r globalNetworkSets) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindGlobalNetworkSet, nil)
|
||||
}
|
||||
101
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/hostendpoint.go
generated
vendored
Normal file
101
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/hostendpoint.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2017 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// HostEndpointInterface has methods to work with HostEndpoint resources.
|
||||
type HostEndpointInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.HostEndpoint, opts options.SetOptions) (*apiv3.HostEndpoint, error)
|
||||
Update(ctx context.Context, res *apiv3.HostEndpoint, opts options.SetOptions) (*apiv3.HostEndpoint, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.HostEndpoint, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.HostEndpoint, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.HostEndpointList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// hostEndpoints implements HostEndpointInterface
|
||||
type hostEndpoints struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a HostEndpoint and creates it. Returns the stored
|
||||
// representation of the HostEndpoint, and an error, if there is any.
|
||||
func (r hostEndpoints) Create(ctx context.Context, res *apiv3.HostEndpoint, opts options.SetOptions) (*apiv3.HostEndpoint, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindHostEndpoint, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.HostEndpoint), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a HostEndpoint and updates it. Returns the stored
|
||||
// representation of the HostEndpoint, and an error, if there is any.
|
||||
func (r hostEndpoints) Update(ctx context.Context, res *apiv3.HostEndpoint, opts options.SetOptions) (*apiv3.HostEndpoint, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindHostEndpoint, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.HostEndpoint), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the HostEndpoint and deletes it. Returns an error if one occurs.
|
||||
func (r hostEndpoints) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.HostEndpoint, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindHostEndpoint, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.HostEndpoint), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the HostEndpoint, and returns the corresponding HostEndpoint object,
|
||||
// and an error if there is any.
|
||||
func (r hostEndpoints) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.HostEndpoint, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindHostEndpoint, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.HostEndpoint), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of HostEndpoint objects that match the supplied options.
|
||||
func (r hostEndpoints) List(ctx context.Context, opts options.ListOptions) (*apiv3.HostEndpointList, error) {
|
||||
res := &apiv3.HostEndpointList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindHostEndpoint, apiv3.KindHostEndpointList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the HostEndpoints that match the
|
||||
// supplied options.
|
||||
func (r hostEndpoints) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindHostEndpoint, nil)
|
||||
}
|
||||
62
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/interface.go
generated
vendored
Normal file
62
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/interface.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2017-2019 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/projectcalico/libcalico-go/lib/ipam"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
// Nodes returns an interface for managing node resources.
|
||||
Nodes() NodeInterface
|
||||
// GlobalNetworkPolicies returns an interface for managing global network policy resources.
|
||||
GlobalNetworkPolicies() GlobalNetworkPolicyInterface
|
||||
// NetworkPolicies returns an interface for managing namespaced network policy resources.
|
||||
NetworkPolicies() NetworkPolicyInterface
|
||||
// IPPools returns an interface for managing IP pool resources.
|
||||
IPPools() IPPoolInterface
|
||||
// Profiles returns an interface for managing profile resources.
|
||||
Profiles() ProfileInterface
|
||||
// GlobalNetworkSets returns an interface for managing global network sets resources.
|
||||
GlobalNetworkSets() GlobalNetworkSetInterface
|
||||
// NetworkSets returns an interface for managing network sets resources.
|
||||
NetworkSets() NetworkSetInterface
|
||||
// HostEndpoints returns an interface for managing host endpoint resources.
|
||||
HostEndpoints() HostEndpointInterface
|
||||
// WorkloadEndpoints returns an interface for managing workload endpoint resources.
|
||||
WorkloadEndpoints() WorkloadEndpointInterface
|
||||
// BGPPeers returns an interface for managing BGP peer resources.
|
||||
BGPPeers() BGPPeerInterface
|
||||
// IPAM returns an interface for managing IP address assignment and releasing.
|
||||
IPAM() ipam.Interface
|
||||
// BGPConfigurations returns an interface for managing the BGP configuration resources.
|
||||
BGPConfigurations() BGPConfigurationInterface
|
||||
// FelixConfigurations returns an interface for managing the Felix configuration resources.
|
||||
FelixConfigurations() FelixConfigurationInterface
|
||||
// ClusterInformation returns an interface for managing the cluster information resource.
|
||||
ClusterInformation() ClusterInformationInterface
|
||||
// EnsureInitialized is used to ensure the backend datastore is correctly
|
||||
// initialized for use by Calico. This method may be called multiple times, and
|
||||
// will have no effect if the datastore is already correctly initialized.
|
||||
// Most Calico deployment scenarios will automatically implicitly invoke this
|
||||
// method and so a general consumer of this API can assume that the datastore
|
||||
// is already initialized.
|
||||
EnsureInitialized(ctx context.Context, calicoVersion, clusterType string) error
|
||||
}
|
||||
|
||||
// Compile-time assertion that our client implements its interface.
|
||||
var _ Interface = (*client)(nil)
|
||||
620
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/ippool.go
generated
vendored
Normal file
620
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/ippool.go
generated
vendored
Normal file
@@ -0,0 +1,620 @@
|
||||
// Copyright (c) 2017-2019 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/backend/model"
|
||||
cerrors "github.com/projectcalico/libcalico-go/lib/errors"
|
||||
cnet "github.com/projectcalico/libcalico-go/lib/net"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// IPPoolInterface has methods to work with IPPool resources.
|
||||
type IPPoolInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.IPPool, opts options.SetOptions) (*apiv3.IPPool, error)
|
||||
Update(ctx context.Context, res *apiv3.IPPool, opts options.SetOptions) (*apiv3.IPPool, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.IPPool, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.IPPool, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.IPPoolList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// ipPools implements IPPoolInterface
|
||||
type ipPools struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a IPPool and creates it. Returns the stored
|
||||
// representation of the IPPool, and an error, if there is any.
|
||||
func (r ipPools) Create(ctx context.Context, res *apiv3.IPPool, opts options.SetOptions) (*apiv3.IPPool, error) {
|
||||
if res != nil {
|
||||
// Since we're about to default some fields, take a (shallow) copy of the input data
|
||||
// before we do so.
|
||||
resCopy := *res
|
||||
res = &resCopy
|
||||
}
|
||||
// Validate the IPPool before creating the resource.
|
||||
if err := r.validateAndSetDefaults(ctx, res, nil); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Check that there are no existing blocks in the pool range that have a different block size.
|
||||
poolBlockSize := res.Spec.BlockSize
|
||||
poolIP, poolCIDR, err := net.ParseCIDR(res.Spec.CIDR)
|
||||
if err != nil {
|
||||
return nil, cerrors.ErrorParsingDatastoreEntry{
|
||||
RawKey: "CIDR",
|
||||
RawValue: string(res.Spec.CIDR),
|
||||
Err: err,
|
||||
}
|
||||
}
|
||||
|
||||
ipVersion := 4
|
||||
if poolIP.To4() == nil {
|
||||
ipVersion = 6
|
||||
}
|
||||
|
||||
blocks, err := r.client.backend.List(ctx, model.BlockListOptions{IPVersion: ipVersion}, "")
|
||||
if _, ok := err.(cerrors.ErrorOperationNotSupported); !ok && err != nil {
|
||||
// There was an error and it wasn't OperationNotSupported - return it.
|
||||
return nil, err
|
||||
} else if err == nil {
|
||||
// Skip the block check if the error is OperationUnsupported - listing blocks is not
|
||||
// supported with host-local IPAM on KDD.
|
||||
for _, b := range blocks.KVPairs {
|
||||
k := b.Key.(model.BlockKey)
|
||||
ones, _ := k.CIDR.Mask.Size()
|
||||
// Check if this block has a different size to the pool, and that it overlaps with the pool.
|
||||
if ones != poolBlockSize && k.CIDR.IsNetOverlap(*poolCIDR) {
|
||||
return nil, cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "IPPool.Spec.BlockSize",
|
||||
Reason: "IPPool blocksSize conflicts with existing allocations that use a different blockSize",
|
||||
Value: res.Spec.BlockSize,
|
||||
}},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Enable IPIP or VXLAN globally if required. Do this before the Create so if it fails the user
|
||||
// can retry the same command.
|
||||
err = r.maybeEnableIPIP(ctx, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = r.maybeEnableVXLAN(ctx, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindIPPool, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.IPPool), err
|
||||
}
|
||||
return nil, err
|
||||
|
||||
}
|
||||
|
||||
// Update takes the representation of a IPPool and updates it. Returns the stored
|
||||
// representation of the IPPool, and an error, if there is any.
|
||||
func (r ipPools) Update(ctx context.Context, res *apiv3.IPPool, opts options.SetOptions) (*apiv3.IPPool, error) {
|
||||
if res != nil {
|
||||
// Since we're about to default some fields, take a (shallow) copy of the input data
|
||||
// before we do so.
|
||||
resCopy := *res
|
||||
res = &resCopy
|
||||
}
|
||||
|
||||
// Get the existing settings, so that we can validate the CIDR and block size have not changed.
|
||||
old, err := r.Get(ctx, res.Name, options.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Validate the IPPool updating the resource.
|
||||
if err := r.validateAndSetDefaults(ctx, res, old); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Enable IPIP globally if required. Do this before the Update so if it fails the user
|
||||
// can retry the same command.
|
||||
err = r.maybeEnableIPIP(ctx, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = r.maybeEnableVXLAN(ctx, res)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindIPPool, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.IPPool), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the IPPool and deletes it. Returns an error if one occurs.
|
||||
func (r ipPools) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.IPPool, error) {
|
||||
// Deleting a pool requires a little care because of existing endpoints
|
||||
// using IP addresses allocated in the pool. We do the deletion in
|
||||
// the following steps:
|
||||
// - disable the pool so no more IPs are assigned from it
|
||||
// - remove all affinities associated with the pool
|
||||
// - delete the pool
|
||||
|
||||
// Get the pool so that we can find the CIDR associated with it.
|
||||
pool, err := r.Get(ctx, name, options.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logCxt := log.WithFields(log.Fields{
|
||||
"CIDR": pool.Spec.CIDR,
|
||||
"Name": name,
|
||||
})
|
||||
|
||||
// If the pool is active, set the disabled flag to ensure we stop allocating from this pool.
|
||||
if !pool.Spec.Disabled {
|
||||
logCxt.Info("Disabling pool to release affinities")
|
||||
pool.Spec.Disabled = true
|
||||
|
||||
// If the Delete has been called with a ResourceVersion then use that to perform the
|
||||
// update - that way we'll catch update conflicts (we could actually check here, but
|
||||
// the most likely scenario is there isn't one - so just pass it through and let the
|
||||
// Update handle any conflicts).
|
||||
if opts.ResourceVersion != "" {
|
||||
pool.ResourceVersion = opts.ResourceVersion
|
||||
}
|
||||
if _, err := r.Update(ctx, pool, options.SetOptions{}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Reset the resource version before the actual delete since the version of that resource
|
||||
// will now have been updated.
|
||||
opts.ResourceVersion = ""
|
||||
}
|
||||
|
||||
// Release affinities associated with this pool. We do this even if the pool was disabled
|
||||
// (since it may have been enabled at one time, and if there are no affine blocks created
|
||||
// then this will be a no-op). We've already validated the CIDR so we know it will parse.
|
||||
if _, cidrNet, err := cnet.ParseCIDR(pool.Spec.CIDR); err == nil {
|
||||
logCxt.Info("Releasing pool affinities")
|
||||
|
||||
// Pause for a short period before releasing the affinities - this gives any in-progress
|
||||
// allocations an opportunity to finish.
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
err = r.client.IPAM().ReleasePoolAffinities(ctx, *cidrNet)
|
||||
|
||||
// Depending on the datastore, IPAM may not be supported. If we get a not supported
|
||||
// error, then continue. Any other error, fail.
|
||||
if _, ok := err.(cerrors.ErrorOperationNotSupported); !ok && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// And finally, delete the pool.
|
||||
logCxt.Info("Deleting pool")
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindIPPool, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.IPPool), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the IPPool, and returns the corresponding IPPool object,
|
||||
// and an error if there is any.
|
||||
func (r ipPools) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.IPPool, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindIPPool, noNamespace, name)
|
||||
if out != nil {
|
||||
convertIpPoolFromStorage(out.(*apiv3.IPPool))
|
||||
return out.(*apiv3.IPPool), err
|
||||
}
|
||||
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of IPPool objects that match the supplied options.
|
||||
func (r ipPools) List(ctx context.Context, opts options.ListOptions) (*apiv3.IPPoolList, error) {
|
||||
res := &apiv3.IPPoolList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindIPPool, apiv3.KindIPPoolList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Default values when reading from backend.
|
||||
for i := range res.Items {
|
||||
convertIpPoolFromStorage(&res.Items[i])
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Default pool values when reading from storage
|
||||
func convertIpPoolFromStorage(pool *apiv3.IPPool) error {
|
||||
// Default the blockSize if it wasn't previously set
|
||||
if pool.Spec.BlockSize == 0 {
|
||||
// Get the IP address of the CIDR to find the IP version
|
||||
ipAddr, _, err := cnet.ParseCIDR(pool.Spec.CIDR)
|
||||
if err != nil {
|
||||
return cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: "IPPool CIDR must be a valid subnet",
|
||||
Value: pool.Spec.CIDR,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
if ipAddr.Version() == 4 {
|
||||
pool.Spec.BlockSize = 26
|
||||
} else {
|
||||
pool.Spec.BlockSize = 122
|
||||
}
|
||||
}
|
||||
|
||||
// Default the nodeSelector if it wasn't previously set.
|
||||
if pool.Spec.NodeSelector == "" {
|
||||
pool.Spec.NodeSelector = "all()"
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the IPPools that match the
|
||||
// supplied options.
|
||||
func (r ipPools) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindIPPool, nil)
|
||||
}
|
||||
|
||||
// validateAndSetDefaults validates IPPool fields and sets default values that are
|
||||
// not assigned.
|
||||
// The old pool will be unassigned for a Create.
|
||||
func (r ipPools) validateAndSetDefaults(ctx context.Context, new, old *apiv3.IPPool) error {
|
||||
errFields := []cerrors.ErroredField{}
|
||||
|
||||
// Spec.CIDR field must not be empty.
|
||||
if new.Spec.CIDR == "" {
|
||||
return cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: "IPPool CIDR must be specified",
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the CIDR is parsable.
|
||||
ipAddr, cidr, err := cnet.ParseCIDR(new.Spec.CIDR)
|
||||
if err != nil {
|
||||
return cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: "IPPool CIDR must be a valid subnet",
|
||||
Value: new.Spec.CIDR,
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
// Normalize the CIDR before persisting.
|
||||
new.Spec.CIDR = cidr.String()
|
||||
|
||||
// If a nodeSelector is not specified, then this IP pool selects all nodes.
|
||||
if new.Spec.NodeSelector == "" {
|
||||
new.Spec.NodeSelector = "all()"
|
||||
}
|
||||
|
||||
// If there was a previous pool then this must be an Update, validate that the
|
||||
// CIDR has not changed. Since we are using normalized CIDRs we can just do a
|
||||
// simple string comparison.
|
||||
if old != nil && old.Spec.CIDR != new.Spec.CIDR {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: "IPPool CIDR cannot be modified",
|
||||
Value: new.Spec.CIDR,
|
||||
})
|
||||
}
|
||||
|
||||
// Default the blockSize
|
||||
if new.Spec.BlockSize == 0 {
|
||||
if ipAddr.Version() == 4 {
|
||||
new.Spec.BlockSize = 26
|
||||
} else {
|
||||
new.Spec.BlockSize = 122
|
||||
}
|
||||
}
|
||||
|
||||
// Check that the blockSize hasn't changed since updates are not supported.
|
||||
if old != nil && old.Spec.BlockSize != new.Spec.BlockSize {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.BlockSize",
|
||||
Reason: "IPPool BlockSize cannot be modified",
|
||||
Value: new.Spec.BlockSize,
|
||||
})
|
||||
}
|
||||
|
||||
if ipAddr.Version() == 4 {
|
||||
if new.Spec.BlockSize > 32 || new.Spec.BlockSize < 20 {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.BlockSize",
|
||||
Reason: "IPv4 block size must be between 20 and 32",
|
||||
Value: new.Spec.BlockSize,
|
||||
})
|
||||
|
||||
}
|
||||
} else {
|
||||
if new.Spec.BlockSize > 128 || new.Spec.BlockSize < 116 {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.BlockSize",
|
||||
Reason: "IPv6 block size must be between 116 and 128",
|
||||
Value: new.Spec.BlockSize,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// The Calico IPAM places restrictions on the minimum IP pool size. If
|
||||
// the ippool is enabled, check that the pool is at least the minimum size.
|
||||
if !new.Spec.Disabled {
|
||||
ones, _ := cidr.Mask.Size()
|
||||
log.Debugf("Pool CIDR: %s, mask: %d, blockSize: %d", cidr.String(), ones, new.Spec.BlockSize)
|
||||
if ones > new.Spec.BlockSize {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: "IP pool size is too small for use with Calico IPAM. It must be equal to or greater than the block size.",
|
||||
Value: new.Spec.CIDR,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// If there was no previous pool then this must be a Create. Check that the CIDR
|
||||
// does not overlap with any other pool CIDRs.
|
||||
if old == nil {
|
||||
allPools, err := r.List(ctx, options.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, otherPool := range allPools.Items {
|
||||
// It's possible that Create is called for a pre-existing pool, so skip our own
|
||||
// pool and let the generic processing handle the pre-existing resource error case.
|
||||
if otherPool.Name == new.Name {
|
||||
continue
|
||||
}
|
||||
_, otherCIDR, err := cnet.ParseCIDR(otherPool.Spec.CIDR)
|
||||
if err != nil {
|
||||
log.WithField("Name", otherPool.Name).WithError(err).Error("IPPool is configured with an invalid CIDR")
|
||||
continue
|
||||
}
|
||||
if otherCIDR.IsNetOverlap(cidr.IPNet) {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: fmt.Sprintf("IPPool(%s) CIDR overlaps with IPPool(%s) CIDR %s", new.Name, otherPool.Name, otherPool.Spec.CIDR),
|
||||
Value: new.Spec.CIDR,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure IPIPMode is defaulted to "Never".
|
||||
if len(new.Spec.IPIPMode) == 0 {
|
||||
new.Spec.IPIPMode = apiv3.IPIPModeNever
|
||||
}
|
||||
|
||||
// Make sure VXLANMode is defaulted to "Never".
|
||||
if len(new.Spec.VXLANMode) == 0 {
|
||||
new.Spec.VXLANMode = apiv3.VXLANModeNever
|
||||
}
|
||||
|
||||
// Make sure only one of VXLAN and IPIP is enabled.
|
||||
if new.Spec.VXLANMode != apiv3.VXLANModeNever && new.Spec.IPIPMode != apiv3.IPIPModeNever {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.VXLANMode",
|
||||
Reason: "Cannot enable both VXLAN and IPIP on the same IPPool",
|
||||
Value: new.Spec.VXLANMode,
|
||||
})
|
||||
}
|
||||
|
||||
// IPIP cannot be enabled for IPv6.
|
||||
if cidr.Version() == 6 && new.Spec.IPIPMode != apiv3.IPIPModeNever {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.IPIPMode",
|
||||
Reason: "IPIP is not supported on an IPv6 IP pool",
|
||||
Value: new.Spec.IPIPMode,
|
||||
})
|
||||
}
|
||||
|
||||
// The Calico CIDR should be strictly masked
|
||||
log.Debugf("IPPool CIDR: %s, Masked IP: %d", new.Spec.CIDR, cidr.IP)
|
||||
if cidr.IP.String() != ipAddr.String() {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: "IPPool CIDR is not strictly masked",
|
||||
Value: new.Spec.CIDR,
|
||||
})
|
||||
}
|
||||
|
||||
// IPv4 link local subnet.
|
||||
ipv4LinkLocalNet := net.IPNet{
|
||||
IP: net.ParseIP("169.254.0.0"),
|
||||
Mask: net.CIDRMask(16, 32),
|
||||
}
|
||||
// IPv6 link local subnet.
|
||||
ipv6LinkLocalNet := net.IPNet{
|
||||
IP: net.ParseIP("fe80::"),
|
||||
Mask: net.CIDRMask(10, 128),
|
||||
}
|
||||
|
||||
// IP Pool CIDR cannot overlap with IPv4 or IPv6 link local address range.
|
||||
if cidr.Version() == 4 && cidr.IsNetOverlap(ipv4LinkLocalNet) {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: "IPPool CIDR overlaps with IPv4 Link Local range 169.254.0.0/16",
|
||||
Value: new.Spec.CIDR,
|
||||
})
|
||||
}
|
||||
|
||||
if cidr.Version() == 6 && cidr.IsNetOverlap(ipv6LinkLocalNet) {
|
||||
errFields = append(errFields, cerrors.ErroredField{
|
||||
Name: "IPPool.Spec.CIDR",
|
||||
Reason: "IPPool CIDR overlaps with IPv6 Link Local range fe80::/10",
|
||||
Value: new.Spec.CIDR,
|
||||
})
|
||||
}
|
||||
|
||||
// Return the errors if we have one or more validation errors.
|
||||
if len(errFields) > 0 {
|
||||
return cerrors.ErrorValidation{
|
||||
ErroredFields: errFields,
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// maybeEnableIPIP enables global IPIP if a default setting is not already configured
|
||||
// and the pool has IPIP enabled.
|
||||
func (c ipPools) maybeEnableIPIP(ctx context.Context, pool *apiv3.IPPool) error {
|
||||
if pool.Spec.IPIPMode == apiv3.IPIPModeNever {
|
||||
log.Debug("IPIP is not enabled for this pool - no need to check global setting")
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
ipEnabled := true
|
||||
for i := 0; i < maxApplyRetries; i++ {
|
||||
log.WithField("Retry", i).Debug("Checking global IPIP setting")
|
||||
res, err := c.client.FelixConfigurations().Get(ctx, "default", options.GetOptions{})
|
||||
if _, ok := err.(cerrors.ErrorResourceDoesNotExist); !ok && err != nil {
|
||||
log.WithError(err).Debug("Error getting current FelixConfiguration resource")
|
||||
return err
|
||||
}
|
||||
|
||||
if res == nil {
|
||||
log.Debug("Global FelixConfiguration does not exist - creating")
|
||||
res = apiv3.NewFelixConfiguration()
|
||||
res.Name = "default"
|
||||
} else if res.Spec.IPIPEnabled != nil {
|
||||
// A value for the default config is set so leave unchanged. It may be set to false,
|
||||
// so log the actual value - but we shouldn't update it if someone has explicitly
|
||||
// disabled it globally.
|
||||
log.WithField("IPIPEnabled", res.Spec.IPIPEnabled).Debug("Global IPIPEnabled setting is already configured")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enable IpInIp and do the Create or Update.
|
||||
res.Spec.IPIPEnabled = &ipEnabled
|
||||
if res.ResourceVersion == "" {
|
||||
res, err = c.client.FelixConfigurations().Create(ctx, res, options.SetOptions{})
|
||||
if _, ok := err.(cerrors.ErrorResourceAlreadyExists); ok {
|
||||
log.Debug("FelixConfiguration already exists - retry update")
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
res, err = c.client.FelixConfigurations().Update(ctx, res, options.SetOptions{})
|
||||
if _, ok := err.(cerrors.ErrorResourceUpdateConflict); ok {
|
||||
log.Debug("FelixConfiguration update conflict - retry update")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
log.Debug("FelixConfiguration updated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.WithError(err).Debug("Error updating FelixConfiguration to enable IPIP")
|
||||
return err
|
||||
}
|
||||
|
||||
// Return the error from the final Update.
|
||||
log.WithError(err).Info("Too many conflict failures attempting to update FelixConfiguration to enable IPIP")
|
||||
return err
|
||||
}
|
||||
|
||||
// maybeEnableVXLAN enables global VXLAN if a default setting is not already configured
|
||||
// and the pool has VXLAN enabled.
|
||||
func (c ipPools) maybeEnableVXLAN(ctx context.Context, pool *apiv3.IPPool) error {
|
||||
if pool.Spec.VXLANMode == apiv3.VXLANModeNever {
|
||||
log.Debug("VXLAN is not enabled for this pool - no need to check global setting")
|
||||
return nil
|
||||
}
|
||||
|
||||
var err error
|
||||
ipEnabled := true
|
||||
for i := 0; i < maxApplyRetries; i++ {
|
||||
log.WithField("Retry", i).Debug("Checking global VXLAN setting")
|
||||
res, err := c.client.FelixConfigurations().Get(ctx, "default", options.GetOptions{})
|
||||
if _, ok := err.(cerrors.ErrorResourceDoesNotExist); !ok && err != nil {
|
||||
log.WithError(err).Debug("Error getting current FelixConfiguration resource")
|
||||
return err
|
||||
}
|
||||
|
||||
if res == nil {
|
||||
log.Debug("Global FelixConfiguration does not exist - creating")
|
||||
res = apiv3.NewFelixConfiguration()
|
||||
res.Name = "default"
|
||||
} else if res.Spec.VXLANEnabled != nil {
|
||||
// A value for the default config is set so leave unchanged. It may be set to false,
|
||||
// so log the actual value - but we shouldn't update it if someone has explicitly
|
||||
// disabled it globally.
|
||||
log.WithField("VXLANEnabled", res.Spec.VXLANEnabled).Debug("Global VXLANEnabled setting is already configured")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Enable IpInIp and do the Create or Update.
|
||||
res.Spec.VXLANEnabled = &ipEnabled
|
||||
if res.ResourceVersion == "" {
|
||||
res, err = c.client.FelixConfigurations().Create(ctx, res, options.SetOptions{})
|
||||
if _, ok := err.(cerrors.ErrorResourceAlreadyExists); ok {
|
||||
log.Debug("FelixConfiguration already exists - retry update")
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
res, err = c.client.FelixConfigurations().Update(ctx, res, options.SetOptions{})
|
||||
if _, ok := err.(cerrors.ErrorResourceUpdateConflict); ok {
|
||||
log.Debug("FelixConfiguration update conflict - retry update")
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
log.Debug("FelixConfiguration updated successfully")
|
||||
return nil
|
||||
}
|
||||
|
||||
log.WithError(err).Debug("Error updating FelixConfiguration to enable VXLAN")
|
||||
return err
|
||||
}
|
||||
|
||||
// Return the error from the final Update.
|
||||
log.WithError(err).Info("Too many conflict failures attempting to update FelixConfiguration to enable VXLAN")
|
||||
return err
|
||||
}
|
||||
152
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/networkpolicy.go
generated
vendored
Normal file
152
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/networkpolicy.go
generated
vendored
Normal file
@@ -0,0 +1,152 @@
|
||||
// Copyright (c) 2017-2018 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// NetworkPolicyInterface has methods to work with NetworkPolicy resources.
|
||||
type NetworkPolicyInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.NetworkPolicy, opts options.SetOptions) (*apiv3.NetworkPolicy, error)
|
||||
Update(ctx context.Context, res *apiv3.NetworkPolicy, opts options.SetOptions) (*apiv3.NetworkPolicy, error)
|
||||
Delete(ctx context.Context, namespace, name string, opts options.DeleteOptions) (*apiv3.NetworkPolicy, error)
|
||||
Get(ctx context.Context, namespace, name string, opts options.GetOptions) (*apiv3.NetworkPolicy, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.NetworkPolicyList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// networkPolicies implements NetworkPolicyInterface
|
||||
type networkPolicies struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a NetworkPolicy and creates it. Returns the stored
|
||||
// representation of the NetworkPolicy, and an error, if there is any.
|
||||
func (r networkPolicies) Create(ctx context.Context, res *apiv3.NetworkPolicy, opts options.SetOptions) (*apiv3.NetworkPolicy, error) {
|
||||
if res != nil {
|
||||
// Since we're about to default some fields, take a (shallow) copy of the input data
|
||||
// before we do so.
|
||||
resCopy := *res
|
||||
res = &resCopy
|
||||
}
|
||||
defaultPolicyTypesField(res.Spec.Ingress, res.Spec.Egress, &res.Spec.Types)
|
||||
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Properly prefix the name
|
||||
res.GetObjectMeta().SetName(convertPolicyNameForStorage(res.GetObjectMeta().GetName()))
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindNetworkPolicy, res)
|
||||
if out != nil {
|
||||
// Remove the prefix out of the returned policy name.
|
||||
out.GetObjectMeta().SetName(convertPolicyNameFromStorage(out.GetObjectMeta().GetName()))
|
||||
return out.(*apiv3.NetworkPolicy), err
|
||||
}
|
||||
|
||||
// Remove the prefix out of the returned policy name.
|
||||
res.GetObjectMeta().SetName(convertPolicyNameFromStorage(res.GetObjectMeta().GetName()))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a NetworkPolicy and updates it. Returns the stored
|
||||
// representation of the NetworkPolicy, and an error, if there is any.
|
||||
func (r networkPolicies) Update(ctx context.Context, res *apiv3.NetworkPolicy, opts options.SetOptions) (*apiv3.NetworkPolicy, error) {
|
||||
if res != nil {
|
||||
// Since we're about to default some fields, take a (shallow) copy of the input data
|
||||
// before we do so.
|
||||
resCopy := *res
|
||||
res = &resCopy
|
||||
}
|
||||
defaultPolicyTypesField(res.Spec.Ingress, res.Spec.Egress, &res.Spec.Types)
|
||||
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Properly prefix the name
|
||||
res.GetObjectMeta().SetName(convertPolicyNameForStorage(res.GetObjectMeta().GetName()))
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindNetworkPolicy, res)
|
||||
if out != nil {
|
||||
// Remove the prefix out of the returned policy name.
|
||||
out.GetObjectMeta().SetName(convertPolicyNameFromStorage(out.GetObjectMeta().GetName()))
|
||||
return out.(*apiv3.NetworkPolicy), err
|
||||
}
|
||||
|
||||
// Remove the prefix out of the returned policy name.
|
||||
res.GetObjectMeta().SetName(convertPolicyNameFromStorage(res.GetObjectMeta().GetName()))
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the NetworkPolicy and deletes it. Returns an error if one occurs.
|
||||
func (r networkPolicies) Delete(ctx context.Context, namespace, name string, opts options.DeleteOptions) (*apiv3.NetworkPolicy, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindNetworkPolicy, namespace, convertPolicyNameForStorage(name))
|
||||
if out != nil {
|
||||
// Remove the prefix out of the returned policy name.
|
||||
out.GetObjectMeta().SetName(convertPolicyNameFromStorage(out.GetObjectMeta().GetName()))
|
||||
return out.(*apiv3.NetworkPolicy), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the NetworkPolicy, and returns the corresponding NetworkPolicy object,
|
||||
// and an error if there is any.
|
||||
func (r networkPolicies) Get(ctx context.Context, namespace, name string, opts options.GetOptions) (*apiv3.NetworkPolicy, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindNetworkPolicy, namespace, convertPolicyNameForStorage(name))
|
||||
if out != nil {
|
||||
// Remove the prefix out of the returned policy name.
|
||||
out.GetObjectMeta().SetName(convertPolicyNameFromStorage(out.GetObjectMeta().GetName()))
|
||||
return out.(*apiv3.NetworkPolicy), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of NetworkPolicy objects that match the supplied options.
|
||||
func (r networkPolicies) List(ctx context.Context, opts options.ListOptions) (*apiv3.NetworkPolicyList, error) {
|
||||
res := &apiv3.NetworkPolicyList{}
|
||||
// Add the name prefix if name is provided
|
||||
if opts.Name != "" {
|
||||
opts.Name = convertPolicyNameForStorage(opts.Name)
|
||||
}
|
||||
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindNetworkPolicy, apiv3.KindNetworkPolicyList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Remove the prefix off of each policy name
|
||||
for i, _ := range res.Items {
|
||||
name := res.Items[i].GetObjectMeta().GetName()
|
||||
res.Items[i].GetObjectMeta().SetName(convertPolicyNameFromStorage(name))
|
||||
}
|
||||
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the NetworkPolicies that match the
|
||||
// supplied options.
|
||||
func (r networkPolicies) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
// Add the name prefix if name is provided
|
||||
if opts.Name != "" {
|
||||
opts.Name = convertPolicyNameForStorage(opts.Name)
|
||||
}
|
||||
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindNetworkPolicy, &policyConverter{})
|
||||
}
|
||||
99
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/networkset.go
generated
vendored
Normal file
99
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/networkset.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright (c) 2018-2019 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// NetworkSetInterface has methods to work with NetworkSet resources.
|
||||
type NetworkSetInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.NetworkSet, opts options.SetOptions) (*apiv3.NetworkSet, error)
|
||||
Update(ctx context.Context, res *apiv3.NetworkSet, opts options.SetOptions) (*apiv3.NetworkSet, error)
|
||||
Delete(ctx context.Context, namespace, name string, opts options.DeleteOptions) (*apiv3.NetworkSet, error)
|
||||
Get(ctx context.Context, namespace, name string, opts options.GetOptions) (*apiv3.NetworkSet, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.NetworkSetList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// networkSets implements NetworkSetInterface
|
||||
type networkSets struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a NetworkSet and creates it. Returns the stored
|
||||
// representation of the NetworkSet, and an error, if there is any.
|
||||
func (r networkSets) Create(ctx context.Context, res *apiv3.NetworkSet, opts options.SetOptions) (*apiv3.NetworkSet, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindNetworkSet, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.NetworkSet), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a NetworkSet and updates it. Returns the stored
|
||||
// representation of the NetworkSet, and an error, if there is any.
|
||||
func (r networkSets) Update(ctx context.Context, res *apiv3.NetworkSet, opts options.SetOptions) (*apiv3.NetworkSet, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindNetworkSet, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.NetworkSet), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the NetworkSet and deletes it. Returns an error if one occurs.
|
||||
func (r networkSets) Delete(ctx context.Context, namespace, name string, opts options.DeleteOptions) (*apiv3.NetworkSet, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindNetworkSet, namespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.NetworkSet), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the NetworkSet, and returns the corresponding NetworkSet object,
|
||||
// and an error if there is any.
|
||||
func (r networkSets) Get(ctx context.Context, namespace, name string, opts options.GetOptions) (*apiv3.NetworkSet, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindNetworkSet, namespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.NetworkSet), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of NetworkSet objects that match the supplied options.
|
||||
func (r networkSets) List(ctx context.Context, opts options.ListOptions) (*apiv3.NetworkSetList, error) {
|
||||
res := &apiv3.NetworkSetList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindNetworkSet, apiv3.KindNetworkSetList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the NetworkSets that match the
|
||||
// supplied options.
|
||||
func (r networkSets) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindNetworkSet, nil)
|
||||
}
|
||||
212
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/node.go
generated
vendored
Normal file
212
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/node.go
generated
vendored
Normal file
@@ -0,0 +1,212 @@
|
||||
// Copyright (c) 2017 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"fmt"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/errors"
|
||||
"github.com/projectcalico/libcalico-go/lib/names"
|
||||
"github.com/projectcalico/libcalico-go/lib/net"
|
||||
cnet "github.com/projectcalico/libcalico-go/lib/net"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// NodeInterface has methods to work with Node resources.
|
||||
type NodeInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.Node, opts options.SetOptions) (*apiv3.Node, error)
|
||||
Update(ctx context.Context, res *apiv3.Node, opts options.SetOptions) (*apiv3.Node, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.Node, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.Node, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.NodeList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// nodes implements NodeInterface
|
||||
type nodes struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a Node and creates it. Returns the stored
|
||||
// representation of the Node, and an error, if there is any.
|
||||
func (r nodes) Create(ctx context.Context, res *apiv3.Node, opts options.SetOptions) (*apiv3.Node, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// For host-protection only clusters, we instruct the user to create a Node as the first
|
||||
// operation. Piggy-back the datastore initialisation on that to ensure the Ready flag gets
|
||||
// set. Since we're likely being called from calicoctl, we don't know the Calico version.
|
||||
err := r.client.EnsureInitialized(ctx, "", "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindNode, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.Node), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a Node and updates it. Returns the stored
|
||||
// representation of the Node, and an error, if there is any.
|
||||
func (r nodes) Update(ctx context.Context, res *apiv3.Node, opts options.SetOptions) (*apiv3.Node, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindNode, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.Node), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the Node and deletes it. Returns an error if one occurs.
|
||||
func (r nodes) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.Node, error) {
|
||||
pname, err := names.WorkloadEndpointIdentifiers{Node: name}.CalculateWorkloadEndpointName(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get all weps belonging to the node
|
||||
weps, err := r.client.WorkloadEndpoints().List(ctx, options.ListOptions{
|
||||
Prefix: true,
|
||||
Name: pname,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Collate all IPs across all endpoints, and then release those IPs.
|
||||
ips := []net.IP{}
|
||||
for _, wep := range weps.Items {
|
||||
// The prefix match is unfortunately not a perfect match on the Node (since it is theoretically possible for
|
||||
// another node to match the prefix (e.g. a node name of the format <thisnode>-foobar would also match a prefix
|
||||
// search of the node <thisnode>). Therefore, we will also need to check that the Spec.Node field matches the Node.
|
||||
if wep.Spec.Node != name {
|
||||
continue
|
||||
}
|
||||
for _, ip := range wep.Spec.IPNetworks {
|
||||
ipAddr, _, err := cnet.ParseCIDROrIP(ip)
|
||||
if err == nil {
|
||||
ips = append(ips, *ipAddr)
|
||||
} else {
|
||||
// Validation for wep insists upon CIDR, so we should always succeed
|
||||
log.WithError(err).Warnf("Failed to parse CIDR: %s", ip)
|
||||
}
|
||||
}
|
||||
}
|
||||
_, err = r.client.IPAM().ReleaseIPs(context.Background(), ips)
|
||||
switch err.(type) {
|
||||
case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete the weps.
|
||||
for _, wep := range weps.Items {
|
||||
if wep.Spec.Node != name {
|
||||
continue
|
||||
}
|
||||
|
||||
_, err = r.client.WorkloadEndpoints().Delete(ctx, wep.Namespace, wep.Name, options.DeleteOptions{})
|
||||
switch err.(type) {
|
||||
case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the node from the IPAM data if it exists.
|
||||
err = r.client.IPAM().RemoveIPAMHost(ctx, name)
|
||||
switch err.(type) {
|
||||
case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Remove BGPPeers.
|
||||
bgpPeers, err := r.client.BGPPeers().List(ctx, options.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, peer := range bgpPeers.Items {
|
||||
if peer.Spec.Node != name {
|
||||
continue
|
||||
}
|
||||
_, err = r.client.BGPPeers().Delete(ctx, peer.Name, options.DeleteOptions{})
|
||||
switch err.(type) {
|
||||
case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Delete felix configuration
|
||||
nodeConfName := fmt.Sprintf("node.%s", name)
|
||||
_, err = r.client.FelixConfigurations().Delete(ctx, nodeConfName, options.DeleteOptions{})
|
||||
switch err.(type) {
|
||||
case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete bgp configuration
|
||||
_, err = r.client.BGPConfigurations().Delete(ctx, nodeConfName, options.DeleteOptions{})
|
||||
switch err.(type) {
|
||||
case nil, errors.ErrorResourceDoesNotExist, errors.ErrorOperationNotSupported:
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete the node.
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindNode, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.Node), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the Node, and returns the corresponding Node object,
|
||||
// and an error if there is any.
|
||||
func (r nodes) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.Node, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindNode, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.Node), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of Node objects that match the supplied options.
|
||||
func (r nodes) List(ctx context.Context, opts options.ListOptions) (*apiv3.NodeList, error) {
|
||||
res := &apiv3.NodeList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindNode, apiv3.KindNodeList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the Nodes that match the
|
||||
// supplied options.
|
||||
func (r nodes) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindNode, nil)
|
||||
}
|
||||
101
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/profile.go
generated
vendored
Normal file
101
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/profile.go
generated
vendored
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2017 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// ProfileInterface has methods to work with Profile resources.
|
||||
type ProfileInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.Profile, opts options.SetOptions) (*apiv3.Profile, error)
|
||||
Update(ctx context.Context, res *apiv3.Profile, opts options.SetOptions) (*apiv3.Profile, error)
|
||||
Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.Profile, error)
|
||||
Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.Profile, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.ProfileList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// profiles implements ProfileInterface
|
||||
type profiles struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a Profile and creates it. Returns the stored
|
||||
// representation of the Profile, and an error, if there is any.
|
||||
func (r profiles) Create(ctx context.Context, res *apiv3.Profile, opts options.SetOptions) (*apiv3.Profile, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindProfile, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.Profile), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a Profile and updates it. Returns the stored
|
||||
// representation of the Profile, and an error, if there is any.
|
||||
func (r profiles) Update(ctx context.Context, res *apiv3.Profile, opts options.SetOptions) (*apiv3.Profile, error) {
|
||||
if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindProfile, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.Profile), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the Profile and deletes it. Returns an error if one occurs.
|
||||
func (r profiles) Delete(ctx context.Context, name string, opts options.DeleteOptions) (*apiv3.Profile, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindProfile, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.Profile), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the Profile, and returns the corresponding Profile object,
|
||||
// and an error if there is any.
|
||||
func (r profiles) Get(ctx context.Context, name string, opts options.GetOptions) (*apiv3.Profile, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindProfile, noNamespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.Profile), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of Profile objects that match the supplied options.
|
||||
func (r profiles) List(ctx context.Context, opts options.ListOptions) (*apiv3.ProfileList, error) {
|
||||
res := &apiv3.ProfileList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindProfile, apiv3.KindProfileList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the Profiles that match the
|
||||
// supplied options.
|
||||
func (r profiles) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindProfile, nil)
|
||||
}
|
||||
434
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/resources.go
generated
vendored
Normal file
434
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/resources.go
generated
vendored
Normal file
@@ -0,0 +1,434 @@
|
||||
// Copyright (c) 2017 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync/atomic"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
bapi "github.com/projectcalico/libcalico-go/lib/backend/api"
|
||||
"github.com/projectcalico/libcalico-go/lib/backend/model"
|
||||
cerrors "github.com/projectcalico/libcalico-go/lib/errors"
|
||||
"github.com/projectcalico/libcalico-go/lib/namespace"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
const (
|
||||
noNamespace = ""
|
||||
defaultNamespace = "default"
|
||||
maxApplyRetries = 10
|
||||
)
|
||||
|
||||
// All Calico resources implement the resource interface.
|
||||
type resource interface {
|
||||
runtime.Object
|
||||
v1.ObjectMetaAccessor
|
||||
}
|
||||
|
||||
// All Calico resource lists implement the resourceList interface.
|
||||
type resourceList interface {
|
||||
runtime.Object
|
||||
v1.ListMetaAccessor
|
||||
}
|
||||
|
||||
// resourceInterface has methods to work with generic resource types.
|
||||
type resourceInterface interface {
|
||||
Create(ctx context.Context, opts options.SetOptions, kind string, in resource) (resource, error)
|
||||
Update(ctx context.Context, opts options.SetOptions, kind string, in resource) (resource, error)
|
||||
Delete(ctx context.Context, opts options.DeleteOptions, kind, ns, name string) (resource, error)
|
||||
Get(ctx context.Context, opts options.GetOptions, kind, ns, name string) (resource, error)
|
||||
List(ctx context.Context, opts options.ListOptions, kind, listkind string, inout resourceList) error
|
||||
Watch(ctx context.Context, opts options.ListOptions, kind string, converter watcherConverter) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// resources implements resourceInterface.
|
||||
type resources struct {
|
||||
backend bapi.Client
|
||||
}
|
||||
|
||||
// Create creates a resource in the backend datastore.
|
||||
func (c *resources) Create(ctx context.Context, opts options.SetOptions, kind string, in resource) (resource, error) {
|
||||
// Resource must have a Name. Currently we do not support GenerateName.
|
||||
if len(in.GetObjectMeta().GetName()) == 0 {
|
||||
var generateNameMessage string
|
||||
if len(in.GetObjectMeta().GetGenerateName()) != 0 {
|
||||
generateNameMessage = " (GenerateName is not supported)"
|
||||
}
|
||||
return nil, cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "Metadata.Name",
|
||||
Reason: "field must be set for a Create request" + generateNameMessage,
|
||||
Value: in.GetObjectMeta().GetName(),
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
// A ResourceVersion should never be specified on a Create.
|
||||
if len(in.GetObjectMeta().GetResourceVersion()) != 0 {
|
||||
logWithResource(in).Info("Rejecting Create request with non-empty resource version")
|
||||
return nil, cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "Metadata.ResourceVersion",
|
||||
Reason: "field must not be set for a Create request",
|
||||
Value: in.GetObjectMeta().GetResourceVersion(),
|
||||
}},
|
||||
}
|
||||
}
|
||||
if err := c.checkNamespace(in.GetObjectMeta().GetNamespace(), kind); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Add in the UID and creation timestamp for the resource if needed.
|
||||
creationTimestamp := in.GetObjectMeta().GetCreationTimestamp()
|
||||
if creationTimestamp.IsZero() {
|
||||
in.GetObjectMeta().SetCreationTimestamp(v1.Now())
|
||||
}
|
||||
if in.GetObjectMeta().GetUID() == "" {
|
||||
in.GetObjectMeta().SetUID(uuid.NewUUID())
|
||||
}
|
||||
|
||||
// Convert the resource to a KVPair and pass that to the backend datastore, converting
|
||||
// the response (if we get one) back to a resource.
|
||||
kvp, err := c.backend.Create(ctx, c.resourceToKVPair(opts, kind, in))
|
||||
if kvp != nil {
|
||||
return c.kvPairToResource(kvp), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update updates a resource in the backend datastore.
|
||||
func (c *resources) Update(ctx context.Context, opts options.SetOptions, kind string, in resource) (resource, error) {
|
||||
// A ResourceVersion should always be specified on an Update.
|
||||
if len(in.GetObjectMeta().GetResourceVersion()) == 0 {
|
||||
logWithResource(in).Info("Rejecting Update request with empty resource version")
|
||||
return nil, cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "Metadata.ResourceVersion",
|
||||
Reason: "field must be set for an Update request",
|
||||
Value: in.GetObjectMeta().GetResourceVersion(),
|
||||
}},
|
||||
}
|
||||
}
|
||||
if err := c.checkNamespace(in.GetObjectMeta().GetNamespace(), kind); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
creationTimestamp := in.GetObjectMeta().GetCreationTimestamp()
|
||||
if creationTimestamp.IsZero() {
|
||||
return nil, cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "Metadata.CreationTimestamp",
|
||||
Reason: "field must be set for an Update request",
|
||||
Value: in.GetObjectMeta().GetCreationTimestamp(),
|
||||
}},
|
||||
}
|
||||
}
|
||||
if in.GetObjectMeta().GetUID() == "" {
|
||||
return nil, cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "Metadata.UID",
|
||||
Reason: "field must be set for an Update request",
|
||||
Value: in.GetObjectMeta().GetUID(),
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
||||
// Convert the resource to a KVPair and pass that to the backend datastore, converting
|
||||
// the response (if we get one) back to a resource.
|
||||
kvp, err := c.backend.Update(ctx, c.resourceToKVPair(opts, kind, in))
|
||||
if kvp != nil {
|
||||
return c.kvPairToResource(kvp), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete deletes a resource from the backend datastore.
|
||||
func (c *resources) Delete(ctx context.Context, opts options.DeleteOptions, kind, ns, name string) (resource, error) {
|
||||
if err := c.checkNamespace(ns, kind); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Create a ResourceKey and pass that to the backend datastore.
|
||||
key := model.ResourceKey{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: ns,
|
||||
}
|
||||
kvp, err := c.backend.Delete(ctx, key, opts.ResourceVersion)
|
||||
if kvp != nil {
|
||||
return c.kvPairToResource(kvp), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get gets a resource from the backend datastore.
|
||||
func (c *resources) Get(ctx context.Context, opts options.GetOptions, kind, ns, name string) (resource, error) {
|
||||
if err := c.checkNamespace(ns, kind); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := model.ResourceKey{
|
||||
Kind: kind,
|
||||
Name: name,
|
||||
Namespace: ns,
|
||||
}
|
||||
kvp, err := c.backend.Get(ctx, key, opts.ResourceVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := c.kvPairToResource(kvp)
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// List lists a resource from the backend datastore.
|
||||
func (c *resources) List(ctx context.Context, opts options.ListOptions, kind, listKind string, listObj resourceList) error {
|
||||
list := model.ResourceListOptions{
|
||||
Kind: kind,
|
||||
Name: opts.Name,
|
||||
Namespace: opts.Namespace,
|
||||
Prefix: opts.Prefix,
|
||||
}
|
||||
|
||||
// Query the backend.
|
||||
kvps, err := c.backend.List(ctx, list, opts.ResourceVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Convert the slice of KVPairs to a slice of Objects.
|
||||
resources := []runtime.Object{}
|
||||
for _, kvp := range kvps.KVPairs {
|
||||
resources = append(resources, c.kvPairToResource(kvp))
|
||||
}
|
||||
err = meta.SetList(listObj, resources)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Finally, set the resource version and api group version of the list object.
|
||||
listObj.GetListMeta().SetResourceVersion(kvps.Revision)
|
||||
listObj.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{
|
||||
Group: apiv3.Group,
|
||||
Version: apiv3.VersionCurrent,
|
||||
Kind: listKind,
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Watch watches a specific resource or resource type.
|
||||
func (c *resources) Watch(ctx context.Context, opts options.ListOptions, kind string, converter watcherConverter) (watch.Interface, error) {
|
||||
list := model.ResourceListOptions{
|
||||
Kind: kind,
|
||||
Name: opts.Name,
|
||||
Namespace: opts.Namespace,
|
||||
}
|
||||
|
||||
// Create the backend watcher. We need to process the results to add revision data etc.
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
backend, err := c.backend.Watch(ctx, list, opts.ResourceVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
w := &watcher{
|
||||
results: make(chan watch.Event, 100),
|
||||
client: c,
|
||||
cancel: cancel,
|
||||
context: ctx,
|
||||
backend: backend,
|
||||
converter: converter,
|
||||
}
|
||||
go w.run()
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// resourceToKVPair converts the resource to a KVPair that can be consumed by the
|
||||
// backend datastore client.
|
||||
func (c *resources) resourceToKVPair(opts options.SetOptions, kind string, in resource) *model.KVPair {
|
||||
// Prepare the resource to remove non-persisted fields.
|
||||
rv := in.GetObjectMeta().GetResourceVersion()
|
||||
in.GetObjectMeta().SetResourceVersion("")
|
||||
in.GetObjectMeta().SetSelfLink("")
|
||||
|
||||
// Make sure the kind and version are set before storing.
|
||||
in.GetObjectKind().SetGroupVersionKind(schema.GroupVersionKind{
|
||||
Group: apiv3.Group,
|
||||
Version: apiv3.VersionCurrent,
|
||||
Kind: kind,
|
||||
})
|
||||
|
||||
// Create a KVPair using the "generic" resource Key, and the actual object as
|
||||
// the value.
|
||||
return &model.KVPair{
|
||||
TTL: opts.TTL,
|
||||
Value: in,
|
||||
Key: model.ResourceKey{
|
||||
Kind: kind,
|
||||
Name: in.GetObjectMeta().GetName(),
|
||||
Namespace: in.GetObjectMeta().GetNamespace(),
|
||||
},
|
||||
Revision: rv,
|
||||
}
|
||||
}
|
||||
|
||||
// kvPairToResource converts a KVPair returned by the backend datastore client to a
|
||||
// resource.
|
||||
func (c *resources) kvPairToResource(kvp *model.KVPair) resource {
|
||||
// Extract the resource from the returned value - the backend will already have
|
||||
// decoded it.
|
||||
out := kvp.Value.(resource)
|
||||
|
||||
// Remove the SelfLink which Calico does not use, and set the ResourceVersion from the
|
||||
// value returned from the backend datastore.
|
||||
out.GetObjectMeta().SetSelfLink("")
|
||||
out.GetObjectMeta().SetResourceVersion(kvp.Revision)
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
// checkNamespace checks that the namespace is supplied on a namespaced resource type.
|
||||
func (c *resources) checkNamespace(ns, kind string) error {
|
||||
|
||||
if namespace.IsNamespaced(kind) && len(ns) == 0 {
|
||||
return cerrors.ErrorValidation{
|
||||
ErroredFields: []cerrors.ErroredField{{
|
||||
Name: "Metadata.Namespace",
|
||||
Reason: "namespace is not specified on namespaced resource",
|
||||
}},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// watcher implements the watch.Interface.
|
||||
type watcher struct {
|
||||
backend bapi.WatchInterface
|
||||
context context.Context
|
||||
cancel context.CancelFunc
|
||||
results chan watch.Event
|
||||
client *resources
|
||||
terminated uint32
|
||||
converter watcherConverter
|
||||
}
|
||||
|
||||
func (w *watcher) Stop() {
|
||||
w.cancel()
|
||||
}
|
||||
|
||||
func (w *watcher) ResultChan() <-chan watch.Event {
|
||||
return w.results
|
||||
}
|
||||
|
||||
// run is the main watch loop, pulling events from the backend watcher and sending
|
||||
// down the results channel.
|
||||
func (w *watcher) run() {
|
||||
log.Info("Main client watcher loop")
|
||||
|
||||
// Make sure we terminate resources if we exit.
|
||||
defer w.terminate()
|
||||
|
||||
for {
|
||||
select {
|
||||
case event, ok := <-w.backend.ResultChan():
|
||||
if !ok {
|
||||
log.Debug("Watcher results channel closed by remote")
|
||||
return
|
||||
}
|
||||
e := w.convertEvent(event)
|
||||
select {
|
||||
case w.results <- e:
|
||||
case <-w.context.Done():
|
||||
log.Info("Process backend watcher done event during watch event in main client")
|
||||
return
|
||||
}
|
||||
case <-w.context.Done(): // user cancel
|
||||
log.Info("Process backend watcher done event in main client")
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// terminate all resources associated with this watcher.
|
||||
func (w *watcher) terminate() {
|
||||
log.Info("Terminating main client watcher loop")
|
||||
w.cancel()
|
||||
close(w.results)
|
||||
atomic.AddUint32(&w.terminated, 1)
|
||||
}
|
||||
|
||||
// convertEvent converts a backend watch event into a client watch event.
|
||||
func (w *watcher) convertEvent(backendEvent bapi.WatchEvent) watch.Event {
|
||||
apiEvent := watch.Event{
|
||||
Error: backendEvent.Error,
|
||||
}
|
||||
switch backendEvent.Type {
|
||||
case bapi.WatchError:
|
||||
apiEvent.Type = watch.Error
|
||||
case bapi.WatchAdded:
|
||||
apiEvent.Type = watch.Added
|
||||
case bapi.WatchDeleted:
|
||||
apiEvent.Type = watch.Deleted
|
||||
case bapi.WatchModified:
|
||||
apiEvent.Type = watch.Modified
|
||||
}
|
||||
|
||||
if backendEvent.Old != nil {
|
||||
res := w.client.kvPairToResource(backendEvent.Old)
|
||||
if w.converter != nil {
|
||||
res = w.converter.Convert(res)
|
||||
}
|
||||
apiEvent.Previous = res
|
||||
}
|
||||
if backendEvent.New != nil {
|
||||
res := w.client.kvPairToResource(backendEvent.New)
|
||||
if w.converter != nil {
|
||||
apiEvent.Object = w.converter.Convert(res)
|
||||
}
|
||||
apiEvent.Object = res
|
||||
}
|
||||
|
||||
return apiEvent
|
||||
}
|
||||
|
||||
// hasTerminated returns true if the watcher has terminated, release all resources.
|
||||
// Used for test purposes.
|
||||
func (w *watcher) hasTerminated() bool {
|
||||
t := atomic.LoadUint32(&w.terminated) != 0
|
||||
bt := w.backend.HasTerminated()
|
||||
log.Infof("hasTerminated() terminated=%v; backend-terminated=%v", t, bt)
|
||||
return t && bt
|
||||
}
|
||||
|
||||
// logWithResource returns a logrus entry with key resource attributes included.
|
||||
func logWithResource(res resource) *log.Entry {
|
||||
return log.WithFields(log.Fields{
|
||||
"Kind": res.GetObjectKind().GroupVersionKind(),
|
||||
"Name": res.GetObjectMeta().GetName(),
|
||||
"Namespace": res.GetObjectMeta().GetNamespace(),
|
||||
"ResourceVersion": res.GetObjectMeta().GetResourceVersion(),
|
||||
})
|
||||
}
|
||||
|
||||
// watcherConverter represents a formatter for calico resources returned by Watch.
|
||||
type watcherConverter interface {
|
||||
// Convert the internal representation of a resource to a readable format.
|
||||
Convert(resource) resource
|
||||
}
|
||||
166
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/workloadendpoint.go
generated
vendored
Normal file
166
vendor/github.com/projectcalico/libcalico-go/lib/clientv3/workloadendpoint.go
generated
vendored
Normal file
@@ -0,0 +1,166 @@
|
||||
// Copyright (c) 2017-2018 Tigera, 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 clientv3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
apiv3 "github.com/projectcalico/libcalico-go/lib/apis/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/errors"
|
||||
"github.com/projectcalico/libcalico-go/lib/names"
|
||||
"github.com/projectcalico/libcalico-go/lib/options"
|
||||
validator "github.com/projectcalico/libcalico-go/lib/validator/v3"
|
||||
"github.com/projectcalico/libcalico-go/lib/watch"
|
||||
)
|
||||
|
||||
// WorkloadEndpointInterface has methods to work with WorkloadEndpoint resources.
|
||||
type WorkloadEndpointInterface interface {
|
||||
Create(ctx context.Context, res *apiv3.WorkloadEndpoint, opts options.SetOptions) (*apiv3.WorkloadEndpoint, error)
|
||||
Update(ctx context.Context, res *apiv3.WorkloadEndpoint, opts options.SetOptions) (*apiv3.WorkloadEndpoint, error)
|
||||
Delete(ctx context.Context, namespace, name string, opts options.DeleteOptions) (*apiv3.WorkloadEndpoint, error)
|
||||
Get(ctx context.Context, namespace, name string, opts options.GetOptions) (*apiv3.WorkloadEndpoint, error)
|
||||
List(ctx context.Context, opts options.ListOptions) (*apiv3.WorkloadEndpointList, error)
|
||||
Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// workloadEndpoints implements WorkloadEndpointInterface
|
||||
type workloadEndpoints struct {
|
||||
client client
|
||||
}
|
||||
|
||||
// Create takes the representation of a WorkloadEndpoint and creates it. Returns the stored
|
||||
// representation of the WorkloadEndpoint, and an error, if there is any.
|
||||
func (r workloadEndpoints) Create(ctx context.Context, res *apiv3.WorkloadEndpoint, opts options.SetOptions) (*apiv3.WorkloadEndpoint, error) {
|
||||
if res != nil {
|
||||
// Since we're about to default some fields, take a (shallow) copy of the input data
|
||||
// before we do so.
|
||||
resCopy := *res
|
||||
res = &resCopy
|
||||
}
|
||||
if err := r.assignOrValidateName(res); err != nil {
|
||||
return nil, err
|
||||
} else if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.updateLabelsForStorage(res)
|
||||
out, err := r.client.resources.Create(ctx, opts, apiv3.KindWorkloadEndpoint, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.WorkloadEndpoint), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Update takes the representation of a WorkloadEndpoint and updates it. Returns the stored
|
||||
// representation of the WorkloadEndpoint, and an error, if there is any.
|
||||
func (r workloadEndpoints) Update(ctx context.Context, res *apiv3.WorkloadEndpoint, opts options.SetOptions) (*apiv3.WorkloadEndpoint, error) {
|
||||
if res != nil {
|
||||
// Since we're about to default some fields, take a (shallow) copy of the input data
|
||||
// before we do so.
|
||||
resCopy := *res
|
||||
res = &resCopy
|
||||
}
|
||||
if err := r.assignOrValidateName(res); err != nil {
|
||||
return nil, err
|
||||
} else if err := validator.Validate(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.updateLabelsForStorage(res)
|
||||
out, err := r.client.resources.Update(ctx, opts, apiv3.KindWorkloadEndpoint, res)
|
||||
if out != nil {
|
||||
return out.(*apiv3.WorkloadEndpoint), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Delete takes name of the WorkloadEndpoint and deletes it. Returns an error if one occurs.
|
||||
func (r workloadEndpoints) Delete(ctx context.Context, namespace, name string, opts options.DeleteOptions) (*apiv3.WorkloadEndpoint, error) {
|
||||
out, err := r.client.resources.Delete(ctx, opts, apiv3.KindWorkloadEndpoint, namespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.WorkloadEndpoint), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Get takes name of the WorkloadEndpoint, and returns the corresponding WorkloadEndpoint object,
|
||||
// and an error if there is any.
|
||||
func (r workloadEndpoints) Get(ctx context.Context, namespace, name string, opts options.GetOptions) (*apiv3.WorkloadEndpoint, error) {
|
||||
out, err := r.client.resources.Get(ctx, opts, apiv3.KindWorkloadEndpoint, namespace, name)
|
||||
if out != nil {
|
||||
return out.(*apiv3.WorkloadEndpoint), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// List returns the list of WorkloadEndpoint objects that match the supplied options.
|
||||
func (r workloadEndpoints) List(ctx context.Context, opts options.ListOptions) (*apiv3.WorkloadEndpointList, error) {
|
||||
res := &apiv3.WorkloadEndpointList{}
|
||||
if err := r.client.resources.List(ctx, opts, apiv3.KindWorkloadEndpoint, apiv3.KindWorkloadEndpointList, res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// Watch returns a watch.Interface that watches the NetworkPolicies that match the
|
||||
// supplied options.
|
||||
func (r workloadEndpoints) Watch(ctx context.Context, opts options.ListOptions) (watch.Interface, error) {
|
||||
return r.client.resources.Watch(ctx, opts, apiv3.KindWorkloadEndpoint, nil)
|
||||
}
|
||||
|
||||
// assignOrValidateName either assigns the name calculated from the Spec fields, or validates
|
||||
// the name against the spec fields.
|
||||
func (r workloadEndpoints) assignOrValidateName(res *apiv3.WorkloadEndpoint) error {
|
||||
// Validate the workload endpoint indices and the name match.
|
||||
wepids := names.WorkloadEndpointIdentifiers{
|
||||
Node: res.Spec.Node,
|
||||
Orchestrator: res.Spec.Orchestrator,
|
||||
Endpoint: res.Spec.Endpoint,
|
||||
Workload: res.Spec.Workload,
|
||||
Pod: res.Spec.Pod,
|
||||
ContainerID: res.Spec.ContainerID,
|
||||
}
|
||||
expectedName, err := wepids.CalculateWorkloadEndpointName(false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(res.Name) == 0 {
|
||||
// If a name was not specified then we will calculate it on behalf of the caller.
|
||||
res.Name = expectedName
|
||||
return nil
|
||||
}
|
||||
if res.Name != expectedName {
|
||||
return errors.ErrorValidation{
|
||||
ErroredFields: []errors.ErroredField{{
|
||||
Name: "Name",
|
||||
Value: res.Name,
|
||||
Reason: fmt.Sprintf("the WorkloadEndpoint name does not match the primary identifiers assigned in the Spec: expected name %s", expectedName),
|
||||
}},
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// updateLabelsForStorage updates the set of labels that we persist. It adds/overrides
|
||||
// the Namespace and Orchestrator labels which must be set to the correct values and are
|
||||
// not user configurable.
|
||||
func (r workloadEndpoints) updateLabelsForStorage(res *apiv3.WorkloadEndpoint) {
|
||||
labelsCopy := make(map[string]string, len(res.GetLabels())+2)
|
||||
for k, v := range res.GetLabels() {
|
||||
labelsCopy[k] = v
|
||||
}
|
||||
labelsCopy[apiv3.LabelNamespace] = res.Namespace
|
||||
labelsCopy[apiv3.LabelOrchestrator] = res.Spec.Orchestrator
|
||||
res.SetLabels(labelsCopy)
|
||||
}
|
||||
Reference in New Issue
Block a user