diff --git a/Makefile b/Makefile index 9bce4e6af4..26b1f05e2a 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,6 @@ PKG := $(shell awk -F "\"" '/^ignored = / { print $$2 }' Gopkg.toml) DEST := $(GOPATH)/src/$(GIT_HOST)/$(BASE_DIR) SOURCES := $(shell find $(DEST) -name '*.go') -HAS_MERCURIAL := $(shell command -v hg;) HAS_DEP := $(shell command -v dep;) HAS_LINT := $(shell command -v golint;) HAS_GOX := $(shell command -v gox;) @@ -68,7 +67,7 @@ test: unit functional check: depend fmt vet lint -unit: depend +unit: generate depend go test -tags=unit $(shell go list ./...) $(TESTARGS) functional: @@ -87,7 +86,7 @@ endif vet: go vet ./... -cover: depend +cover: generate depend go test -tags=unit $(shell go list ./...) -cover docs: diff --git a/README.md b/README.md index 16e602f20c..2b005e1eb1 100644 --- a/README.md +++ b/README.md @@ -197,3 +197,7 @@ your openstack Cluster API Kubernetes cluster. ```bash rm -rf $HOME/.ssh/openstack_tmp* ``` + +### Trouble shooting + +Please refer to [Trouble shooting documentation](docs/trouble_shooting.md) for further info. diff --git a/config/crds/openstackproviderconfig_v1alpha1_openstackclusterproviderspec.yaml b/config/crds/openstackproviderconfig_v1alpha1_openstackclusterproviderspec.yaml index c060d199b1..506d4a7491 100644 --- a/config/crds/openstackproviderconfig_v1alpha1_openstackclusterproviderspec.yaml +++ b/config/crds/openstackproviderconfig_v1alpha1_openstackclusterproviderspec.yaml @@ -15,24 +15,50 @@ spec: openAPIV3Schema: properties: apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string + cloudName: + description: The name of the cloud to use from the clouds secret + type: string + cloudsSecret: + description: The name of the secret containing the openstack credentials + type: object disableServerTags: + description: 'Default: True. In case of server tag errors, set to False' type: boolean dnsNameservers: + description: DNSNameservers is the list of nameservers for OpenStack Subnet + being created. items: type: string type: array externalNetworkId: + description: ExternalNetworkID is the ID of an external OpenStack Network. + This is necessary to get public internet to the VMs. type: string kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string managedSecurityGroups: + description: ManagedSecurityGroups defines that kubernetes manages the OpenStack + security groups for now, that means that we'll create two security groups, + one allowing SSH and API access from everywhere, and another one that + allows all traffic to/from machines belonging to that group. In the future, + we could make this more flexible. type: boolean metadata: type: object nodeCidr: + description: NodeCIDR is the OpenStack Subnet to be created. Cluster actuator + will create a network, a subnet with NodeCIDR, and a router connected + to this subnet. If you leave this empty, no network will be created. type: string tags: + description: Tags for all resources in cluster items: type: string type: array diff --git a/config/crds/openstackproviderconfig_v1alpha1_openstackclusterproviderstatus.yaml b/config/crds/openstackproviderconfig_v1alpha1_openstackclusterproviderstatus.yaml index 690cc360d6..be866d07dc 100644 --- a/config/crds/openstackproviderconfig_v1alpha1_openstackclusterproviderstatus.yaml +++ b/config/crds/openstackproviderconfig_v1alpha1_openstackclusterproviderstatus.yaml @@ -15,8 +15,15 @@ spec: openAPIV3Schema: properties: apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string controlPlaneSecurityGroup: + description: 'ControlPlaneSecurityGroups contains all the information about + the OpenStack Security Group that needs to be applied to control plane + nodes. TODO: Maybe instead of two properties, we add a property to the + group?' properties: id: type: string @@ -63,6 +70,9 @@ spec: - rules type: object globalSecurityGroup: + description: GlobalSecurityGroup contains all the information about the + OpenStack Security Group that needs to be applied to all nodes, both control + plane and worker nodes. properties: id: type: string @@ -109,10 +119,15 @@ spec: - rules type: object kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string metadata: type: object network: + description: Network contains all information about the created OpenStack + Network. It includes Subnets and Router. properties: id: type: string diff --git a/config/crds/openstackproviderconfig_v1alpha1_openstackproviderspec.yaml b/config/crds/openstackproviderconfig_v1alpha1_openstackproviderspec.yaml index 3c1405ba67..43bc624cee 100644 --- a/config/crds/openstackproviderconfig_v1alpha1_openstackproviderspec.yaml +++ b/config/crds/openstackproviderconfig_v1alpha1_openstackproviderspec.yaml @@ -15,31 +15,53 @@ spec: openAPIV3Schema: properties: apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources' type: string availabilityZone: + description: The availability zone from which to launch the server. type: string cloudName: + description: The name of the cloud to use from the clouds secret type: string cloudsSecret: + description: The name of the secret containing the openstack credentials type: object configDrive: + description: Config Drive support type: boolean flavor: + description: The flavor reference for the flavor for your server instance. type: string floatingIP: + description: The floatingIP which will be associated to the machine, only + used for master. The floatingIP should have been created and haven't been + associated. type: string image: + description: The name of the image to use for your server instance. If the + RootVolume is specified, this will be ignored and use rootVolume directly. type: string keyName: + description: The ssh key to inject in the instance type: string kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' type: string metadata: type: object networks: + description: A networks object. Required parameter when there are multiple + networks defined for the tenant. When you do not specify the networks + parameter, the server attaches to the only network created for the current + tenant. items: properties: filter: + description: Filters for optional network query properties: adminStateUp: type: boolean @@ -76,11 +98,14 @@ spec: type: string type: object fixedIp: + description: A fixed IPv4 address for the NIC. type: string subnets: + description: Subnet within a network to use items: properties: filter: + description: Filters for optional network query properties: cidr: type: string @@ -93,6 +118,10 @@ spec: ipVersion: format: int64 type: integer + ipv6AddressMode: + type: string + ipv6RaMode: + type: string limit: format: int64 type: integer @@ -122,14 +151,19 @@ spec: type: string type: object uuid: + description: The UUID of the network. Required if you omit the + port attribute. type: string type: object type: array uuid: + description: The UUID of the network. Required if you omit the port + attribute. type: string type: object type: array rootVolume: + description: The volume metadata to boot from properties: deviceType: type: string @@ -144,9 +178,11 @@ spec: - deviceType type: object securityGroups: + description: The names of the security groups to assign to the instance items: properties: filter: + description: Filters used to query security groups in openstack properties: description: type: string @@ -177,22 +213,31 @@ spec: type: string type: object name: + description: Security Group name type: string uuid: + description: Security Group UID type: string type: object type: array serverMetadata: + description: Metadata mapping. Allows you to create a map of key value pairs + to add to the server instance. type: object sshUserName: + description: The machine ssh username type: string tags: + description: Machine tags Requires Nova api 2.52 minimum! items: type: string type: array trunk: + description: Whether the server instance is created on a trunk port or not. type: boolean userDataSecret: + description: The name of the secret containing the user data (startup script + in most cases) type: object required: - cloudsSecret diff --git a/config/manager/deployment.yaml b/config/manager/deployment.yaml index 2a2d840d3f..b324d1ef58 100644 --- a/config/manager/deployment.yaml +++ b/config/manager/deployment.yaml @@ -8,6 +8,10 @@ metadata: controller-tools.k8s.io: "1.0" spec: replicas: 1 + selector: + matchLabels: + control-plane: controller-manager + controller-tools.k8s.io: "1.0" template: metadata: labels: diff --git a/config/rbac/rbac_role.yaml b/config/rbac/rbac_role.yaml index 2530cd1cc5..5c557468f2 100644 --- a/config/rbac/rbac_role.yaml +++ b/config/rbac/rbac_role.yaml @@ -36,6 +36,7 @@ rules: - "" resources: - nodes + - events verbs: - get - list diff --git a/docs/config.md b/docs/config.md index f3ccde4cf1..c3a81cf1a4 100644 --- a/docs/config.md +++ b/docs/config.md @@ -257,3 +257,9 @@ Instead of tagging, you also have the option to add metadata to instances. This securityGroups: ... ``` + +## Timeout settings +During some heavy workload cloud, the time for create and delete openstack instance might takes long time, by default it's 5 minute. +you can set: +`CLUSTER_API_OPENSTACK_INSTANCE_DELETE_TIMEOUT` for instance delete timeout value. +`CLUSTER_API_OPENSTACK_INSTANCE_CREATE_TIMEOUT` for instance create timeout value. diff --git a/docs/trouble_shooting.md b/docs/trouble_shooting.md new file mode 100644 index 0000000000..86d5d6d1d3 --- /dev/null +++ b/docs/trouble_shooting.md @@ -0,0 +1,20 @@ +# Trouble shooting + +This guide (based on minikube and others should be similar) explains general info on how to debug issues if cluster failed to create. + +## Get log of clusterapi-controllers containers + +1. Get openstack container name, the output depends on the system you are running. + the `minikube.kubeconfig` which is bootstrap cluster's kubeconfig by default locates at `cmd/clusterctl` folder. + + ``` + # kubectl --kubeconfig minikube.kubeconfig get pods -n openstack-provider-system + NAMESPACE NAME READY STATUS RESTARTS AGE + openstack-provider-system clusterapi-controllers-xxxxxxxxx-xxxxx 1/1 Running 0 27m + ``` + +2. Get log of clusterapi-controllers-xxxxxxxx-xxxxx + + ``` + # kubectl --kubeconfig minikube.kubeconfig log clusterapi-controllers-xxxxxxxxx-xxxxx -n openstack-provider-system + ``` diff --git a/overlays-config/coreos/manager/deployment.yaml b/overlays-config/coreos/manager/deployment.yaml index 924079b9e0..4329f391da 100644 --- a/overlays-config/coreos/manager/deployment.yaml +++ b/overlays-config/coreos/manager/deployment.yaml @@ -7,6 +7,10 @@ metadata: control-plane: controller-manager controller-tools.k8s.io: "1.0" spec: + selector: + matchLabels: + control-plane: controller-manager + controller-tools.k8s.io: "1.0" template: spec: volumes: diff --git a/overlays-config/generic/manager/deployment.yaml b/overlays-config/generic/manager/deployment.yaml index 5cdc5a0c25..2f0d2fbb94 100644 --- a/overlays-config/generic/manager/deployment.yaml +++ b/overlays-config/generic/manager/deployment.yaml @@ -7,6 +7,10 @@ metadata: control-plane: controller-manager controller-tools.k8s.io: "1.0" spec: + selector: + matchLabels: + control-plane: controller-manager + controller-tools.k8s.io: "1.0" template: spec: volumes: diff --git a/pkg/apis/openstackproviderconfig/v1alpha1/types.go b/pkg/apis/openstackproviderconfig/v1alpha1/types.go index 28b4b56752..2e6347eb99 100644 --- a/pkg/apis/openstackproviderconfig/v1alpha1/types.go +++ b/pkg/apis/openstackproviderconfig/v1alpha1/types.go @@ -220,12 +220,6 @@ type OpenstackClusterProviderStatus struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - // CACertificate is a PEM encoded CA Certificate for the control plane nodes. - CACertificate []byte - - // CAPrivateKey is a PEM encoded PKCS1 CA PrivateKey for the control plane nodes. - CAPrivateKey []byte - // Network contains all information about the created OpenStack Network. // It includes Subnets and Router. Network *Network `json:"network,omitempty"` diff --git a/pkg/apis/openstackproviderconfig/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/openstackproviderconfig/v1alpha1/zz_generated.deepcopy.go index f45d83dcbe..93d5f93764 100644 --- a/pkg/apis/openstackproviderconfig/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/openstackproviderconfig/v1alpha1/zz_generated.deepcopy.go @@ -111,6 +111,11 @@ func (in *OpenstackClusterProviderSpec) DeepCopyInto(out *OpenstackClusterProvid *out = make([]string, len(*in)) copy(*out, *in) } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } return } @@ -137,16 +142,6 @@ func (in *OpenstackClusterProviderStatus) DeepCopyInto(out *OpenstackClusterProv *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - if in.CACertificate != nil { - in, out := &in.CACertificate, &out.CACertificate - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.CAPrivateKey != nil { - in, out := &in.CAPrivateKey, &out.CAPrivateKey - *out = make([]byte, len(*in)) - copy(*out, *in) - } if in.Network != nil { in, out := &in.Network, &out.Network *out = new(Network) @@ -210,9 +205,11 @@ func (in *OpenstackProviderSpec) DeepCopyInto(out *OpenstackProviderSpec) { *out = new(v1.SecretReference) **out = **in } - out.RootVolume = in.RootVolume - out.Tags = in.Tags - + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } if in.ServerMetadata != nil { in, out := &in.ServerMetadata, &out.ServerMetadata *out = make(map[string]string, len(*in)) @@ -220,6 +217,16 @@ func (in *OpenstackProviderSpec) DeepCopyInto(out *OpenstackProviderSpec) { (*out)[key] = val } } + if in.ConfigDrive != nil { + in, out := &in.ConfigDrive, &out.ConfigDrive + *out = new(bool) + **out = **in + } + if in.RootVolume != nil { + in, out := &in.RootVolume, &out.RootVolume + *out = new(RootVolume) + **out = **in + } return } diff --git a/pkg/cloud/openstack/clients/machineservice.go b/pkg/cloud/openstack/clients/machineservice.go index 4569239079..913fd89742 100644 --- a/pkg/cloud/openstack/clients/machineservice.go +++ b/pkg/cloud/openstack/clients/machineservice.go @@ -104,7 +104,7 @@ func GetCloudFromSecret(kubeClient kubernetes.Interface, namespace string, secre secret, err := kubeClient.CoreV1().Secrets(namespace).Get(secretName, metav1.GetOptions{}) if err != nil { - return emptyCloud, err + return emptyCloud, fmt.Errorf("Failed to get secrets from kubernetes api: %v", err) } content, ok := secret.Data[CloudsSecretKey] @@ -125,7 +125,7 @@ func GetCloudFromSecret(kubeClient kubernetes.Interface, namespace string, secre func NewInstanceServiceFromMachine(kubeClient kubernetes.Interface, machine *machinev1.Machine) (*InstanceService, error) { machineSpec, err := openstackconfigv1.MachineSpecFromProviderSpec(machine.Spec.ProviderSpec) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to get Machine Spec from Provider Spec (clients/machineservice.go 138): %v", err) } cloud := clientconfig.Cloud{} if machineSpec.CloudsSecret != nil && machineSpec.CloudsSecret.Name != "" { @@ -135,7 +135,7 @@ func NewInstanceServiceFromMachine(kubeClient kubernetes.Interface, machine *mac } cloud, err = GetCloudFromSecret(kubeClient, namespace, machineSpec.CloudsSecret.Name, machineSpec.CloudName) if err != nil { - return nil, err + return nil, fmt.Errorf("Failed to get cloud from secret (clients/machienservice.go 150): %v", err) } } return NewInstanceServiceFromCloud(cloud) diff --git a/pkg/cloud/openstack/clients/secgroupservice.go b/pkg/cloud/openstack/clients/secgroupservice.go index 1cf3530fd2..76a85c7352 100644 --- a/pkg/cloud/openstack/clients/secgroupservice.go +++ b/pkg/cloud/openstack/clients/secgroupservice.go @@ -111,7 +111,35 @@ func (s *SecGroupService) Reconcile(clusterName string, desired openstackconfigv status.GlobalSecurityGroup = observedSecGroups["global"] return nil +} + +func (s *SecGroupService) Delete(group *openstackconfigv1.SecurityGroup) error { + exists, err := s.exists(group.ID) + if err != nil { + return err + } + if exists { + return groups.Delete(s.client, group.ID).ExtractErr() + } + return nil +} +func (s *SecGroupService) exists(groupID string) (bool, error) { + opts := groups.ListOpts{ + ID: groupID, + } + allPages, err := groups.List(s.client, opts).AllPages() + if err != nil { + return false, err + } + allGroups, err := groups.ExtractGroups(allPages) + if err != nil { + return false, err + } + if len(allGroups) == 0 { + return false, nil + } + return true, nil } func (s *SecGroupService) generateControlPlaneGroup(clusterName string) openstackconfigv1.SecurityGroup { diff --git a/pkg/cloud/openstack/cluster/actuator.go b/pkg/cloud/openstack/cluster/actuator.go index d4d4107157..0825c2499d 100644 --- a/pkg/cloud/openstack/cluster/actuator.go +++ b/pkg/cloud/openstack/cluster/actuator.go @@ -87,6 +87,11 @@ func (a *Actuator) Delete(cluster *clusterv1.Cluster) error { return err } + secGroupService, err := clients.NewSecGroupService(client) + if err != nil { + return err + } + // Load provider config. _, err = providerv1.ClusterSpecFromProviderSpec(cluster.Spec.ProviderSpec) if err != nil { @@ -94,13 +99,29 @@ func (a *Actuator) Delete(cluster *clusterv1.Cluster) error { } // Load provider status. - _, err = providerv1.ClusterStatusFromProviderStatus(cluster.Status.ProviderStatus) + providerStatus, err := providerv1.ClusterStatusFromProviderStatus(cluster.Status.ProviderStatus) if err != nil { return errors.Errorf("failed to load cluster provider status: %v", err) } // Delete other things + if providerStatus.GlobalSecurityGroup != nil { + klog.Infof("Deleting global security group %q", providerStatus.GlobalSecurityGroup.Name) + err := secGroupService.Delete(providerStatus.GlobalSecurityGroup) + if err != nil { + return errors.Errorf("failed to delete security group: %v", err) + } + } + + if providerStatus.ControlPlaneSecurityGroup != nil { + klog.Infof("Deleting control plane security group %q", providerStatus.ControlPlaneSecurityGroup.Name) + err := secGroupService.Delete(providerStatus.ControlPlaneSecurityGroup) + if err != nil { + return errors.Errorf("failed to delete security group: %v", err) + } + } + return nil } diff --git a/pkg/cloud/openstack/machine/actuator.go b/pkg/cloud/openstack/machine/actuator.go index 28031ee42d..b132265bbf 100644 --- a/pkg/cloud/openstack/machine/actuator.go +++ b/pkg/cloud/openstack/machine/actuator.go @@ -21,7 +21,9 @@ import ( "encoding/json" "fmt" "net" + "os" "reflect" + "strconv" "time" "k8s.io/apimachinery/pkg/api/equality" @@ -40,6 +42,7 @@ import ( "sigs.k8s.io/cluster-api-provider-openstack/pkg/bootstrap" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/openstack" "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/openstack/clients" + "sigs.k8s.io/cluster-api-provider-openstack/pkg/cloud/openstack/options" "sigs.k8s.io/controller-runtime/pkg/client" clconfig "github.com/coreos/container-linux-config-transpiler/config" @@ -52,11 +55,9 @@ const ( DisableTemplatingKey = "disableTemplating" PostprocessorKey = "postprocessor" - TimeoutInstanceCreate = 5 * time.Minute - TimeoutInstanceDelete = 5 * time.Minute + TimeoutInstanceCreate = 5 + TimeoutInstanceDelete = 5 RetryIntervalInstanceStatus = 10 * time.Second - - TokenTTL = 60 * time.Minute ) type OpenstackClient struct { @@ -75,6 +76,16 @@ func NewActuator(params openstack.ActuatorParams) (*OpenstackClient, error) { }, nil } +func getTimeout(name string, timeout int) time.Duration { + if v := os.Getenv(name); v != "" { + timeout, err := strconv.Atoi(v) + if err == nil { + return time.Duration(timeout) + } + } + return time.Duration(timeout) +} + func (oc *OpenstackClient) Create(ctx context.Context, cluster *clusterv1.Cluster, machine *machinev1.Machine) error { kubeClient := oc.params.KubeClient @@ -210,8 +221,9 @@ func (oc *OpenstackClient) Create(ctx context.Context, cluster *clusterv1.Cluste return oc.handleMachineError(machine, apierrors.CreateMachine( "error creating Openstack instance: %v", err)) } - // TODO: wait instance ready - err = util.PollImmediate(RetryIntervalInstanceStatus, TimeoutInstanceCreate, func() (bool, error) { + instanceCreateTimeout := getTimeout("CLUSTER_API_OPENSTACK_INSTANCE_CREATE_TIMEOUT", TimeoutInstanceCreate) + instanceCreateTimeout = instanceCreateTimeout * time.Minute + err = util.PollImmediate(RetryIntervalInstanceStatus, instanceCreateTimeout, func() (bool, error) { instance, err := machineService.GetInstance(instance.ID) if err != nil { return false, nil @@ -295,7 +307,9 @@ func (oc *OpenstackClient) Update(ctx context.Context, cluster *clusterv1.Cluste if err != nil { klog.Errorf("delete machine %s for update failed: %v", currentMachine.ObjectMeta.Name, err) } else { - err = util.PollImmediate(RetryIntervalInstanceStatus, TimeoutInstanceDelete, func() (bool, error) { + instanceDeleteTimeout := getTimeout("CLUSTER_API_OPENSTACK_INSTANCE_DELETE_TIMEOUT", TimeoutInstanceDelete) + instanceDeleteTimeout = instanceDeleteTimeout * time.Minute + err = util.PollImmediate(RetryIntervalInstanceStatus, instanceDeleteTimeout, func() (bool, error) { instance, err := oc.instanceExists(machine) if err != nil { return false, nil @@ -321,7 +335,7 @@ func (oc *OpenstackClient) Update(ctx context.Context, cluster *clusterv1.Cluste func (oc *OpenstackClient) Exists(ctx context.Context, cluster *clusterv1.Cluster, machine *machinev1.Machine) (bool, error) { instance, err := oc.instanceExists(machine) if err != nil { - return false, err + return false, fmt.Errorf("Error checking if instance exists (machine/actuator.go 346): %v", err) } return instance != nil, err } @@ -432,7 +446,7 @@ func (oc *OpenstackClient) requiresUpdate(a *machinev1.Machine, b *machinev1.Mac func (oc *OpenstackClient) instanceExists(machine *machinev1.Machine) (instance *clients.Instance, err error) { machineSpec, err := openstackconfigv1.MachineSpecFromProviderSpec(machine.Spec.ProviderSpec) if err != nil { - return nil, err + return nil, fmt.Errorf("\nError getting the machine spec from the provider spec (machine/actuator.go 457): %v", err) } opts := &clients.InstanceListOpts{ Name: machine.Name, @@ -442,12 +456,12 @@ func (oc *OpenstackClient) instanceExists(machine *machinev1.Machine) (instance machineService, err := clients.NewInstanceServiceFromMachine(oc.params.KubeClient, machine) if err != nil { - return nil, err + return nil, fmt.Errorf("\nError getting a new instance service from the machine (machine/actuator.go 467): %v", err) } instanceList, err := machineService.GetInstanceList(opts) if err != nil { - return nil, err + return nil, fmt.Errorf("\nError listing the instances (machine/actuator.go 472): %v", err) } if len(instanceList) == 0 { return nil, nil @@ -461,7 +475,7 @@ func (oc *OpenstackClient) createBootstrapToken() (string, error) { return "", err } - expiration := time.Now().UTC().Add(TokenTTL) + expiration := time.Now().UTC().Add(options.TokenTTL) tokenSecret, err := bootstrap.GenerateTokenSecret(token, expiration) if err != nil { panic(fmt.Sprintf("unable to create token. there might be a bug somwhere: %v", err)) diff --git a/pkg/cloud/openstack/options/options.go b/pkg/cloud/openstack/options/options.go new file mode 100644 index 0000000000..f15d4bc6e5 --- /dev/null +++ b/pkg/cloud/openstack/options/options.go @@ -0,0 +1,30 @@ +/* +Copyright 2019 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 options + +import ( + "flag" + "time" +) + +var ( + TokenTTL time.Duration +) + +func init() { + flag.DurationVar(&TokenTTL, "token_ttl", 60*time.Minute, "TTL for kubeadm bootstrap token of the target Kubernetes cluster") +}