Merge pull request #11498 from johngmyers/cloud-statusstore

Subsume StatusStore into fi.Cloud
This commit is contained in:
Kubernetes Prow Robot 2021-05-18 06:29:31 -07:00 committed by GitHub
commit a1e331a46b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 390 additions and 508 deletions

View File

@ -132,7 +132,7 @@ func (c *MockGCECloud) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterSt
}
// GetApiIngressStatus implements GCECloud::GetApiIngressStatus
func (c *MockGCECloud) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
func (c *MockGCECloud) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return nil, fmt.Errorf("MockGCECloud::GetApiIngressStatus not implemented")
}

View File

@ -243,8 +243,7 @@ func RunEditCluster(ctx context.Context, f *util.Factory, cmd *cobra.Command, ar
}
// Retrieve the current status of the cluster. This will eventually be part of the cluster object.
statusDiscovery := &commands.CloudDiscoveryStatusStore{}
status, err := statusDiscovery.FindClusterStatus(oldCluster)
status, err := cloud.FindClusterStatus(oldCluster)
if err != nil {
return err
}

View File

@ -27,8 +27,8 @@ import (
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kops/cmd/kops/util"
kopsapi "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/commands"
"k8s.io/kops/pkg/kubeconfig"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
)
@ -139,11 +139,15 @@ func RunExportKubecfg(ctx context.Context, f *util.Factory, out io.Writer, optio
return err
}
cloud, err := cloudup.BuildCloud(cluster)
if err != nil {
return err
}
conf, err := kubeconfig.BuildKubecfg(
cluster,
keyStore,
secretStore,
&commands.CloudDiscoveryStatusStore{},
cloud,
options.admin,
options.user,
options.internal,

View File

@ -27,8 +27,8 @@ import (
"k8s.io/klog/v2"
"k8s.io/kops/cmd/kops/util"
kopsapi "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/commands"
"k8s.io/kops/pkg/kopscodecs"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kops/util/pkg/text"
"k8s.io/kops/util/pkg/vfs"
cmdutil "k8s.io/kubectl/pkg/cmd/util"
@ -120,8 +120,11 @@ func RunReplace(ctx context.Context, f *util.Factory, cmd *cobra.Command, out io
case *kopsapi.Cluster:
{
// Retrieve the current status of the cluster. This will eventually be part of the cluster object.
statusDiscovery := &commands.CloudDiscoveryStatusStore{}
status, err := statusDiscovery.FindClusterStatus(v)
cloud, err := cloudup.BuildCloud(v)
if err != nil {
return err
}
status, err := cloud.FindClusterStatus(v)
if err != nil {
return err
}

View File

@ -32,7 +32,6 @@ import (
"k8s.io/klog/v2"
"k8s.io/kops/cmd/kops/util"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/commands"
"k8s.io/kops/pkg/kubeconfig"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup"
@ -318,7 +317,7 @@ func RunUpdateCluster(ctx context.Context, f *util.Factory, clusterName string,
cluster,
keyStore,
secretStore,
&commands.CloudDiscoveryStatusStore{},
cloud,
c.admin,
c.user,
c.internal,

View File

@ -16,18 +16,6 @@ limitations under the License.
package kops
import (
"k8s.io/klog/v2"
)
// StatusStore abstracts the key status functions; and lets us introduce status gradually
type StatusStore interface {
// FindClusterStatus discovers the status of the cluster, by inspecting the cloud objects
FindClusterStatus(cluster *Cluster) (*ClusterStatus, error)
GetApiIngressStatus(cluster *Cluster) ([]ApiIngressStatus, error)
}
type ClusterStatus struct {
// EtcdClusters stores the status for each cluster
EtcdClusters []EtcdClusterStatus `json:"etcdClusters,omitempty"`
@ -48,35 +36,3 @@ type EtcdMemberStatus struct {
// volumeId is the id of the cloud volume (e.g. the AWS volume id)
VolumeId string `json:"volumeId,omitempty"`
}
// ApiIngressStatus represents the status of an ingress point:
// traffic intended for the service should be sent to an ingress point.
type ApiIngressStatus struct {
// IP is set for load-balancer ingress points that are IP based
// (typically GCE or OpenStack load-balancers)
// +optional
IP string `json:"ip,omitempty" protobuf:"bytes,1,opt,name=ip"`
// Hostname is set for load-balancer ingress points that are DNS based
// (typically AWS load-balancers)
// +optional
Hostname string `json:"hostname,omitempty" protobuf:"bytes,2,opt,name=hostname"`
}
// NoopStatusStore is a stub implementation that returns empty status
// It is a temporary hackaround while we introduce status
type NoopStatusStore struct {
}
var _ StatusStore = &NoopStatusStore{}
// FindClusterStatus discovers the status of the cluster, by inspecting the cloud objects
func (s *NoopStatusStore) FindClusterStatus(cluster *Cluster) (*ClusterStatus, error) {
klog.Warningf("FindClusterStatus called on NoopStore")
return nil, nil
}
func (s *NoopStatusStore) GetApiIngressStatus(cluster *Cluster) ([]ApiIngressStatus, error) {
klog.Warningf("GetApiIngressStatus called on NoopStore")
return nil, nil
}

View File

@ -91,7 +91,7 @@ func validateEtcdClusterUpdate(fp *field.Path, obj kops.EtcdClusterSpec, status
fp := fp.Child("etcdMembers").Key(k)
if oldMember, ok := oldMembers[k]; ok {
allErrs = append(allErrs, validateEtcdMemberUpdate(fp, newMember, etcdClusterStatus, oldMember)...)
allErrs = append(allErrs, validateEtcdMemberUpdate(fp, newMember, oldMember)...)
}
}
}
@ -99,7 +99,7 @@ func validateEtcdClusterUpdate(fp *field.Path, obj kops.EtcdClusterSpec, status
return allErrs
}
func validateEtcdMemberUpdate(fp *field.Path, obj kops.EtcdMemberSpec, status *kops.EtcdClusterStatus, old kops.EtcdMemberSpec) field.ErrorList {
func validateEtcdMemberUpdate(fp *field.Path, obj kops.EtcdMemberSpec, old kops.EtcdMemberSpec) field.ErrorList {
allErrs := field.ErrorList{}
if obj.Name != old.Name {

View File

@ -183,22 +183,6 @@ func (in *AmazonVPCNetworkingSpec) DeepCopy() *AmazonVPCNetworkingSpec {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ApiIngressStatus) DeepCopyInto(out *ApiIngressStatus) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiIngressStatus.
func (in *ApiIngressStatus) DeepCopy() *ApiIngressStatus {
if in == nil {
return nil
}
out := new(ApiIngressStatus)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Assets) DeepCopyInto(out *Assets) {
*out = *in
@ -4183,22 +4167,6 @@ func (in *NodeTerminationHandlerConfig) DeepCopy() *NodeTerminationHandlerConfig
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *NoopStatusStore) DeepCopyInto(out *NoopStatusStore) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NoopStatusStore.
func (in *NoopStatusStore) DeepCopy() *NoopStatusStore {
if in == nil {
return nil
}
out := new(NoopStatusStore)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OpenstackBlockStorageConfig) DeepCopyInto(out *OpenstackBlockStorageConfig) {
*out = *in

View File

@ -7,7 +7,6 @@ go_library(
"helpers_readwrite.go",
"set_cluster.go",
"set_instancegroups.go",
"status_discovery.go",
"version.go",
],
importpath = "k8s.io/kops/pkg/commands",
@ -21,14 +20,7 @@ go_library(
"//pkg/client/simple:go_default_library",
"//pkg/commands/helpers:go_default_library",
"//pkg/featureflag:go_default_library",
"//pkg/resources/digitalocean:go_default_library",
"//upup/pkg/fi/cloudup:go_default_library",
"//upup/pkg/fi/cloudup/aliup:go_default_library",
"//upup/pkg/fi/cloudup/awstasks:go_default_library",
"//upup/pkg/fi/cloudup/awsup:go_default_library",
"//upup/pkg/fi/cloudup/azure:go_default_library",
"//upup/pkg/fi/cloudup/gce:go_default_library",
"//upup/pkg/fi/cloudup/openstack:go_default_library",
"//util/pkg/reflectutils:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",

View File

@ -52,8 +52,7 @@ func UpdateCluster(ctx context.Context, clientset simple.Clientset, cluster *kop
}
// Retrieve the current status of the cluster. This will eventually be part of the cluster object.
statusDiscovery := &CloudDiscoveryStatusStore{}
status, err := statusDiscovery.FindClusterStatus(cluster)
status, err := cloud.FindClusterStatus(cluster)
if err != nil {
return err
}

View File

@ -1,112 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package commands
import (
"fmt"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/resources/digitalocean"
"k8s.io/kops/upup/pkg/fi/cloudup"
"k8s.io/kops/upup/pkg/fi/cloudup/aliup"
"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
"k8s.io/kops/upup/pkg/fi/cloudup/azure"
"k8s.io/kops/upup/pkg/fi/cloudup/gce"
"k8s.io/kops/upup/pkg/fi/cloudup/openstack"
)
// CloudDiscoveryStatusStore implements status.Store by inspecting cloud objects.
// Likely temporary until we validate our status usage
type CloudDiscoveryStatusStore struct {
}
var _ kops.StatusStore = &CloudDiscoveryStatusStore{}
func (s *CloudDiscoveryStatusStore) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
cloud, err := cloudup.BuildCloud(cluster)
if err != nil {
return nil, err
}
if aliCloud, ok := cloud.(aliup.ALICloud); ok {
return aliCloud.GetApiIngressStatus(cluster)
}
if gceCloud, ok := cloud.(gce.GCECloud); ok {
return gceCloud.GetApiIngressStatus(cluster)
}
if awsCloud, ok := cloud.(awsup.AWSCloud); ok {
var ingresses []kops.ApiIngressStatus
if lbDnsName, err := awstasks.FindDNSName(awsCloud, cluster); err != nil {
return nil, fmt.Errorf("error finding aws DNSName: %v", err)
} else if lbDnsName != "" {
ingresses = append(ingresses, kops.ApiIngressStatus{Hostname: lbDnsName})
}
return ingresses, nil
}
if azureCloud, ok := cloud.(azure.AzureCloud); ok {
return azureCloud.GetApiIngressStatus(cluster)
}
if osCloud, ok := cloud.(openstack.OpenstackCloud); ok {
return osCloud.GetApiIngressStatus(cluster)
}
if doCloud, ok := cloud.(*digitalocean.Cloud); ok {
return doCloud.GetApiIngressStatus(cluster)
}
return nil, fmt.Errorf("API Ingress Status not implemented for %T", cloud)
}
// FindClusterStatus discovers the status of the cluster, by inspecting the cloud objects
func (s *CloudDiscoveryStatusStore) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error) {
cloud, err := cloudup.BuildCloud(cluster)
if err != nil {
return nil, err
}
if gceCloud, ok := cloud.(gce.GCECloud); ok {
return gceCloud.FindClusterStatus(cluster)
}
if awsCloud, ok := cloud.(awsup.AWSCloud); ok {
return awsCloud.FindClusterStatus(cluster)
}
if aliCloud, ok := cloud.(aliup.ALICloud); ok {
return aliCloud.FindClusterStatus(cluster)
}
if azureCloud, ok := cloud.(azure.AzureCloud); ok {
return azureCloud.FindClusterStatus(cluster)
}
if osCloud, ok := cloud.(openstack.OpenstackCloud); ok {
return osCloud.FindClusterStatus(cluster)
}
if doCloud, ok := cloud.(*digitalocean.Cloud); ok {
return doCloud.FindClusterStatus(cluster)
}
return nil, fmt.Errorf("etcd Status not implemented for %T", cloud)
}

View File

@ -28,11 +28,14 @@ go_test(
srcs = ["create_kubecfg_test.go"],
embed = [":go_default_library"],
deps = [
"//dnsprovider/pkg/dnsprovider:go_default_library",
"//pkg/apis/kops:go_default_library",
"//pkg/cloudinstances:go_default_library",
"//pkg/pki:go_default_library",
"//pkg/testutils:go_default_library",
"//upup/pkg/fi:go_default_library",
"//util/pkg/vfs:go_default_library",
"//vendor/github.com/google/go-cmp/cmp:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
],
)

View File

@ -34,7 +34,7 @@ import (
const DefaultKubecfgAdminLifetime = 18 * time.Hour
func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.SecretStore, status kops.StatusStore, admin time.Duration, configUser string, internal bool, kopsStateStore string, useKopsAuthenticationPlugin bool) (*KubeconfigBuilder, error) {
func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.SecretStore, cloud fi.Cloud, admin time.Duration, configUser string, internal bool, kopsStateStore string, useKopsAuthenticationPlugin bool) (*KubeconfigBuilder, error) {
clusterName := cluster.ObjectMeta.Name
var master string
@ -71,7 +71,7 @@ func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.Se
}
if useELBName {
ingresses, err := status.GetApiIngressStatus(cluster)
ingresses, err := cloud.GetApiIngressStatus(cluster)
if err != nil {
return nil, fmt.Errorf("error getting ingress status: %v", err)
}

View File

@ -21,6 +21,9 @@ import (
"testing"
"time"
v1 "k8s.io/api/core/v1"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
"k8s.io/kops/pkg/cloudinstances"
"k8s.io/kops/pkg/testutils"
"github.com/google/go-cmp/cmp"
@ -34,19 +37,52 @@ const certData = "-----BEGIN CERTIFICATE-----\nMIIC2DCCAcCgAwIBAgIRALJXAkVj964tq
const privatekeyData = "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA4JwpEprZ5n8RIEt6jT2lAh+UDgRgx/4px21gjgywQivYHVxH\nAZexVb/E9pBa9Q2G9B1Q7TCO7YsUVRQy4JMDZVt+McFnWVwexnqBYFNcVjkEmDgA\ngvCYGE0P9d/RwRL4KuLHo+u6fv7P0jXMN+CpOxyLhYZZNa0ZOZDHsSiJSQSj9WGF\nGHrbCf0KVDpKieR1uBqHrRO+mLR5zkX2L58m74kjK4dsBhmjeq/7OAoTmiG2QgJ/\nP2IjyhiA2mRqY+hl55lwEUV/0yHYEkJC8LdGkwwZz2eF77aSPGmi/A2CSKgMwDTx\n9m+P7jcpWreYw6NG9BueGoDIve/tgFKwvVFF6QIDAQABAoIBAA0ktjaTfyrAxsTI\nBezb7Zr5NBW55dvuII299cd6MJo+rI/TRYhvUv48kY8IFXp/hyUjzgeDLunxmIf9\n/Zgsoic9Ol44/g45mMduhcGYPzAAeCdcJ5OB9rR9VfDCXyjYLlN8H8iU0734tTqM\n0V13tQ9zdSqkGPZOIcq/kR/pylbOZaQMe97BTlsAnOMSMKDgnftY4122Lq3GYy+t\nvpr+bKVaQZwvkLoSU3rECCaKaghgwCyX7jft9aEkhdJv+KlwbsGY6WErvxOaLWHd\ncuMQjGapY1Fa/4UD00mvrA260NyKfzrp6+P46RrVMwEYRJMIQ8YBAk6N6Hh7dc0G\n8Z6i1m0CgYEA9HeCJR0TSwbIQ1bDXUrzpftHuidG5BnSBtax/ND9qIPhR/FBW5nj\n22nwLc48KkyirlfIULd0ae4qVXJn7wfYcuX/cJMLDmSVtlM5Dzmi/91xRiFgIzx1\nAsbBzaFjISP2HpSgL+e9FtSXaaqeZVrflitVhYKUpI/AKV31qGHf04sCgYEA6zTV\n99Sb49Wdlns5IgsfnXl6ToRttB18lfEKcVfjAM4frnkk06JpFAZeR+9GGKUXZHqs\nz2qcplw4d/moCC6p3rYPBMLXsrGNEUFZqBlgz72QA6BBq3X0Cg1Bc2ZbK5VIzwkg\nST2SSux6ccROfgULmN5ZiLOtdUKNEZpFF3i3qtsCgYADT/s7dYFlatobz3kmMnXK\nsfTu2MllHdRys0YGHu7Q8biDuQkhrJwhxPW0KS83g4JQym+0aEfzh36bWcl+u6R7\nKhKj+9oSf9pndgk345gJz35RbPJYh+EuAHNvzdgCAvK6x1jETWeKf6btj5pF1U1i\nQ4QNIw/QiwIXjWZeubTGsQKBgQCbduLu2rLnlyyAaJZM8DlHZyH2gAXbBZpxqU8T\nt9mtkJDUS/KRiEoYGFV9CqS0aXrayVMsDfXY6B/S/UuZjO5u7LtklDzqOf1aKG3Q\ndGXPKibknqqJYH+bnUNjuYYNerETV57lijMGHuSYCf8vwLn3oxBfERRX61M/DU8Z\nworz/QKBgQDCTJI2+jdXg26XuYUmM4XXfnocfzAXhXBULt1nENcogNf1fcptAVtu\nBAiz4/HipQKqoWVUYmxfgbbLRKKLK0s0lOWKbYdVjhEm/m2ZU8wtXTagNwkIGoyq\nY/C1Lox4f1ROJnCjc/hfcOjcxX5M8A8peecHWlVtUPKTJgxQ7oMKcw==\n-----END RSA PRIVATE KEY-----\n"
// mock a fake status store.
type fakeStatusStore struct {
FindClusterStatusFn func(cluster *kops.Cluster) (*kops.ClusterStatus, error)
GetApiIngressStatusFn func(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error)
type fakeStatusCloud struct {
GetApiIngressStatusFn func(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error)
}
func (f fakeStatusStore) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error) {
return f.FindClusterStatusFn(cluster)
}
var _ fi.Cloud = &fakeStatusCloud{}
func (f fakeStatusStore) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
func (f fakeStatusCloud) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return f.GetApiIngressStatusFn(cluster)
}
func (f fakeStatusCloud) ProviderID() kops.CloudProviderID {
panic("not implemented")
}
func (f fakeStatusCloud) DNS() (dnsprovider.Interface, error) {
panic("not implemented")
}
func (f fakeStatusCloud) FindVPCInfo(id string) (*fi.VPCInfo, error) {
panic("not implemented")
}
func (f fakeStatusCloud) DeleteInstance(instance *cloudinstances.CloudInstance) error {
panic("not implemented")
}
func (f fakeStatusCloud) DeleteGroup(group *cloudinstances.CloudInstanceGroup) error {
panic("not implemented")
}
func (f fakeStatusCloud) DetachInstance(instance *cloudinstances.CloudInstance) error {
panic("not implemented")
}
func (f fakeStatusCloud) GetCloudGroups(cluster *kops.Cluster, instancegroups []*kops.InstanceGroup, warnUnmatched bool, nodes []v1.Node) (map[string]*cloudinstances.CloudInstanceGroup, error) {
panic("not implemented")
}
func (f fakeStatusCloud) Region() string {
panic("not implemented")
}
func (f fakeStatusCloud) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error) {
panic("not implemented")
}
// mock a fake key store
type fakeKeyStore struct {
FindKeypairFn func(name string) (*pki.Certificate, *pki.PrivateKey, bool, error)
@ -110,7 +146,7 @@ func TestBuildKubecfg(t *testing.T) {
type args struct {
cluster *kops.Cluster
secretStore fi.SecretStore
status fakeStatusStore
status fakeStatusCloud
admin time.Duration
user string
internal bool
@ -135,7 +171,7 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For Public DNS with admin",
args: args{
cluster: publicCluster,
status: fakeStatusStore{},
status: fakeStatusCloud{},
admin: DefaultKubecfgAdminLifetime,
user: "",
},
@ -151,7 +187,7 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For Public DNS with admin and secondary NLB port",
args: args{
cluster: certNLBCluster,
status: fakeStatusStore{},
status: fakeStatusCloud{},
admin: DefaultKubecfgAdminLifetime,
},
want: &KubeconfigBuilder{
@ -166,7 +202,7 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For Public DNS with admin and CLB ACM Certificate",
args: args{
cluster: certCluster,
status: fakeStatusStore{},
status: fakeStatusCloud{},
admin: DefaultKubecfgAdminLifetime,
},
want: &KubeconfigBuilder{
@ -181,7 +217,7 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For Public DNS without admin and with ACM certificate",
args: args{
cluster: certNLBCluster,
status: fakeStatusStore{},
status: fakeStatusCloud{},
admin: 0,
},
want: &KubeconfigBuilder{
@ -196,7 +232,7 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For Public DNS without admin",
args: args{
cluster: publicCluster,
status: fakeStatusStore{},
status: fakeStatusCloud{},
admin: 0,
user: "myuser",
},
@ -212,7 +248,7 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For Public DNS with Empty Master Name",
args: args{
cluster: emptyMasterPublicNameCluster,
status: fakeStatusStore{},
status: fakeStatusCloud{},
admin: 0,
user: "",
},
@ -228,9 +264,9 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For Gossip cluster",
args: args{
cluster: gossipCluster,
status: fakeStatusStore{
GetApiIngressStatusFn: func(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
return []kops.ApiIngressStatus{
status: fakeStatusCloud{
GetApiIngressStatusFn: func(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return []fi.ApiIngressStatus{
{
Hostname: "elbHostName",
},
@ -250,7 +286,7 @@ func TestBuildKubecfg(t *testing.T) {
name: "Public DNS with kops auth plugin",
args: args{
cluster: publicCluster,
status: fakeStatusStore{},
status: fakeStatusCloud{},
admin: 0,
useKopsAuthenticationPlugin: true,
},
@ -273,7 +309,7 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For internal DNS name with admin",
args: args{
cluster: publicCluster,
status: fakeStatusStore{},
status: fakeStatusCloud{},
admin: DefaultKubecfgAdminLifetime,
internal: true,
},
@ -289,9 +325,9 @@ func TestBuildKubecfg(t *testing.T) {
name: "Test Kube Config Data For Gossip cluster with admin and secondary NLB port",
args: args{
cluster: certGossipNLBCluster,
status: fakeStatusStore{
GetApiIngressStatusFn: func(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
return []kops.ApiIngressStatus{
status: fakeStatusCloud{
GetApiIngressStatusFn: func(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return []fi.ApiIngressStatus{
{
Hostname: "nlbHostName",
},

View File

@ -199,8 +199,8 @@ func (c *Cloud) FindVPCInfo(id string) (*fi.VPCInfo, error) {
return nil, errors.New("not implemented")
}
func (c *Cloud) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
var ingresses []kops.ApiIngressStatus
func (c *Cloud) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
var ingresses []fi.ApiIngressStatus
if cluster.Spec.MasterPublicName != "" {
// Note that this must match Digital Ocean's lb name
klog.V(2).Infof("Querying DO to find Loadbalancers for API (%q)", cluster.Name)
@ -221,7 +221,7 @@ func (c *Cloud) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressSta
}
address := lb.IP
ingresses = append(ingresses, kops.ApiIngressStatus{IP: address})
ingresses = append(ingresses, fi.ApiIngressStatus{IP: address})
return ingresses, nil
}

View File

@ -47,6 +47,11 @@ type Cloud interface {
// Region returns the cloud region bound to the cloud instance.
// If the region concept does not apply, returns "".
Region() string
// FindClusterStatus discovers the status of the cluster, by inspecting the cloud objects
FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error)
GetApiIngressStatus(cluster *kops.Cluster) ([]ApiIngressStatus, error)
}
type VPCInfo struct {
@ -63,6 +68,20 @@ type SubnetInfo struct {
CIDR string
}
// ApiIngressStatus represents the status of an ingress point:
// traffic intended for the service should be sent to an ingress point.
type ApiIngressStatus struct {
// IP is set for load-balancer ingress points that are IP based
// (typically GCE or OpenStack load-balancers)
// +optional
IP string `json:"ip,omitempty" protobuf:"bytes,1,opt,name=ip"`
// Hostname is set for load-balancer ingress points that are DNS based
// (typically AWS load-balancers)
// +optional
Hostname string `json:"hostname,omitempty" protobuf:"bytes,2,opt,name=hostname"`
}
// zonesToCloud allows us to infer from certain well-known zones to a cloud
// Note it is safe to "overmap" zones that don't exist: we'll check later if the zones actually exist
var zonesToCloud = map[string]kops.CloudProviderID{

View File

@ -70,8 +70,6 @@ type ALICloud interface {
CreateTags(resourceId string, resourceType string, tags map[string]string) error
RemoveTags(resourceId string, resourceType string, tags map[string]string) error
GetClusterTags() map[string]string
FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error)
GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error)
}
type aliCloudImplementation struct {
@ -342,8 +340,8 @@ func (c *aliCloudImplementation) GetClusterTags() map[string]string {
return c.tags
}
func (c *aliCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
var ingresses []kops.ApiIngressStatus
func (c *aliCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
var ingresses []fi.ApiIngressStatus
name := "api." + cluster.Name
describeLoadBalancersArgs := &slb.DescribeLoadBalancersArgs{
@ -364,7 +362,7 @@ func (c *aliCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]k
}
address := responseLoadBalancers[0].Address
ingresses = append(ingresses, kops.ApiIngressStatus{IP: address})
ingresses = append(ingresses, fi.ApiIngressStatus{IP: address})
return ingresses, nil
}

View File

@ -87,7 +87,6 @@ go_library(
importpath = "k8s.io/kops/upup/pkg/fi/cloudup/awstasks",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/kops:go_default_library",
"//pkg/diff:go_default_library",
"//pkg/featureflag:go_default_library",
"//pkg/pki:go_default_library",

View File

@ -143,7 +143,7 @@ func (e *AutoscalingGroup) Find(c *fi.Context) (*AutoscalingGroup, error) {
}
}
if apiLBTask != nil && len(actual.LoadBalancers) > 0 {
apiLBDesc, err := FindLoadBalancerByNameTag(c.Cloud.(awsup.AWSCloud), fi.StringValue(apiLBTask.Name))
apiLBDesc, err := c.Cloud.(awsup.AWSCloud).FindELBByNameTag(fi.StringValue(apiLBTask.Name))
if err != nil {
return nil, err
}
@ -335,7 +335,7 @@ func (v *AutoscalingGroup) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Autos
for _, k := range e.LoadBalancers {
if k.LoadBalancerName == nil {
lbDesc, err := FindLoadBalancerByNameTag(t.Cloud, fi.StringValue(k.GetName()))
lbDesc, err := t.Cloud.FindELBByNameTag(fi.StringValue(k.GetName()))
if err != nil {
return err
}

View File

@ -185,67 +185,6 @@ func findLoadBalancerByAlias(cloud awsup.AWSCloud, alias *route53.AliasTarget) (
return found[0], nil
}
func FindLoadBalancerByNameTag(cloud awsup.AWSCloud, findNameTag string) (*elb.LoadBalancerDescription, error) {
// TODO: Any way around this?
klog.V(2).Infof("Listing all ELBs for findLoadBalancerByNameTag")
request := &elb.DescribeLoadBalancersInput{}
// ELB DescribeTags has a limit of 20 names, so we set the page size here to 20 also
request.PageSize = aws.Int64(20)
var found []*elb.LoadBalancerDescription
var innerError error
err := cloud.ELB().DescribeLoadBalancersPages(request, func(p *elb.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancerDescriptions) == 0 {
return true
}
// TODO: Filter by cluster?
var names []string
nameToELB := make(map[string]*elb.LoadBalancerDescription)
for _, elb := range p.LoadBalancerDescriptions {
name := aws.StringValue(elb.LoadBalancerName)
nameToELB[name] = elb
names = append(names, name)
}
tagMap, err := describeLoadBalancerTags(cloud, names)
if err != nil {
innerError = err
return false
}
for loadBalancerName, tags := range tagMap {
name, foundNameTag := awsup.FindELBTag(tags, "Name")
if !foundNameTag || name != findNameTag {
continue
}
elb := nameToELB[loadBalancerName]
found = append(found, elb)
}
return true
})
if err != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", err)
}
if innerError != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", innerError)
}
if len(found) == 0 {
return nil, nil
}
if len(found) != 1 {
return nil, fmt.Errorf("Found multiple ELBs with Name %q", findNameTag)
}
return found[0], nil
}
func describeLoadBalancers(cloud awsup.AWSCloud, request *elb.DescribeLoadBalancersInput, filter func(*elb.LoadBalancerDescription) bool) ([]*elb.LoadBalancerDescription, error) {
var found []*elb.LoadBalancerDescription
err := cloud.ELB().DescribeLoadBalancersPages(request, func(p *elb.DescribeLoadBalancersOutput, lastPage bool) (shouldContinue bool) {
@ -265,26 +204,6 @@ func describeLoadBalancers(cloud awsup.AWSCloud, request *elb.DescribeLoadBalanc
return found, nil
}
func describeLoadBalancerTags(cloud awsup.AWSCloud, loadBalancerNames []string) (map[string][]*elb.Tag, error) {
// TODO: Filter by cluster?
request := &elb.DescribeTagsInput{}
request.LoadBalancerNames = aws.StringSlice(loadBalancerNames)
// TODO: Cache?
klog.V(2).Infof("Querying ELB tags for %s", loadBalancerNames)
response, err := cloud.ELB().DescribeTags(request)
if err != nil {
return nil, err
}
tagMap := make(map[string][]*elb.Tag)
for _, tagset := range response.TagDescriptions {
tagMap[aws.StringValue(tagset.LoadBalancerName)] = tagset.Tags
}
return tagMap, nil
}
func (e *ClassicLoadBalancer) getDNSName() *string {
return e.DNSName
}
@ -296,7 +215,7 @@ func (e *ClassicLoadBalancer) getHostedZoneId() *string {
func (e *ClassicLoadBalancer) Find(c *fi.Context) (*ClassicLoadBalancer, error) {
cloud := c.Cloud.(awsup.AWSCloud)
lb, err := FindLoadBalancerByNameTag(cloud, fi.StringValue(e.Name))
lb, err := cloud.FindELBByNameTag(fi.StringValue(e.Name))
if err != nil {
return nil, err
}
@ -315,7 +234,7 @@ func (e *ClassicLoadBalancer) Find(c *fi.Context) (*ClassicLoadBalancer, error)
actual.Lifecycle = e.Lifecycle
actual.ForAPIServer = e.ForAPIServer
tagMap, err := describeLoadBalancerTags(cloud, []string{*lb.LoadBalancerName})
tagMap, err := cloud.DescribeELBTags([]string{*lb.LoadBalancerName})
if err != nil {
return nil, err
}
@ -433,7 +352,7 @@ func (e *ClassicLoadBalancer) IsForAPIServer() bool {
func (e *ClassicLoadBalancer) FindIPAddress(context *fi.Context) (*string, error) {
cloud := context.Cloud.(awsup.AWSCloud)
lb, err := FindLoadBalancerByNameTag(cloud, fi.StringValue(e.Name))
lb, err := cloud.FindELBByNameTag(fi.StringValue(e.Name))
if err != nil {
return nil, err
}

View File

@ -24,7 +24,6 @@ import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/route53"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awsup"
"k8s.io/kops/upup/pkg/fi/cloudup/cloudformation"
@ -130,49 +129,6 @@ func (e *DNSName) Find(c *fi.Context) (*DNSName, error) {
return actual, nil
}
func FindDNSName(awsCloud awsup.AWSCloud, cluster *kops.Cluster) (string, error) {
name := "api." + cluster.Name
lb, err := FindElasticLoadBalancerByNameTag(awsCloud, cluster)
if err != nil {
return "", fmt.Errorf("error looking for AWS ELB: %v", err)
}
if lb == nil {
return "", nil
}
lbDnsName := aws.StringValue(lb.getDNSName())
if lbDnsName == "" {
return "", fmt.Errorf("found ELB %q, but it did not have a DNSName", name)
}
return lbDnsName, nil
}
func FindElasticLoadBalancerByNameTag(awsCloud awsup.AWSCloud, cluster *kops.Cluster) (DNSTarget, error) {
name := "api." + cluster.Name
if cluster.Spec.API == nil || cluster.Spec.API.LoadBalancer == nil {
return nil, nil
}
if cluster.Spec.API.LoadBalancer.Class == kops.LoadBalancerClassClassic {
if lb, err := FindLoadBalancerByNameTag(awsCloud, name); err != nil {
return nil, fmt.Errorf("error looking for AWS ELB: %v", err)
} else if lb != nil {
return &ClassicLoadBalancer{Name: fi.String(name), DNSName: lb.DNSName}, nil
}
} else if cluster.Spec.API.LoadBalancer.Class == kops.LoadBalancerClassNetwork {
if lb, err := FindNetworkLoadBalancerByNameTag(awsCloud, name); err != nil {
return nil, fmt.Errorf("error looking for AWS NLB: %v", err)
} else if lb != nil {
return &NetworkLoadBalancer{Name: fi.String(name), DNSName: lb.DNSName}, nil
}
}
return nil, nil
}
func findDNSTarget(cloud awsup.AWSCloud, aliasTarget *route53.AliasTarget, dnsName string, targetDNSName *string) (DNSTarget, error) {
//TODO: I would like to search dnsName for presence of ".elb" or ".nlb" to simply searching, however both nlb and elb have .elb. in the name at present
if ELB, err := findDNSTargetELB(cloud, aliasTarget, dnsName, targetDNSName); err != nil {
@ -198,7 +154,7 @@ func findDNSTargetNLB(cloud awsup.AWSCloud, aliasTarget *route53.AliasTarget, dn
if lb != nil {
loadBalancerName := aws.StringValue(lb.LoadBalancerName) //TOOD: can we keep these on object
loadBalancerArn := aws.StringValue(lb.LoadBalancerArn) //TODO: can we keep these on object
tagMap, err := describeNetworkLoadBalancerTags(cloud, []string{loadBalancerArn})
tagMap, err := cloud.DescribeELBV2Tags([]string{loadBalancerArn})
if err != nil {
return nil, err
}
@ -220,7 +176,7 @@ func findDNSTargetELB(cloud awsup.AWSCloud, aliasTarget *route53.AliasTarget, dn
}
if lb != nil {
loadBalancerName := aws.StringValue(lb.LoadBalancerName)
tagMap, err := describeLoadBalancerTags(cloud, []string{loadBalancerName})
tagMap, err := cloud.DescribeELBTags([]string{loadBalancerName})
if err != nil {
return nil, err
}

View File

@ -211,66 +211,6 @@ func findNetworkLoadBalancerByAlias(cloud awsup.AWSCloud, alias *route53.AliasTa
return found[0], nil
}
func FindNetworkLoadBalancerByNameTag(cloud awsup.AWSCloud, findNameTag string) (*elbv2.LoadBalancer, error) {
// TODO: Any way around this?
klog.V(2).Infof("Listing all NLBs for findNetworkLoadBalancerByNameTag")
request := &elbv2.DescribeLoadBalancersInput{}
// ELB DescribeTags has a limit of 20 names, so we set the page size here to 20 also
request.PageSize = aws.Int64(20)
var found []*elbv2.LoadBalancer
var innerError error
err := cloud.ELBV2().DescribeLoadBalancersPages(request, func(p *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancers) == 0 {
return true
}
// TODO: Filter by cluster?
var arns []string
arnToELB := make(map[string]*elbv2.LoadBalancer)
for _, elb := range p.LoadBalancers {
arn := aws.StringValue(elb.LoadBalancerArn)
arnToELB[arn] = elb
arns = append(arns, arn)
}
tagMap, err := describeNetworkLoadBalancerTags(cloud, arns)
if err != nil {
innerError = err
return false
}
for loadBalancerArn, tags := range tagMap {
name, foundNameTag := awsup.FindELBV2Tag(tags, "Name")
if !foundNameTag || name != findNameTag {
continue
}
elb := arnToELB[loadBalancerArn]
found = append(found, elb)
}
return true
})
if err != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", err)
}
if innerError != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", innerError)
}
if len(found) == 0 {
return nil, nil
}
if len(found) != 1 {
return nil, fmt.Errorf("Found multiple NLBs with Name %q", findNameTag)
}
return found[0], nil
}
func describeNetworkLoadBalancers(cloud awsup.AWSCloud, request *elbv2.DescribeLoadBalancersInput, filter func(*elbv2.LoadBalancer) bool) ([]*elbv2.LoadBalancer, error) {
var found []*elbv2.LoadBalancer
err := cloud.ELBV2().DescribeLoadBalancersPages(request, func(p *elbv2.DescribeLoadBalancersOutput, lastPage bool) (shouldContinue bool) {
@ -290,26 +230,6 @@ func describeNetworkLoadBalancers(cloud awsup.AWSCloud, request *elbv2.DescribeL
return found, nil
}
func describeNetworkLoadBalancerTags(cloud awsup.AWSCloud, loadBalancerArns []string) (map[string][]*elbv2.Tag, error) {
// TODO: Filter by cluster?
request := &elbv2.DescribeTagsInput{}
request.ResourceArns = aws.StringSlice(loadBalancerArns)
// TODO: Cache?
klog.V(2).Infof("Querying ELBV2 api for tags for %s", loadBalancerArns)
response, err := cloud.ELBV2().DescribeTags(request)
if err != nil {
return nil, err
}
tagMap := make(map[string][]*elbv2.Tag)
for _, tagset := range response.TagDescriptions {
tagMap[aws.StringValue(tagset.ResourceArn)] = tagset.Tags
}
return tagMap, nil
}
func (e *NetworkLoadBalancer) getDNSName() *string {
return e.DNSName
}
@ -321,7 +241,7 @@ func (e *NetworkLoadBalancer) getHostedZoneId() *string {
func (e *NetworkLoadBalancer) Find(c *fi.Context) (*NetworkLoadBalancer, error) {
cloud := c.Cloud.(awsup.AWSCloud)
lb, err := FindNetworkLoadBalancerByNameTag(cloud, e.Tags["Name"])
lb, err := cloud.FindELBV2ByNameTag(e.Tags["Name"])
if err != nil {
return nil, err
}
@ -340,7 +260,7 @@ func (e *NetworkLoadBalancer) Find(c *fi.Context) (*NetworkLoadBalancer, error)
actual.VPC = &VPC{ID: lb.VpcId}
actual.Type = lb.Type
tagMap, err := describeNetworkLoadBalancerTags(cloud, []string{*loadBalancerArn})
tagMap, err := cloud.DescribeELBV2Tags([]string{*loadBalancerArn})
if err != nil {
return nil, err
}
@ -488,7 +408,7 @@ func (e *NetworkLoadBalancer) IsForAPIServer() bool {
func (e *NetworkLoadBalancer) FindIPAddress(context *fi.Context) (*string, error) {
cloud := context.Cloud.(awsup.AWSCloud)
lb, err := FindNetworkLoadBalancerByNameTag(cloud, e.Tags["Name"])
lb, err := cloud.FindELBV2ByNameTag(e.Tags["Name"])
if err != nil {
return nil, err
}

View File

@ -148,6 +148,11 @@ type AWSCloud interface {
RemoveELBTags(loadBalancerName string, tags map[string]string) error
RemoveELBV2Tags(ResourceArn string, tags map[string]string) error
FindELBByNameTag(findNameTag string) (*elb.LoadBalancerDescription, error)
DescribeELBTags(loadBalancerNames []string) (map[string][]*elb.Tag, error)
FindELBV2ByNameTag(findNameTag string) (*elbv2.LoadBalancer, error)
DescribeELBV2Tags(loadBalancerNames []string) (map[string][]*elbv2.Tag, error)
// DescribeInstance is a helper that queries for the specified instance by id
DescribeInstance(instanceID string) (*ec2.Instance, error)
@ -172,9 +177,6 @@ type AWSCloud interface {
// DescribeInstanceType calls ec2.DescribeInstanceType to get information for a particular instance type
DescribeInstanceType(instanceType string) (*ec2.InstanceTypeInfo, error)
// FindClusterStatus gets the status of the cluster as it exists in AWS, inferred from volumes
FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error)
// AccountInfo returns the AWS account ID and AWS partition that we are deploying into
AccountInfo() (string, string, error)
}
@ -1387,6 +1389,183 @@ func (c *awsCloudImplementation) AddTags(name *string, tags map[string]string) {
}
}
func (c *awsCloudImplementation) FindELBByNameTag(findNameTag string) (*elb.LoadBalancerDescription, error) {
return findELBByNameTag(c, findNameTag)
}
func findELBByNameTag(c AWSCloud, findNameTag string) (*elb.LoadBalancerDescription, error) {
// TODO: Any way around this?
klog.V(2).Infof("Listing all ELBs for findLoadBalancerByNameTag")
request := &elb.DescribeLoadBalancersInput{}
// ELB DescribeTags has a limit of 20 names, so we set the page size here to 20 also
request.PageSize = aws.Int64(20)
var found []*elb.LoadBalancerDescription
var innerError error
err := c.ELB().DescribeLoadBalancersPages(request, func(p *elb.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancerDescriptions) == 0 {
return true
}
// TODO: Filter by cluster?
var names []string
nameToELB := make(map[string]*elb.LoadBalancerDescription)
for _, elb := range p.LoadBalancerDescriptions {
name := aws.StringValue(elb.LoadBalancerName)
nameToELB[name] = elb
names = append(names, name)
}
tagMap, err := c.DescribeELBTags(names)
if err != nil {
innerError = err
return false
}
for loadBalancerName, tags := range tagMap {
name, foundNameTag := FindELBTag(tags, "Name")
if !foundNameTag || name != findNameTag {
continue
}
elb := nameToELB[loadBalancerName]
found = append(found, elb)
}
return true
})
if err != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", err)
}
if innerError != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", innerError)
}
if len(found) == 0 {
return nil, nil
}
if len(found) != 1 {
return nil, fmt.Errorf("Found multiple ELBs with Name %q", findNameTag)
}
return found[0], nil
}
func (c *awsCloudImplementation) DescribeELBTags(loadBalancerNames []string) (map[string][]*elb.Tag, error) {
return describeELBTags(c, loadBalancerNames)
}
func describeELBTags(c AWSCloud, loadBalancerNames []string) (map[string][]*elb.Tag, error) {
// TODO: Filter by cluster?
request := &elb.DescribeTagsInput{}
request.LoadBalancerNames = aws.StringSlice(loadBalancerNames)
// TODO: Cache?
klog.V(2).Infof("Querying ELB tags for %s", loadBalancerNames)
response, err := c.ELB().DescribeTags(request)
if err != nil {
return nil, err
}
tagMap := make(map[string][]*elb.Tag)
for _, tagset := range response.TagDescriptions {
tagMap[aws.StringValue(tagset.LoadBalancerName)] = tagset.Tags
}
return tagMap, nil
}
func (c *awsCloudImplementation) FindELBV2ByNameTag(findNameTag string) (*elbv2.LoadBalancer, error) {
return findELBV2ByNameTag(c, findNameTag)
}
func findELBV2ByNameTag(c AWSCloud, findNameTag string) (*elbv2.LoadBalancer, error) {
// TODO: Any way around this?
klog.V(2).Infof("Listing all NLBs for findNetworkLoadBalancerByNameTag")
request := &elbv2.DescribeLoadBalancersInput{}
// ELB DescribeTags has a limit of 20 names, so we set the page size here to 20 also
request.PageSize = aws.Int64(20)
var found []*elbv2.LoadBalancer
var innerError error
err := c.ELBV2().DescribeLoadBalancersPages(request, func(p *elbv2.DescribeLoadBalancersOutput, lastPage bool) bool {
if len(p.LoadBalancers) == 0 {
return true
}
// TODO: Filter by cluster?
var arns []string
arnToELB := make(map[string]*elbv2.LoadBalancer)
for _, elb := range p.LoadBalancers {
arn := aws.StringValue(elb.LoadBalancerArn)
arnToELB[arn] = elb
arns = append(arns, arn)
}
tagMap, err := c.DescribeELBV2Tags(arns)
if err != nil {
innerError = err
return false
}
for loadBalancerArn, tags := range tagMap {
name, foundNameTag := FindELBV2Tag(tags, "Name")
if !foundNameTag || name != findNameTag {
continue
}
elb := arnToELB[loadBalancerArn]
found = append(found, elb)
}
return true
})
if err != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", err)
}
if innerError != nil {
return nil, fmt.Errorf("error describing LoadBalancers: %v", innerError)
}
if len(found) == 0 {
return nil, nil
}
if len(found) != 1 {
return nil, fmt.Errorf("Found multiple NLBs with Name %q", findNameTag)
}
return found[0], nil
}
func (c *awsCloudImplementation) DescribeELBV2Tags(loadBalancerArns []string) (map[string][]*elbv2.Tag, error) {
return describeELBV2Tags(c, loadBalancerArns)
}
func describeELBV2Tags(c AWSCloud, loadBalancerArns []string) (map[string][]*elbv2.Tag, error) {
// TODO: Filter by cluster?
request := &elbv2.DescribeTagsInput{}
request.ResourceArns = aws.StringSlice(loadBalancerArns)
// TODO: Cache?
klog.V(2).Infof("Querying ELBV2 api for tags for %s", loadBalancerArns)
response, err := c.ELBV2().DescribeTags(request)
if err != nil {
return nil, err
}
tagMap := make(map[string][]*elbv2.Tag)
for _, tagset := range response.TagDescriptions {
tagMap[aws.StringValue(tagset.ResourceArn)] = tagset.Tags
}
return tagMap, nil
}
func (c *awsCloudImplementation) BuildFilters(name *string) []*ec2.Filter {
return buildFilters(c.tags, name)
}
@ -1686,6 +1865,42 @@ func findVPCInfo(c AWSCloud, vpcID string) (*fi.VPCInfo, error) {
return vpcInfo, nil
}
func (c *awsCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return getApiIngressStatus(c, cluster)
}
func getApiIngressStatus(c AWSCloud, cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
var ingresses []fi.ApiIngressStatus
if lbDnsName, err := findDNSName(c, cluster); err != nil {
return nil, fmt.Errorf("error finding aws DNSName: %v", err)
} else if lbDnsName != "" {
ingresses = append(ingresses, fi.ApiIngressStatus{Hostname: lbDnsName})
}
return ingresses, nil
}
func findDNSName(c AWSCloud, cluster *kops.Cluster) (string, error) {
name := "api." + cluster.Name
if cluster.Spec.API == nil || cluster.Spec.API.LoadBalancer == nil {
return "", nil
}
if cluster.Spec.API.LoadBalancer.Class == kops.LoadBalancerClassClassic {
if lb, err := c.FindELBByNameTag(name); err != nil {
return "", fmt.Errorf("error looking for AWS ELB: %v", err)
} else if lb != nil {
return aws.StringValue(lb.DNSName), nil
}
} else if cluster.Spec.API.LoadBalancer.Class == kops.LoadBalancerClassNetwork {
if lb, err := c.FindELBV2ByNameTag(name); err != nil {
return "", fmt.Errorf("error looking for AWS NLB: %v", err)
} else if lb != nil {
return aws.StringValue(lb.DNSName), nil
}
}
return "", nil
}
// DefaultInstanceType determines an instance type for the specified cluster & instance group
func (c *awsCloudImplementation) DefaultInstanceType(cluster *kops.Cluster, ig *kops.InstanceGroup) (string, error) {
var candidates []string

View File

@ -19,18 +19,19 @@ package awsup
import (
"fmt"
"github.com/aws/aws-sdk-go/service/eventbridge/eventbridgeiface"
"github.com/aws/aws-sdk-go/service/sqs/sqsiface"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/autoscaling/autoscalingiface"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/ec2/ec2iface"
"github.com/aws/aws-sdk-go/service/elb"
"github.com/aws/aws-sdk-go/service/elb/elbiface"
"github.com/aws/aws-sdk-go/service/elbv2"
"github.com/aws/aws-sdk-go/service/elbv2/elbv2iface"
"github.com/aws/aws-sdk-go/service/eventbridge/eventbridgeiface"
"github.com/aws/aws-sdk-go/service/iam/iamiface"
"github.com/aws/aws-sdk-go/service/route53/route53iface"
"github.com/aws/aws-sdk-go/service/sqs/sqsiface"
v1 "k8s.io/api/core/v1"
"k8s.io/klog/v2"
"k8s.io/kops/dnsprovider/pkg/dnsprovider"
@ -191,6 +192,22 @@ func (c *MockAWSCloud) RemoveELBV2Tags(ResourceArn string, tags map[string]strin
return removeELBV2Tags(c, ResourceArn, tags)
}
func (c *MockAWSCloud) FindELBByNameTag(findNameTag string) (*elb.LoadBalancerDescription, error) {
return findELBByNameTag(c, findNameTag)
}
func (c *MockAWSCloud) DescribeELBTags(loadBalancerNames []string) (map[string][]*elb.Tag, error) {
return describeELBTags(c, loadBalancerNames)
}
func (c *MockAWSCloud) FindELBV2ByNameTag(findNameTag string) (*elbv2.LoadBalancer, error) {
return findELBV2ByNameTag(c, findNameTag)
}
func (c *MockAWSCloud) DescribeELBV2Tags(loadBalancerArns []string) (map[string][]*elbv2.Tag, error) {
return describeELBV2Tags(c, loadBalancerArns)
}
func (c *MockAWSCloud) DescribeInstance(instanceID string) (*ec2.Instance, error) {
return nil, fmt.Errorf("MockAWSCloud DescribeInstance not implemented")
}
@ -284,6 +301,10 @@ func (c *MockAWSCloud) FindVPCInfo(id string) (*fi.VPCInfo, error) {
return findVPCInfo(c, id)
}
func (c *MockAWSCloud) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return getApiIngressStatus(c, cluster)
}
// DefaultInstanceType determines an instance type for the specified cluster & instance group
func (c *MockAWSCloud) DefaultInstanceType(cluster *kops.Cluster, ig *kops.InstanceGroup) (string, error) {
switch ig.Spec.Role {

View File

@ -42,8 +42,6 @@ type AzureCloud interface {
fi.Cloud
AddClusterTags(tags map[string]*string)
FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error)
GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error)
SubscriptionID() string
ResourceGroup() ResourceGroupsClient
@ -138,8 +136,8 @@ func (c *azureCloudImplementation) AddClusterTags(tags map[string]*string) {
}
}
func (c *azureCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
var ingresses []kops.ApiIngressStatus
func (c *azureCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
var ingresses []fi.ApiIngressStatus
var rg string = cluster.AzureResourceGroupName()
lbSpec := cluster.Spec.API.LoadBalancer
@ -167,7 +165,7 @@ func (c *azureCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([
if i.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress == nil {
continue
}
ingresses = append(ingresses, kops.ApiIngressStatus{
ingresses = append(ingresses, fi.ApiIngressStatus{
IP: *i.FrontendIPConfigurationPropertiesFormat.PrivateIPAddress,
})
case kops.LoadBalancerTypePublic:
@ -176,7 +174,7 @@ func (c *azureCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([
i.FrontendIPConfigurationPropertiesFormat.PublicIPAddress.PublicIPAddressPropertiesFormat.IPAddress == nil {
continue
}
ingresses = append(ingresses, kops.ApiIngressStatus{
ingresses = append(ingresses, fi.ApiIngressStatus{
IP: *i.FrontendIPConfigurationPropertiesFormat.PublicIPAddress.PublicIPAddressPropertiesFormat.IPAddress,
})
default:
@ -213,7 +211,7 @@ func (c *azureCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([
continue
}
for _, i := range *ni.IPConfigurations {
ingresses = append(ingresses, kops.ApiIngressStatus{
ingresses = append(ingresses, fi.ApiIngressStatus{
IP: *i.PrivateIPAddress,
})
}

View File

@ -158,7 +158,7 @@ func (c *MockAzureCloud) FindClusterStatus(cluster *kops.Cluster) (*kops.Cluster
}
// GetApiIngressStatus returns the status of API ingress.
func (c *MockAzureCloud) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
func (c *MockAzureCloud) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return nil, nil
}

View File

@ -45,12 +45,8 @@ type GCECloud interface {
Project() string
WaitForOp(op *compute.Operation) error
GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error)
Labels() map[string]string
// FindClusterStatus gets the status of the cluster as it exists in GCE, inferred from volumes
FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error)
Zones() ([]string, error)
// ServiceAccount returns the email for the service account that the instances will run under
@ -288,8 +284,8 @@ func (c *gceCloudImplementation) WaitForOp(op *compute.Operation) error {
return WaitForOp(c.compute.srv, op)
}
func (c *gceCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
var ingresses []kops.ApiIngressStatus
func (c *gceCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
var ingresses []fi.ApiIngressStatus
// Note that this must match GCEModelContext::NameForForwardingRule
name := SafeObjectName("api", cluster.ObjectMeta.Name)
@ -309,7 +305,7 @@ func (c *gceCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]k
return nil, fmt.Errorf("found forward rule %q, but it did not have an IPAddress", name)
}
ingresses = append(ingresses, kops.ApiIngressStatus{
ingresses = append(ingresses, fi.ApiIngressStatus{
IP: forwardingRule.IPAddress,
})
}

View File

@ -79,6 +79,7 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/kops:go_default_library",
"//upup/pkg/fi:go_default_library",
"//vendor/github.com/gophercloud/gophercloud:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers:go_default_library",

View File

@ -264,10 +264,6 @@ type OpenstackCloud interface {
// DeleteLB will delete loadbalancer
DeleteLB(lbID string, opt loadbalancers.DeleteOpts) error
GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error)
FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatus, error)
// DefaultInstanceType determines a suitable instance type for the specified instance group
DefaultInstanceType(cluster *kops.Cluster, ig *kops.InstanceGroup) (string, error)
@ -664,11 +660,11 @@ type Address struct {
Addr string
}
func (c *openstackCloud) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
func (c *openstackCloud) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return getApiIngressStatus(c, cluster)
}
func getApiIngressStatus(c OpenstackCloud, cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
func getApiIngressStatus(c OpenstackCloud, cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
if cluster.Spec.CloudConfig.Openstack.Loadbalancer != nil {
return getLoadBalancerIngressStatus(c, cluster)
} else {
@ -676,8 +672,8 @@ func getApiIngressStatus(c OpenstackCloud, cluster *kops.Cluster) ([]kops.ApiIng
}
}
func getLoadBalancerIngressStatus(c OpenstackCloud, cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
var ingresses []kops.ApiIngressStatus
func getLoadBalancerIngressStatus(c OpenstackCloud, cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
var ingresses []fi.ApiIngressStatus
if cluster.Spec.MasterPublicName != "" {
// Note that this must match OpenstackModel lb name
klog.V(2).Infof("Querying Openstack to find Loadbalancers for API (%q)", cluster.Name)
@ -697,7 +693,7 @@ func getLoadBalancerIngressStatus(c OpenstackCloud, cluster *kops.Cluster) ([]ko
}
for _, fip := range fips {
if fip.PortID == lb.VipPortID {
ingresses = append(ingresses, kops.ApiIngressStatus{
ingresses = append(ingresses, fi.ApiIngressStatus{
IP: fip.FloatingIP,
})
}
@ -707,7 +703,7 @@ func getLoadBalancerIngressStatus(c OpenstackCloud, cluster *kops.Cluster) ([]ko
return ingresses, nil
}
func getIPIngressStatus(c OpenstackCloud, cluster *kops.Cluster) (ingresses []kops.ApiIngressStatus, err error) {
func getIPIngressStatus(c OpenstackCloud, cluster *kops.Cluster) (ingresses []fi.ApiIngressStatus, err error) {
done, err := vfs.RetryWithBackoff(readBackoff, func() (bool, error) {
instances, err := c.ListInstances(servers.ListOpts{})
if err != nil {
@ -725,7 +721,7 @@ func getIPIngressStatus(c OpenstackCloud, cluster *kops.Cluster) (ingresses []ko
if err != nil {
return false, fmt.Errorf("failed to get interface address: %v", err)
}
ingresses = append(ingresses, kops.ApiIngressStatus{
ingresses = append(ingresses, fi.ApiIngressStatus{
IP: address,
})
} else {
@ -734,7 +730,7 @@ func getIPIngressStatus(c OpenstackCloud, cluster *kops.Cluster) (ingresses []ko
return false, err
}
for _, ip := range ips {
ingresses = append(ingresses, kops.ApiIngressStatus{
ingresses = append(ingresses, fi.ApiIngressStatus{
IP: fi.StringValue(ip),
})
}

View File

@ -31,6 +31,7 @@ import (
l3floatingips "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/floatingips"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi"
)
func Test_OpenstackCloud_GetApiIngressStatus(t *testing.T) {
@ -41,7 +42,7 @@ func Test_OpenstackCloud_GetApiIngressStatus(t *testing.T) {
l3FloatingIPs []l3floatingips.FloatingIP
instances serverList
cloudFloatingEnabled bool
expectedAPIIngress []kops.ApiIngressStatus
expectedAPIIngress []fi.ApiIngressStatus
expectedError error
}{
{
@ -74,7 +75,7 @@ func Test_OpenstackCloud_GetApiIngressStatus(t *testing.T) {
FloatingIP: "8.8.8.8",
},
},
expectedAPIIngress: []kops.ApiIngressStatus{
expectedAPIIngress: []fi.ApiIngressStatus{
{
IP: "8.8.8.8",
},
@ -122,7 +123,7 @@ func Test_OpenstackCloud_GetApiIngressStatus(t *testing.T) {
FloatingIP: "9.9.9.9",
},
},
expectedAPIIngress: []kops.ApiIngressStatus{
expectedAPIIngress: []fi.ApiIngressStatus{
{IP: "8.8.8.8"},
},
},
@ -200,7 +201,7 @@ func Test_OpenstackCloud_GetApiIngressStatus(t *testing.T) {
},
},
},
expectedAPIIngress: []kops.ApiIngressStatus{
expectedAPIIngress: []fi.ApiIngressStatus{
{IP: "1.2.3.4"},
{IP: "2.3.4.5"},
{IP: "3.4.5.6"},
@ -273,7 +274,7 @@ func Test_OpenstackCloud_GetApiIngressStatus(t *testing.T) {
},
},
cloudFloatingEnabled: true,
expectedAPIIngress: []kops.ApiIngressStatus{
expectedAPIIngress: []fi.ApiIngressStatus{
{IP: "1.2.3.4"},
{IP: "4.5.6.7"},
{IP: "40.50.60.70"},
@ -390,7 +391,7 @@ func Test_OpenstackCloud_GetApiIngressStatus(t *testing.T) {
}
}
type sortByIP []kops.ApiIngressStatus
type sortByIP []fi.ApiIngressStatus
// Len is the number of elements in the collection.
func (s sortByIP) Len() int {

View File

@ -303,7 +303,7 @@ func (c *MockCloud) FindClusterStatus(cluster *kops.Cluster) (*kops.ClusterStatu
func (c *MockCloud) FindNetworkBySubnetID(subnetID string) (*networks.Network, error) {
return findNetworkBySubnetID(c, subnetID)
}
func (c *MockCloud) GetApiIngressStatus(cluster *kops.Cluster) ([]kops.ApiIngressStatus, error) {
func (c *MockCloud) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
return getApiIngressStatus(c, cluster)
}
func (c *MockCloud) GetCloudTags() map[string]string {

View File

@ -353,8 +353,7 @@ func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
if e.LoadBalancer != nil &&
fi.StringValue(name) != fi.StringValue(e.LoadBalancer.Name) {
nlb, err := awstasks.FindNetworkLoadBalancerByNameTag(
cloud, fi.StringValue(e.LoadBalancer.Name))
nlb, err := cloud.FindELBV2ByNameTag(fi.StringValue(e.LoadBalancer.Name))
if err != nil {
return nil, err
}
@ -362,8 +361,7 @@ func (e *Elastigroup) Find(c *fi.Context) (*Elastigroup, error) {
actual.LoadBalancer = e.LoadBalancer
}
elb, err := awstasks.FindLoadBalancerByNameTag(
cloud, fi.StringValue(e.LoadBalancer.Name))
elb, err := cloud.FindELBByNameTag(fi.StringValue(e.LoadBalancer.Name))
if err != nil {
return nil, err
}
@ -642,7 +640,7 @@ func (_ *Elastigroup) create(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
// Load balancer.
{
if e.LoadBalancer != nil {
elb, err := awstasks.FindLoadBalancerByNameTag(cloud, fi.StringValue(e.LoadBalancer.Name))
elb, err := cloud.FindELBByNameTag(fi.StringValue(e.LoadBalancer.Name))
if err != nil {
return err
}
@ -659,7 +657,7 @@ func (_ *Elastigroup) create(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
//TODO: Verify using NLB functionality
//TODO: Consider using DNSTarget Interface and adding .getLoadBalancerName() .getLoadBalancerArn
nlb, err := awstasks.FindNetworkLoadBalancerByNameTag(cloud, fi.StringValue(e.LoadBalancer.Name))
nlb, err := cloud.FindELBV2ByNameTag(fi.StringValue(e.LoadBalancer.Name))
if err != nil {
return err
}
@ -1159,8 +1157,7 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
var name, typ *string
var lb interface{}
lb, err = awstasks.FindLoadBalancerByNameTag(
cloud, fi.StringValue(e.LoadBalancer.Name))
lb, err = cloud.FindELBByNameTag(fi.StringValue(e.LoadBalancer.Name))
if err != nil {
return fmt.Errorf("spotinst: error looking for aws/elb: %v", err)
}
@ -1168,8 +1165,7 @@ func (_ *Elastigroup) update(cloud awsup.AWSCloud, a, e, changes *Elastigroup) e
typ = fi.String("CLASSIC")
name = lb.(*elb.LoadBalancerDescription).LoadBalancerName
} else {
lb, err = awstasks.FindNetworkLoadBalancerByNameTag(
cloud, fi.StringValue(e.LoadBalancer.Name))
lb, err = cloud.FindELBV2ByNameTag(fi.StringValue(e.LoadBalancer.Name))
if err != nil {
return fmt.Errorf("spotinst: error looking for aws/nlb: %v", err)
}