diff --git a/Makefile b/Makefile index 56942bec89..1699286b28 100644 --- a/Makefile +++ b/Makefile @@ -128,8 +128,7 @@ generate-go: ## Runs go generate .PHONY: generate-mocks generate-mocks: clean-bazel-mocks ## Generate mocks, CRDs and runs `go generate` through Bazel - bazel build $(BAZEL_ARGS) //pkg/cloud/services/mocks:mocks \ - //pkg/cloud/services/ec2/mock_ec2iface:mocks \ + bazel build $(BAZEL_ARGS) //pkg/cloud/services/ec2/mock_ec2iface:mocks \ //pkg/cloud/services/elb/mock_elbiface:mocks ./hack/copy-bazel-mocks.sh diff --git a/cmd/manager/BUILD.bazel b/cmd/manager/BUILD.bazel index c3989ea5cf..df1ec1026a 100644 --- a/cmd/manager/BUILD.bazel +++ b/cmd/manager/BUILD.bazel @@ -25,15 +25,11 @@ go_library( visibility = ["//visibility:private"], deps = [ "//pkg/apis:go_default_library", - "//pkg/cloud/actuators/cluster:go_default_library", "//pkg/controller:go_default_library", "//pkg/record:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/klog/klogr:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/client/config:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/manager:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/runtime/log:go_default_library", diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 88e3b4e180..9b031c168c 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -22,16 +22,12 @@ import ( _ "net/http/pprof" "time" - corev1 "k8s.io/client-go/kubernetes/typed/core/v1" "k8s.io/klog" "k8s.io/klog/klogr" capa "sigs.k8s.io/cluster-api-provider-aws/pkg/apis" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/actuators/cluster" "sigs.k8s.io/cluster-api-provider-aws/pkg/controller" "sigs.k8s.io/cluster-api-provider-aws/pkg/record" capi "sigs.k8s.io/cluster-api/pkg/apis" - "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset" - capicluster "sigs.k8s.io/cluster-api/pkg/controller/cluster" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/runtime/log" @@ -78,27 +74,9 @@ func main() { klog.Fatalf("Failed to set up overall controller manager: %v", err) } - cs, err := clientset.NewForConfig(cfg) - if err != nil { - klog.Fatalf("Failed to create client from configuration: %v", err) - } - - coreClient, err := corev1.NewForConfig(cfg) - if err != nil { - klog.Fatalf("Failed to create corev1 client from configuration: %v", err) - } - // Initialize event recorder. record.InitFromRecorder(mgr.GetEventRecorderFor("aws-controller")) - // Initialize cluster actuator. - clusterActuator := cluster.NewActuator(cluster.ActuatorParams{ - Client: mgr.GetClient(), - CoreClient: coreClient, - ClusterClient: cs.ClusterV1alpha2(), - LoggingContext: "[cluster-actuator]", - }) - if err := capi.AddToScheme(mgr.GetScheme()); err != nil { klog.Fatal(err) } @@ -107,8 +85,6 @@ func main() { klog.Fatal(err) } - capicluster.AddWithActuator(mgr, clusterActuator) - // Setup all Controllers. if err := controller.AddToManager(mgr); err != nil { klog.Fatal(err) diff --git a/config/crds/infrastructure.cluster.x-k8s.io_awsclusterproviderspecs.yaml b/config/crds/infrastructure.cluster.x-k8s.io_awsclusterproviderspecs.yaml deleted file mode 100644 index d251b7c0bf..0000000000 --- a/config/crds/infrastructure.cluster.x-k8s.io_awsclusterproviderspecs.yaml +++ /dev/null @@ -1,180 +0,0 @@ - ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - creationTimestamp: null - name: awsclusterproviderspecs.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - kind: AWSClusterProviderSpec - plural: awsclusterproviderspecs - scope: "" - validation: - openAPIV3Schema: - description: AWSClusterProviderSpec is the providerConfig for AWS in the cluster - object - properties: - additionalUserDataFiles: - description: AdditionalUserDataFiles specifies extra files to be passed - to all Machines' user_data upon creation. - items: - description: Files defines the input for generating write_files in cloud-init. - properties: - content: - description: Content is the actual content of the file. - type: string - owner: - description: Owner specifies the ownership of the file, e.g. "root:root". - type: string - path: - description: Path specifies the full path on disk where to store the - file. - type: string - permissions: - description: Permissions specifies the permissions to assign to the - file, e.g. "0640". - type: string - required: - - content - - owner - - path - - permissions - type: object - type: array - 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 - caKeyPair: - description: CAKeyPair is the key pair for ca certs. - properties: - cert: - format: byte - type: string - key: - format: byte - type: string - type: object - etcdCAKeyPair: - description: EtcdCAKeyPair is the key pair for etcd. - properties: - cert: - format: byte - type: string - key: - format: byte - type: string - type: object - frontProxyCAKeyPair: - description: FrontProxyCAKeyPair is the key pair for FrontProxyKeyPair. - properties: - cert: - format: byte - type: string - key: - format: byte - type: string - 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 - networkSpec: - description: NetworkSpec encapsulates all things related to AWS network. - properties: - subnets: - description: Subnets configuration. - items: - description: SubnetSpec configures an AWS Subnet. - properties: - availabilityZone: - description: AvailabilityZone defines the availability zone to - use for this subnet in the cluster's region. - type: string - cidrBlock: - description: CidrBlock is the CIDR block to be used when the provider - creates a managed VPC. - type: string - id: - description: ID defines a unique identifier to reference this - resource. - type: string - isPublic: - description: IsPublic defines the subnet as a public subnet. A - subnet is public when it is associated with a route table that - has a route to an internet gateway. - type: boolean - natGatewayId: - description: NatGatewayID is the NAT gateway id associated with - the subnet. Ignored unless the subnet is managed by the provider, - in which case this is set on the public subnet where the NAT - gateway resides. It is then used to determine routes for private - subnets in the same AZ as the public subnet. - type: string - routeTableId: - description: RouteTableID is the routing table id associated with - the subnet. - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the resource. - type: object - type: object - type: array - vpc: - description: VPC configuration. - properties: - cidrBlock: - description: CidrBlock is the CIDR block to be used when the provider - creates a managed VPC. Defaults to 10.0.0.0/16. - type: string - id: - description: ID is the vpc-id of the VPC this provider should use - to create resources. - type: string - internetGatewayId: - description: InternetGatewayID is the id of the internet gateway - associated with the VPC. - type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the resource. - type: object - type: object - type: object - region: - description: The AWS Region the cluster lives in. - type: string - saKeyPair: - description: SAKeyPair is the service account key pair. - properties: - cert: - format: byte - type: string - key: - format: byte - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the bastion - host. - type: string - type: object - versions: - - name: v1alpha2 - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/crds/infrastructure.cluster.x-k8s.io_awsclusterproviderstatuses.yaml b/config/crds/infrastructure.cluster.x-k8s.io_awsclusterproviderstatuses.yaml deleted file mode 100644 index 48e4121cb7..0000000000 --- a/config/crds/infrastructure.cluster.x-k8s.io_awsclusterproviderstatuses.yaml +++ /dev/null @@ -1,275 +0,0 @@ - ---- -apiVersion: apiextensions.k8s.io/v1beta1 -kind: CustomResourceDefinition -metadata: - creationTimestamp: null - name: awsclusterproviderstatuses.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - kind: AWSClusterProviderStatus - plural: awsclusterproviderstatuses - scope: "" - validation: - openAPIV3Schema: - description: AWSClusterProviderStatus contains the status fields relevant to - AWS in the cluster object. - 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 - bastion: - description: Instance describes an AWS instance. - properties: - ebsOptimized: - description: Indicates whether the instance is optimized for Amazon - EBS I/O. - type: boolean - enaSupport: - description: Specifies whether enhanced networking with ENA is enabled. - type: boolean - iamProfile: - description: The name of the IAM instance profile associated with the - instance, if applicable. - type: string - id: - type: string - imageId: - description: The ID of the AMI used to launch the instance. - type: string - instanceState: - description: The current state of the instance. - type: string - keyName: - description: The name of the SSH key pair. - type: string - privateIp: - description: The private IPv4 address assigned to the instance. - type: string - publicIp: - description: The public IPv4 address assigned to the instance, if applicable. - type: string - rootDeviceSize: - description: Specifies size (in Gi) of the root storage device - format: int64 - type: integer - securityGroupIds: - description: SecurityGroupIDs are one or more security group IDs this - instance belongs to. - items: - type: string - type: array - subnetId: - description: The ID of the subnet of the instance. - type: string - tags: - additionalProperties: - type: string - description: The tags associated with the instance. - type: object - type: - description: The instance type. - type: string - userData: - description: UserData is the raw data script passed to the instance - which is run upon bootstrap. This field must not be base64 encoded - and should only be used when running a new instance. - type: string - required: - - id - 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 encapsulates AWS networking resources. - properties: - apiServerElb: - description: APIServerELB is the Kubernetes api server classic load - balancer. - properties: - attributes: - description: Attributes defines extra attributes associated with - the load balancer. - properties: - idleTimeout: - description: IdleTimeout is time that the connection is allowed - to be idle (no data has been sent over the connection) before - it is closed by the load balancer. - format: int64 - type: integer - type: object - dnsName: - description: DNSName is the dns name of the load balancer. - type: string - healthChecks: - description: HealthCheck is the classic elb health check associated - with the load balancer. - properties: - healthyThreshold: - format: int64 - type: integer - interval: - description: A Duration represents the elapsed time between - two instants as an int64 nanosecond count. The representation - limits the largest representable duration to approximately - 290 years. - format: int64 - type: integer - target: - type: string - timeout: - description: A Duration represents the elapsed time between - two instants as an int64 nanosecond count. The representation - limits the largest representable duration to approximately - 290 years. - format: int64 - type: integer - unhealthyThreshold: - format: int64 - type: integer - required: - - healthyThreshold - - interval - - target - - timeout - - unhealthyThreshold - type: object - listeners: - description: Listeners is an array of classic elb listeners associated - with the load balancer. There must be at least one. - items: - description: ClassicELBListener defines an AWS classic load balancer - listener. - properties: - instancePort: - format: int64 - type: integer - instanceProtocol: - description: ClassicELBProtocol defines listener protocols - for a classic load balancer. - type: string - port: - format: int64 - type: integer - protocol: - description: ClassicELBProtocol defines listener protocols - for a classic load balancer. - type: string - required: - - instancePort - - instanceProtocol - - port - - protocol - type: object - type: array - name: - description: The name of the load balancer. It must be unique within - the set of load balancers defined in the region. It also serves - as identifier. - type: string - scheme: - description: Scheme is the load balancer scheme, either internet-facing - or private. - type: string - securityGroupIds: - description: SecurityGroupIDs is an array of security groups assigned - to the load balancer. - items: - type: string - type: array - subnetIds: - description: SubnetIDs is an array of subnets in the VPC attached - to the load balancer. - items: - type: string - type: array - tags: - additionalProperties: - type: string - description: Tags is a map of tags associated with the load balancer. - type: object - type: object - securityGroups: - additionalProperties: - description: SecurityGroup defines an AWS security group. - properties: - id: - description: ID is a unique identifier. - type: string - ingressRule: - description: IngressRules is the inbound rules associated with - the security group. - items: - description: IngressRule defines an AWS ingress rule for security - groups. - properties: - cidrBlocks: - description: List of CIDR blocks to allow access from. Cannot - be specified with SourceSecurityGroupID. - items: - type: string - type: array - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the protocol - type for a security group rule. - type: string - sourceSecurityGroupIds: - description: The security group id to allow access from. - Cannot be specified with CidrBlocks. - items: - type: string - type: array - toPort: - format: int64 - type: integer - required: - - cidrBlocks - - description - - fromPort - - protocol - - sourceSecurityGroupIds - - toPort - type: object - type: array - name: - description: Name is the security group name. - type: string - tags: - additionalProperties: - type: string - description: Tags is a map of tags associated with the security - group. - type: object - required: - - id - - ingressRule - - name - type: object - description: SecurityGroups is a map from the role/kind of the security - group to its unique name, if any. - type: object - type: object - type: object - versions: - - name: v1alpha2 - served: true - storage: true -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/crds/infrastructure.cluster.x-k8s.io_awsclusters.yaml b/config/crds/infrastructure.cluster.x-k8s.io_awsclusters.yaml new file mode 100644 index 0000000000..c095a84e4e --- /dev/null +++ b/config/crds/infrastructure.cluster.x-k8s.io_awsclusters.yaml @@ -0,0 +1,379 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + creationTimestamp: null + name: awsclusters.infrastructure.cluster.x-k8s.io +spec: + group: infrastructure.cluster.x-k8s.io + names: + kind: AWSCluster + plural: awsclusters + scope: "" + validation: + openAPIV3Schema: + description: AWSCluster is the Schema for the awsclusters API + 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 + 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 + spec: + description: AWSClusterSpec defines the desired state of AWSCluster + properties: + networkSpec: + description: NetworkSpec encapsulates all things related to AWS network. + properties: + subnets: + description: Subnets configuration. + items: + description: SubnetSpec configures an AWS Subnet. + properties: + availabilityZone: + description: AvailabilityZone defines the availability zone + to use for this subnet in the cluster's region. + type: string + cidrBlock: + description: CidrBlock is the CIDR block to be used when the + provider creates a managed VPC. + type: string + id: + description: ID defines a unique identifier to reference this + resource. + type: string + isPublic: + description: IsPublic defines the subnet as a public subnet. + A subnet is public when it is associated with a route table + that has a route to an internet gateway. + type: boolean + natGatewayId: + description: NatGatewayID is the NAT gateway id associated + with the subnet. Ignored unless the subnet is managed by + the provider, in which case this is set on the public subnet + where the NAT gateway resides. It is then used to determine + routes for private subnets in the same AZ as the public + subnet. + type: string + routeTableId: + description: RouteTableID is the routing table id associated + with the subnet. + type: string + tags: + additionalProperties: + type: string + description: Tags is a collection of tags describing the resource. + type: object + type: object + type: array + vpc: + description: VPC configuration. + properties: + cidrBlock: + description: CidrBlock is the CIDR block to be used when the + provider creates a managed VPC. Defaults to 10.0.0.0/16. + type: string + id: + description: ID is the vpc-id of the VPC this provider should + use to create resources. + type: string + internetGatewayId: + description: InternetGatewayID is the id of the internet gateway + associated with the VPC. + type: string + tags: + additionalProperties: + type: string + description: Tags is a collection of tags describing the resource. + type: object + type: object + type: object + region: + description: The AWS Region the cluster lives in. + type: string + sshKeyName: + description: SSHKeyName is the name of the ssh key to attach to the + bastion host. + type: string + type: object + status: + description: AWSClusterStatus defines the observed state of AWSCluster + properties: + apiEndpoints: + description: APIEndpoints represents the endpoints to communicate with + the control plane. + items: + description: APIEndpoint represents a reachable Kubernetes API endpoint. + properties: + host: + description: The hostname on which the API server is serving. + type: string + port: + description: The port on which the API server is serving. + type: integer + required: + - host + - port + type: object + type: array + bastion: + description: Instance describes an AWS instance. + properties: + ebsOptimized: + description: Indicates whether the instance is optimized for Amazon + EBS I/O. + type: boolean + enaSupport: + description: Specifies whether enhanced networking with ENA is enabled. + type: boolean + iamProfile: + description: The name of the IAM instance profile associated with + the instance, if applicable. + type: string + id: + type: string + imageId: + description: The ID of the AMI used to launch the instance. + type: string + instanceState: + description: The current state of the instance. + type: string + keyName: + description: The name of the SSH key pair. + type: string + privateIp: + description: The private IPv4 address assigned to the instance. + type: string + publicIp: + description: The public IPv4 address assigned to the instance, if + applicable. + type: string + rootDeviceSize: + description: Specifies size (in Gi) of the root storage device + format: int64 + type: integer + securityGroupIds: + description: SecurityGroupIDs are one or more security group IDs + this instance belongs to. + items: + type: string + type: array + subnetId: + description: The ID of the subnet of the instance. + type: string + tags: + additionalProperties: + type: string + description: The tags associated with the instance. + type: object + type: + description: The instance type. + type: string + userData: + description: UserData is the raw data script passed to the instance + which is run upon bootstrap. This field must not be base64 encoded + and should only be used when running a new instance. + type: string + required: + - id + type: object + network: + description: Network encapsulates AWS networking resources. + properties: + apiServerElb: + description: APIServerELB is the Kubernetes api server classic load + balancer. + properties: + attributes: + description: Attributes defines extra attributes associated + with the load balancer. + properties: + idleTimeout: + description: IdleTimeout is time that the connection is + allowed to be idle (no data has been sent over the connection) + before it is closed by the load balancer. + format: int64 + type: integer + type: object + dnsName: + description: DNSName is the dns name of the load balancer. + type: string + healthChecks: + description: HealthCheck is the classic elb health check associated + with the load balancer. + properties: + healthyThreshold: + format: int64 + type: integer + interval: + description: A Duration represents the elapsed time between + two instants as an int64 nanosecond count. The representation + limits the largest representable duration to approximately + 290 years. + format: int64 + type: integer + target: + type: string + timeout: + description: A Duration represents the elapsed time between + two instants as an int64 nanosecond count. The representation + limits the largest representable duration to approximately + 290 years. + format: int64 + type: integer + unhealthyThreshold: + format: int64 + type: integer + required: + - healthyThreshold + - interval + - target + - timeout + - unhealthyThreshold + type: object + listeners: + description: Listeners is an array of classic elb listeners + associated with the load balancer. There must be at least + one. + items: + description: ClassicELBListener defines an AWS classic load + balancer listener. + properties: + instancePort: + format: int64 + type: integer + instanceProtocol: + description: ClassicELBProtocol defines listener protocols + for a classic load balancer. + type: string + port: + format: int64 + type: integer + protocol: + description: ClassicELBProtocol defines listener protocols + for a classic load balancer. + type: string + required: + - instancePort + - instanceProtocol + - port + - protocol + type: object + type: array + name: + description: The name of the load balancer. It must be unique + within the set of load balancers defined in the region. It + also serves as identifier. + type: string + scheme: + description: Scheme is the load balancer scheme, either internet-facing + or private. + type: string + securityGroupIds: + description: SecurityGroupIDs is an array of security groups + assigned to the load balancer. + items: + type: string + type: array + subnetIds: + description: SubnetIDs is an array of subnets in the VPC attached + to the load balancer. + items: + type: string + type: array + tags: + additionalProperties: + type: string + description: Tags is a map of tags associated with the load + balancer. + type: object + type: object + securityGroups: + additionalProperties: + description: SecurityGroup defines an AWS security group. + properties: + id: + description: ID is a unique identifier. + type: string + ingressRule: + description: IngressRules is the inbound rules associated + with the security group. + items: + description: IngressRule defines an AWS ingress rule for + security groups. + properties: + cidrBlocks: + description: List of CIDR blocks to allow access from. + Cannot be specified with SourceSecurityGroupID. + items: + type: string + type: array + description: + type: string + fromPort: + format: int64 + type: integer + protocol: + description: SecurityGroupProtocol defines the protocol + type for a security group rule. + type: string + sourceSecurityGroupIds: + description: The security group id to allow access from. + Cannot be specified with CidrBlocks. + items: + type: string + type: array + toPort: + format: int64 + type: integer + required: + - cidrBlocks + - description + - fromPort + - protocol + - sourceSecurityGroupIds + - toPort + type: object + type: array + name: + description: Name is the security group name. + type: string + tags: + additionalProperties: + type: string + description: Tags is a map of tags associated with the security + group. + type: object + required: + - id + - ingressRule + - name + type: object + description: SecurityGroups is a map from the role/kind of the security + group to its unique name, if any. + type: object + type: object + ready: + type: boolean + required: + - ready + type: object + type: object + versions: + - name: v1alpha2 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crds/kustomization.yaml b/config/crds/kustomization.yaml index c6cf75061d..c0e194b43d 100644 --- a/config/crds/kustomization.yaml +++ b/config/crds/kustomization.yaml @@ -4,10 +4,9 @@ # YAML string, with resources separated by document # markers ("---"). resources: + - infrastructure.cluster.x-k8s.io_awsclusters.yaml - infrastructure.cluster.x-k8s.io_awsmachines.yaml - infrastructure.cluster.x-k8s.io_awsmachinetemplates.yaml - - infrastructure.cluster.x-k8s.io_awsclusterproviderspecs.yaml - - infrastructure.cluster.x-k8s.io_awsclusterproviderstatuses.yaml - awsprovider_v1alpha1_awsclusterproviderspec.yaml - awsprovider_v1alpha1_awsclusterproviderstatus.yaml - awsprovider_v1alpha1_awsmachineproviderspec.yaml diff --git a/go.mod b/go.mod index ec0ca71c18..12e2fb8c81 100644 --- a/go.mod +++ b/go.mod @@ -21,7 +21,7 @@ require ( k8s.io/klog v0.3.2 k8s.io/kubernetes v1.14.2 k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 - sigs.k8s.io/cluster-api v0.0.0-20190723164546-bf8541c6acdf + sigs.k8s.io/cluster-api v0.0.0-20190731140622-3be3a5776b37 sigs.k8s.io/controller-runtime v0.2.0-beta.4 sigs.k8s.io/controller-tools v0.2.0-beta.4 sigs.k8s.io/testing_frameworks v0.1.2-0.20190130140139-57f07443c2d4 @@ -31,5 +31,5 @@ require ( replace ( k8s.io/api => k8s.io/api v0.0.0-20190704095032-f4ca3d3bdf1d k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20190704094733-8f6ac2502e51 - sigs.k8s.io/cluster-api => sigs.k8s.io/cluster-api v0.0.0-20190723164546-bf8541c6acdf + sigs.k8s.io/cluster-api => sigs.k8s.io/cluster-api v0.0.0-20190731140622-3be3a5776b37 ) diff --git a/go.sum b/go.sum index d35ed06772..5f8e6b5523 100644 --- a/go.sum +++ b/go.sum @@ -1,19 +1,11 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -contrib.go.opencensus.io/exporter/ocagent v0.4.12 h1:jGFvw3l57ViIVEPKKEUXPcLYIXJmQxLUh6ey1eJhwyc= contrib.go.opencensus.io/exporter/ocagent v0.4.12/go.mod h1:450APlNTSR6FrvC3CTRqYosuDstRB9un7SOx2k/9ckA= -github.com/Azure/go-autorest/autorest v0.2.0 h1:zBtSTOQTtjzHVRe+mhkiHvHwRTKHhjBEyo1m6DfI3So= github.com/Azure/go-autorest/autorest v0.2.0/go.mod h1:AKyIcETwSUFxIcs/Wnq/C+kwCtlEYGUVd7FPNb2slmg= -github.com/Azure/go-autorest/autorest/adal v0.1.0 h1:RSw/7EAullliqwkZvgIGDYZWQm1PGKXI8c4aY/87yuU= github.com/Azure/go-autorest/autorest/adal v0.1.0/go.mod h1:MeS4XhScH55IST095THyTxElntu7WqB7pNbZo8Q5G3E= -github.com/Azure/go-autorest/autorest/date v0.1.0 h1:YGrhWfrgtFs84+h0o46rJrlmsZtyZRg470CqAXTZaGM= github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= -github.com/Azure/go-autorest/autorest/mocks v0.1.0 h1:Kx+AUU2Te+A3JIyYn6Dfs+cFgx5XorQKuIXrZGoq/SI= github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= -github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY= github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= -github.com/Azure/go-autorest/tracing v0.1.0 h1:TRBxC5Pj/fIuh4Qob0ZpkggbfT8RC0SubHbpV3p4/Vc= github.com/Azure/go-autorest/tracing v0.1.0/go.mod h1:ROEEAFwXycQw7Sn3DXNtEedEvdeRAgDr0izn4z5Ij88= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= @@ -27,13 +19,11 @@ github.com/awslabs/goformation v0.0.0-20190310235947-776555df5a6d h1:1y3J+mle+xA github.com/awslabs/goformation v0.0.0-20190310235947-776555df5a6d/go.mod h1:HezUyH08DSwwGn3GioVXWZYUhkdvC+oGJ7ya7vBRm7k= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4= github.com/census-instrumentation/opencensus-proto v0.2.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= @@ -58,14 +48,12 @@ github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= -github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7 h1:u4bArs140e9+AfE52mFHOXVFnOSBJBRlzTHrOPLOIhE= github.com/golang/groupcache v0.0.0-20180513044358-24b0969c4cb7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0 h1:28o5sBqPkBsMGnC6b4MvE2TzSr5/AT4c/1fLqVGIwlk= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -77,11 +65,9 @@ github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeq github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/googleapis/gnostic v0.2.0 h1:l6N3VoaVzTncYYW+9yOz2LJJammFZGBO13sqgEhpy9g= github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/gophercloud/gophercloud v0.2.0 h1:lD2Bce2xBAMNNcFZ0dObTpXkGLlVIb33RPVUNVpw6ic= github.com/gophercloud/gophercloud v0.2.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/grpc-ecosystem/grpc-gateway v1.8.5 h1:2+KSC78XiO6Qy0hIjfc1OD9H+hsaJdJlb8Kqsd41CTE= github.com/grpc-ecosystem/grpc-gateway v1.8.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hashicorp/golang-lru v0.0.0-20180201235237-0fb14efe8c47/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo= @@ -180,7 +166,6 @@ github.com/xeipuuv/gojsonreference v0.0.0-20150808065054-e02fc20de94c/go.mod h1: github.com/xeipuuv/gojsonschema v0.0.0-20181112162635-ac52e6811b56 h1:yhqBHs09SmmUoNOHc9jgK4a60T3XFRtPAkYxVnqgY50= github.com/xeipuuv/gojsonschema v0.0.0-20181112162635-ac52e6811b56/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2 h1:NAfh7zF0/3/HqtMvJNZ/RFrSlCE6ZTlHmKfhL/Dm1Jk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.uber.org/atomic v1.3.2 h1:2Oa65PReHzfn29GpvgsYwloV9AVFHPDk8tYxt2c2tr4= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -191,7 +176,6 @@ go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -210,7 +194,6 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09 h1:KaQtG+aDELoNmXYas3TVkGNYRuq8JQ1aa7LJt8EXVyo= golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -221,7 +204,6 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20170814044513-c84c1ab9fd18/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -250,19 +232,16 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190501045030-23463209683d h1:D7DVZUZEUgsSIDTivnUtVeGfN5AvhDIKtdIZAqx0ieE= golang.org/x/tools v0.0.0-20190501045030-23463209683d/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -gomodules.xyz/jsonpatch/v2 v2.0.0 h1:OyHbl+7IOECpPKfVK42oFr6N7+Y2dR+Jsb/IiDV3hOo= +gomodules.xyz/jsonpatch/v2 v2.0.0 h1:lHNQverf0+Gm1TbSbVIDWVXOhZ2FpZopxRqpr2uIjs4= gomodules.xyz/jsonpatch/v2 v2.0.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= -google.golang.org/api v0.3.1 h1:oJra/lMfmtm13/rgY/8i3MzjFWYXvQIAKjQ3HqofMk8= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19 h1:Lj2SnHtxkRGJDqnGaSjo+CCdIieEnwVazbOXILwQemk= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.19.1 h1:TrBcJ1yqAl1G++wO39nD/qtgpsW9/1+QGrluyMGEYgM= google.golang.org/grpc v1.19.1/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -301,7 +280,6 @@ k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a h1:QoHVuRquf80YZ+/bovwxoMO3Q/A3n k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68= k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.2 h1:qvP/U6CcZ6qyi/qSHlJKdlAboCzo3mT0DAm0XAarpz4= k8s.io/klog v0.3.2/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= @@ -311,8 +289,8 @@ k8s.io/kubernetes v1.14.2 h1:Gdq2hPpttbaJBoClIanCE6WSu4IZReA54yhkZtvPUOo= k8s.io/kubernetes v1.14.2/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y= k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= -sigs.k8s.io/cluster-api v0.0.0-20190723164546-bf8541c6acdf h1:ibZKrPxrS7Gn0rvYMJrSrohal3A1zhvQs4Vd/OynmRQ= -sigs.k8s.io/cluster-api v0.0.0-20190723164546-bf8541c6acdf/go.mod h1:DIiQEP2FjsAiEgBTgT5EEUAVM7XRy7aLgeERFXvZHaQ= +sigs.k8s.io/cluster-api v0.0.0-20190731140622-3be3a5776b37 h1:3KGGmCj+aM/fgKqIQkfAaS10IIrU6lpAJ5hlatuS+cY= +sigs.k8s.io/cluster-api v0.0.0-20190731140622-3be3a5776b37/go.mod h1:DIiQEP2FjsAiEgBTgT5EEUAVM7XRy7aLgeERFXvZHaQ= sigs.k8s.io/controller-runtime v0.2.0-beta.4 h1:S1XVfRWR1MuIXZdkYx3jN8JDw+bbQxmWZroy0i87z/A= sigs.k8s.io/controller-runtime v0.2.0-beta.4/go.mod h1:HweyYKQ8fBuzdu2bdaeBJvsFgAi/OqBBnrVGXcqKhME= sigs.k8s.io/controller-tools v0.2.0-beta.4 h1:W+coTe+nkVNclQrikwlRp6GJKwgcrHzvIQZ9kCaak5A= diff --git a/hack/update-vendor.sh b/hack/update-vendor.sh index 5d61946558..e9a4f5f544 100755 --- a/hack/update-vendor.sh +++ b/hack/update-vendor.sh @@ -19,17 +19,20 @@ set -o nounset set -o pipefail KUBE_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. +# shellcheck source=ensure-go.sh source "${KUBE_ROOT}/hack/ensure-go.sh" +GOPROXY=$(go env GOPROXY) +export GOPROXY="${GOPROXY:-https://proxy.golang.org}" go mod tidy go mod vendor # Copy full dependencies if needed. -for dep in $(cat ${KUBE_ROOT}/go.vendor); do - src=$(go mod download -json ${dep} | jq -r .Dir) +while IFS= read -r dep; do + src="$(go mod download -json "${dep}" | jq -r .Dir)" dst="${KUBE_ROOT}/vendor/${dep}" cp -af "${src}/" "${dst}" - chmod -R +w ${dst} -done + chmod -R +w "${dst}" +done < "${KUBE_ROOT}/go.vendor" go mod verify diff --git a/pkg/apis/infrastructure/v1alpha2/BUILD.bazel b/pkg/apis/infrastructure/v1alpha2/BUILD.bazel index b30f0553b4..ad5fa54cdf 100644 --- a/pkg/apis/infrastructure/v1alpha2/BUILD.bazel +++ b/pkg/apis/infrastructure/v1alpha2/BUILD.bazel @@ -3,8 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "awsclusterproviderconfig_types.go", - "awsclusterproviderstatus_types.go", + "awscluster_types.go", "awsmachine_types.go", "awsmachinetemplate_types.go", "doc.go", @@ -16,24 +15,20 @@ go_library( importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2", visibility = ["//visibility:public"], deps = [ - "//pkg/cloud/services/userdata:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/util/json:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/runtime/scheme:go_default_library", - "//vendor/sigs.k8s.io/yaml:go_default_library", ], ) go_test( name = "go_default_test", srcs = [ - "awsclusterproviderconfig_types_test.go", - "awsclusterproviderstatus_types_test.go", + "awscluster_types_test.go", "awsmachine_types_test.go", "awsmachinetemplate_types_test.go", "v1alpha2_suite_test.go", diff --git a/pkg/apis/infrastructure/v1alpha2/awsclusterproviderconfig_types.go b/pkg/apis/infrastructure/v1alpha2/awscluster_types.go similarity index 71% rename from pkg/apis/infrastructure/v1alpha2/awsclusterproviderconfig_types.go rename to pkg/apis/infrastructure/v1alpha2/awscluster_types.go index c62d5ba286..dd3391ebac 100644 --- a/pkg/apis/infrastructure/v1alpha2/awsclusterproviderconfig_types.go +++ b/pkg/apis/infrastructure/v1alpha2/awscluster_types.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -20,19 +20,18 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - userdata "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/userdata" ) -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. -// AWSClusterProviderSpec is the providerConfig for AWS in the cluster -// object -// +k8s:openapi-gen=true -type AWSClusterProviderSpec struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` +const ( + // ClusterFinalizer allows ReconcileAWSCluster to clean up AWS resources associated with AWSCluster before + // removing it from the apiserver. + ClusterFinalizer = "awscluster.infrastructure.cluster.x-k8s.io" +) +// AWSClusterSpec defines the desired state of AWSCluster +type AWSClusterSpec struct { // NetworkSpec encapsulates all things related to AWS network. NetworkSpec NetworkSpec `json:"networkSpec,omitempty"` @@ -41,45 +40,6 @@ type AWSClusterProviderSpec struct { // SSHKeyName is the name of the ssh key to attach to the bastion host. SSHKeyName string `json:"sshKeyName,omitempty"` - - // CAKeyPair is the key pair for ca certs. - // +optional - CAKeyPair *KeyPair `json:"caKeyPair,omitempty"` - - // EtcdCAKeyPair is the key pair for etcd. - // +optional - EtcdCAKeyPair *KeyPair `json:"etcdCAKeyPair,omitempty"` - - // FrontProxyCAKeyPair is the key pair for FrontProxyKeyPair. - // +optional - FrontProxyCAKeyPair *KeyPair `json:"frontProxyCAKeyPair,omitempty"` - - // SAKeyPair is the service account key pair. - // +optional - SAKeyPair *KeyPair `json:"saKeyPair,omitempty"` - - // AdditionalUserDataFiles specifies extra files to be passed to all Machines' user_data upon creation. - // +optional - AdditionalUserDataFiles []userdata.Files `json:"additionalUserDataFiles,omitempty"` -} - -// KeyPair is how operators can supply custom keypairs for kubeadm to use. -type KeyPair struct { - // +required - Cert []byte `json:"cert,omitempty"` - // +required - Key []byte `json:"key,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -func init() { - SchemeBuilder.Register(&AWSClusterProviderSpec{}) -} - -// HasCertAndKey returns whether a keypair contains cert and key of non-zero length. -func (kp *KeyPair) HasCertAndKey() bool { - return len(kp.Cert) != 0 && len(kp.Key) != 0 } // NetworkSpec encapsulates all things related to AWS network. @@ -152,3 +112,48 @@ type SubnetSpec struct { func (s *SubnetSpec) String() string { return fmt.Sprintf("id=%s/az=%s/public=%v", s.ID, s.AvailabilityZone, s.IsPublic) } + +// AWSClusterStatus defines the observed state of AWSCluster +type AWSClusterStatus struct { + Network Network `json:"network,omitempty"` + Bastion Instance `json:"bastion,omitempty"` + Ready bool `json:"ready"` + // APIEndpoints represents the endpoints to communicate with the control plane. + // +optional + APIEndpoints []APIEndpoint `json:"apiEndpoints,omitempty"` +} + +// APIEndpoint represents a reachable Kubernetes API endpoint. +type APIEndpoint struct { + // The hostname on which the API server is serving. + Host string `json:"host"` + + // The port on which the API server is serving. + Port int `json:"port"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AWSCluster is the Schema for the awsclusters API +// +k8s:openapi-gen=true +type AWSCluster struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec AWSClusterSpec `json:"spec,omitempty"` + Status AWSClusterStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// AWSClusterList contains a list of AWSCluster +type AWSClusterList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []AWSCluster `json:"items"` +} + +func init() { + SchemeBuilder.Register(&AWSCluster{}, &AWSClusterList{}) +} diff --git a/pkg/apis/infrastructure/v1alpha2/awsclusterproviderconfig_types_test.go b/pkg/apis/infrastructure/v1alpha2/awscluster_types_test.go similarity index 90% rename from pkg/apis/infrastructure/v1alpha2/awsclusterproviderconfig_types_test.go rename to pkg/apis/infrastructure/v1alpha2/awscluster_types_test.go index a4eb6b5521..0dc7e633be 100644 --- a/pkg/apis/infrastructure/v1alpha2/awsclusterproviderconfig_types_test.go +++ b/pkg/apis/infrastructure/v1alpha2/awscluster_types_test.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -25,12 +25,12 @@ import ( "k8s.io/apimachinery/pkg/types" ) -func TestStorageAWSClusterProviderSpec(t *testing.T) { +func TestStorageAWSCluster(t *testing.T) { key := types.NamespacedName{ Name: "foo", Namespace: "default", } - created := &AWSClusterProviderSpec{ + created := &AWSCluster{ ObjectMeta: metav1.ObjectMeta{ Name: "foo", Namespace: "default", @@ -38,7 +38,7 @@ func TestStorageAWSClusterProviderSpec(t *testing.T) { g := gomega.NewGomegaWithT(t) // Test Create - fetched := &AWSClusterProviderSpec{} + fetched := &AWSCluster{} g.Expect(c.Create(context.TODO(), created)).NotTo(gomega.HaveOccurred()) g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred()) diff --git a/pkg/apis/infrastructure/v1alpha2/awsclusterproviderstatus_types.go b/pkg/apis/infrastructure/v1alpha2/awsclusterproviderstatus_types.go deleted file mode 100644 index 77087f02a4..0000000000 --- a/pkg/apis/infrastructure/v1alpha2/awsclusterproviderstatus_types.go +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright 2018 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 v1alpha2 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// +genclient -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// AWSClusterProviderStatus contains the status fields -// relevant to AWS in the cluster object. -// +k8s:openapi-gen=true -type AWSClusterProviderStatus struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Network Network `json:"network,omitempty"` - Bastion Instance `json:"bastion,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -func init() { - SchemeBuilder.Register(&AWSClusterProviderStatus{}) -} diff --git a/pkg/apis/infrastructure/v1alpha2/awsclusterproviderstatus_types_test.go b/pkg/apis/infrastructure/v1alpha2/awsclusterproviderstatus_types_test.go deleted file mode 100644 index 8ee5a1a517..0000000000 --- a/pkg/apis/infrastructure/v1alpha2/awsclusterproviderstatus_types_test.go +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2018 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 v1alpha2 - -import ( - "testing" - - "github.com/onsi/gomega" - "golang.org/x/net/context" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" -) - -func TestStorageAWSClusterProviderStatus(t *testing.T) { - key := types.NamespacedName{ - Name: "foo", - Namespace: "default", - } - created := &AWSClusterProviderStatus{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }} - g := gomega.NewGomegaWithT(t) - - // Test Create - fetched := &AWSClusterProviderStatus{} - g.Expect(c.Create(context.TODO(), created)).NotTo(gomega.HaveOccurred()) - - g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred()) - g.Expect(fetched).To(gomega.Equal(created)) - - // Test Updating the Labels - updated := fetched.DeepCopy() - updated.Labels = map[string]string{"hello": "world"} - g.Expect(c.Update(context.TODO(), updated)).NotTo(gomega.HaveOccurred()) - - g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred()) - g.Expect(fetched).To(gomega.Equal(updated)) - - // Test Delete - g.Expect(c.Delete(context.TODO(), fetched)).NotTo(gomega.HaveOccurred()) - g.Expect(c.Get(context.TODO(), key, fetched)).To(gomega.HaveOccurred()) -} diff --git a/pkg/apis/infrastructure/v1alpha2/awsmachine_types.go b/pkg/apis/infrastructure/v1alpha2/awsmachine_types.go index a452878990..2d7cfb1b43 100644 --- a/pkg/apis/infrastructure/v1alpha2/awsmachine_types.go +++ b/pkg/apis/infrastructure/v1alpha2/awsmachine_types.go @@ -19,7 +19,7 @@ package v1alpha2 import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + "sigs.k8s.io/cluster-api/pkg/errors" ) const ( @@ -116,7 +116,7 @@ type AWSMachineStatus struct { // can be added as events to the Machine object and/or logged in the // controller's output. // +optional - ErrorReason *common.MachineStatusError `json:"errorReason,omitempty"` + ErrorReason *errors.MachineStatusError `json:"errorReason,omitempty"` // ErrorMessage will be set in the event that there is a terminal problem // reconciling the Machine and will contain a more verbose string suitable diff --git a/pkg/apis/infrastructure/v1alpha2/register.go b/pkg/apis/infrastructure/v1alpha2/register.go index 4e5a5b3e3e..70ffda98f8 100644 --- a/pkg/apis/infrastructure/v1alpha2/register.go +++ b/pkg/apis/infrastructure/v1alpha2/register.go @@ -23,12 +23,8 @@ limitations under the License. package v1alpha2 import ( - "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" - "k8s.io/apimachinery/pkg/util/json" - clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" - "sigs.k8s.io/yaml" ) var ( @@ -46,68 +42,3 @@ var ( func Resource(resource string) schema.GroupResource { return SchemeGroupVersion.WithResource(resource).GroupResource() } - -// ClusterConfigFromProviderSpec unmarshals a provider config into an AWS Cluster type -func ClusterConfigFromProviderSpec(providerConfig clusterv1.ProviderSpec) (*AWSClusterProviderSpec, error) { - var config AWSClusterProviderSpec - if providerConfig.Value == nil { - return &config, nil - } - - if err := yaml.Unmarshal(providerConfig.Value.Raw, &config); err != nil { - return nil, err - } - return &config, nil -} - -// ClusterStatusFromProviderStatus unmarshals a raw extension into an AWS Cluster type -func ClusterStatusFromProviderStatus(extension *runtime.RawExtension) (*AWSClusterProviderStatus, error) { - if extension == nil { - return &AWSClusterProviderStatus{}, nil - } - - status := new(AWSClusterProviderStatus) - if err := yaml.Unmarshal(extension.Raw, status); err != nil { - return nil, err - } - - return status, nil -} - -// EncodeClusterStatus marshals the cluster status. -func EncodeClusterStatus(status *AWSClusterProviderStatus) (*runtime.RawExtension, error) { - if status == nil { - return &runtime.RawExtension{}, nil - } - - var rawBytes []byte - var err error - - // TODO: use apimachinery conversion https://godoc.org/k8s.io/apimachinery/pkg/runtime#Convert_runtime_Object_To_runtime_RawExtension - if rawBytes, err = json.Marshal(status); err != nil { - return nil, err - } - - return &runtime.RawExtension{ - Raw: rawBytes, - }, nil -} - -// EncodeClusterSpec marshals the cluster provider spec. -func EncodeClusterSpec(spec *AWSClusterProviderSpec) (*runtime.RawExtension, error) { - if spec == nil { - return &runtime.RawExtension{}, nil - } - - var rawBytes []byte - var err error - - // TODO: use apimachinery conversion https://godoc.org/k8s.io/apimachinery/pkg/runtime#Convert_runtime_Object_To_runtime_RawExtension - if rawBytes, err = json.Marshal(spec); err != nil { - return nil, err - } - - return &runtime.RawExtension{ - Raw: rawBytes, - }, nil -} diff --git a/pkg/apis/infrastructure/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/infrastructure/v1alpha2/zz_generated.deepcopy.go index 55b47e5e28..5e6fc5aa45 100644 --- a/pkg/apis/infrastructure/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/infrastructure/v1alpha2/zz_generated.deepcopy.go @@ -23,56 +23,47 @@ package v1alpha2 import ( v1 "k8s.io/api/core/v1" runtime "k8s.io/apimachinery/pkg/runtime" - userdata "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/userdata" - common "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + errors "sigs.k8s.io/cluster-api/pkg/errors" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AWSClusterProviderSpec) DeepCopyInto(out *AWSClusterProviderSpec) { +func (in *APIEndpoint) DeepCopyInto(out *APIEndpoint) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIEndpoint. +func (in *APIEndpoint) DeepCopy() *APIEndpoint { + if in == nil { + return nil + } + out := new(APIEndpoint) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSCluster) DeepCopyInto(out *AWSCluster) { *out = *in out.TypeMeta = in.TypeMeta in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.NetworkSpec.DeepCopyInto(&out.NetworkSpec) - if in.CAKeyPair != nil { - in, out := &in.CAKeyPair, &out.CAKeyPair - *out = new(KeyPair) - (*in).DeepCopyInto(*out) - } - if in.EtcdCAKeyPair != nil { - in, out := &in.EtcdCAKeyPair, &out.EtcdCAKeyPair - *out = new(KeyPair) - (*in).DeepCopyInto(*out) - } - if in.FrontProxyCAKeyPair != nil { - in, out := &in.FrontProxyCAKeyPair, &out.FrontProxyCAKeyPair - *out = new(KeyPair) - (*in).DeepCopyInto(*out) - } - if in.SAKeyPair != nil { - in, out := &in.SAKeyPair, &out.SAKeyPair - *out = new(KeyPair) - (*in).DeepCopyInto(*out) - } - if in.AdditionalUserDataFiles != nil { - in, out := &in.AdditionalUserDataFiles, &out.AdditionalUserDataFiles - *out = make([]userdata.Files, len(*in)) - copy(*out, *in) - } + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSClusterProviderSpec. -func (in *AWSClusterProviderSpec) DeepCopy() *AWSClusterProviderSpec { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSCluster. +func (in *AWSCluster) DeepCopy() *AWSCluster { if in == nil { return nil } - out := new(AWSClusterProviderSpec) + out := new(AWSCluster) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *AWSClusterProviderSpec) DeepCopyObject() runtime.Object { +func (in *AWSCluster) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } @@ -80,33 +71,78 @@ func (in *AWSClusterProviderSpec) DeepCopyObject() runtime.Object { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *AWSClusterProviderStatus) DeepCopyInto(out *AWSClusterProviderStatus) { +func (in *AWSClusterList) DeepCopyInto(out *AWSClusterList) { *out = *in out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Network.DeepCopyInto(&out.Network) - in.Bastion.DeepCopyInto(&out.Bastion) + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]AWSCluster, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } return } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSClusterProviderStatus. -func (in *AWSClusterProviderStatus) DeepCopy() *AWSClusterProviderStatus { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSClusterList. +func (in *AWSClusterList) DeepCopy() *AWSClusterList { if in == nil { return nil } - out := new(AWSClusterProviderStatus) + out := new(AWSClusterList) in.DeepCopyInto(out) return out } // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *AWSClusterProviderStatus) DeepCopyObject() runtime.Object { +func (in *AWSClusterList) DeepCopyObject() runtime.Object { if c := in.DeepCopy(); c != nil { return c } return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSClusterSpec) DeepCopyInto(out *AWSClusterSpec) { + *out = *in + in.NetworkSpec.DeepCopyInto(&out.NetworkSpec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSClusterSpec. +func (in *AWSClusterSpec) DeepCopy() *AWSClusterSpec { + if in == nil { + return nil + } + out := new(AWSClusterSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AWSClusterStatus) DeepCopyInto(out *AWSClusterStatus) { + *out = *in + in.Network.DeepCopyInto(&out.Network) + in.Bastion.DeepCopyInto(&out.Bastion) + if in.APIEndpoints != nil { + in, out := &in.APIEndpoints, &out.APIEndpoints + *out = make([]APIEndpoint, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AWSClusterStatus. +func (in *AWSClusterStatus) DeepCopy() *AWSClusterStatus { + if in == nil { + return nil + } + out := new(AWSClusterStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *AWSMachine) DeepCopyInto(out *AWSMachine) { *out = *in @@ -234,7 +270,7 @@ func (in *AWSMachineStatus) DeepCopyInto(out *AWSMachineStatus) { } if in.ErrorReason != nil { in, out := &in.ErrorReason, &out.ErrorReason - *out = new(common.MachineStatusError) + *out = new(errors.MachineStatusError) **out = **in } if in.ErrorMessage != nil { @@ -646,32 +682,6 @@ func (in *Instance) DeepCopy() *Instance { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KeyPair) DeepCopyInto(out *KeyPair) { - *out = *in - if in.Cert != nil { - in, out := &in.Cert, &out.Cert - *out = make([]byte, len(*in)) - copy(*out, *in) - } - if in.Key != nil { - in, out := &in.Key, &out.Key - *out = make([]byte, len(*in)) - copy(*out, *in) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KeyPair. -func (in *KeyPair) DeepCopy() *KeyPair { - if in == nil { - return nil - } - out := new(KeyPair) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Network) DeepCopyInto(out *Network) { *out = *in diff --git a/pkg/cloud/actuators/BUILD.bazel b/pkg/cloud/actuators/BUILD.bazel deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/pkg/cloud/actuators/cluster/BUILD.bazel b/pkg/cloud/actuators/cluster/BUILD.bazel deleted file mode 100644 index 0c787a1fc7..0000000000 --- a/pkg/cloud/actuators/cluster/BUILD.bazel +++ /dev/null @@ -1,36 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["actuator.go"], - importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/actuators/cluster", - visibility = ["//visibility:public"], - deps = [ - "//pkg/apis/infrastructure/v1alpha2:go_default_library", - "//pkg/cloud/scope:go_default_library", - "//pkg/cloud/services/certificates:go_default_library", - "//pkg/cloud/services/ec2:go_default_library", - "//pkg/cloud/services/elb:go_default_library", - "//pkg/deployer:go_default_library", - "//vendor/github.com/go-logr/logr:go_default_library", - "//vendor/github.com/pkg/errors:go_default_library", - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library", - "//vendor/k8s.io/klog/klogr:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha2:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/controller/remote:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/util:go_default_library", - "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["actuator_test.go"], - embed = [":go_default_library"], - deps = ["//vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster:go_default_library"], -) diff --git a/pkg/cloud/actuators/cluster/actuator.go b/pkg/cloud/actuators/cluster/actuator.go deleted file mode 100644 index 5fea53bdc9..0000000000 --- a/pkg/cloud/actuators/cluster/actuator.go +++ /dev/null @@ -1,223 +0,0 @@ -/* -Copyright 2018 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 cluster - -import ( - "context" - "time" - - "github.com/go-logr/logr" - "github.com/pkg/errors" - apiv1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - corev1 "k8s.io/client-go/kubernetes/typed/core/v1" - "k8s.io/klog/klogr" - "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/certificates" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb" - "sigs.k8s.io/cluster-api-provider-aws/pkg/deployer" - clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" - clientv1 "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha2" - "sigs.k8s.io/cluster-api/pkg/controller/remote" - controllerError "sigs.k8s.io/cluster-api/pkg/errors" - "sigs.k8s.io/cluster-api/pkg/util" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -const waitForControlPlaneMachineDuration = 15 * time.Second //nolint - -// Actuator is responsible for performing cluster reconciliation -type Actuator struct { - *deployer.Deployer - client.Client - - coreClient corev1.CoreV1Interface - clusterClient clientv1.ClusterV1alpha2Interface - log logr.Logger -} - -// ActuatorParams holds parameter information for Actuator -type ActuatorParams struct { - Client client.Client - CoreClient corev1.CoreV1Interface - ClusterClient clientv1.ClusterV1alpha2Interface - LoggingContext string -} - -// NewActuator creates a new Actuator -func NewActuator(params ActuatorParams) *Actuator { - return &Actuator{ - clusterClient: params.ClusterClient, - coreClient: params.CoreClient, - log: klogr.New().WithName(params.LoggingContext), - Deployer: deployer.New(deployer.Params{ClusterScopeGetter: scope.DefaultClusterScopeGetter}), - } -} - -// Reconcile reconciles a cluster and is invoked by the Cluster Controller -func (a *Actuator) Reconcile(cluster *clusterv1.Cluster) error { - log := a.log.WithValues("cluster-name", cluster.Name, "cluster-namespace", cluster.Namespace) - log.Info("Reconciling Cluster") - - scope, err := scope.NewClusterScope(scope.ClusterScopeParams{ - Cluster: cluster, - Logger: a.log, - }) - if err != nil { - return errors.Errorf("failed to create scope: %+v", err) - } - - defer scope.Close() - - ec2svc := ec2.NewService(scope) - elbsvc := elb.NewService(scope) - certSvc := certificates.NewService(scope) - - // Store cert material in spec. - if err := certSvc.ReconcileCertificates(); err != nil { - return errors.Wrapf(err, "failed to reconcile certificates for cluster %q", cluster.Name) - } - - if err := ec2svc.ReconcileNetwork(); err != nil { - return errors.Wrapf(err, "failed to reconcile network for cluster %q", cluster.Name) - } - - if err := ec2svc.ReconcileBastion(); err != nil { - return errors.Wrapf(err, "failed to reconcile bastion host for cluster %q", cluster.Name) - } - - if err := elbsvc.ReconcileLoadbalancers(); err != nil { - return errors.Wrapf(err, "failed to reconcile load balancers for cluster %q", cluster.Name) - } - - if cluster.Annotations == nil { - cluster.Annotations = make(map[string]string) - } - cluster.Annotations[v1alpha2.AnnotationClusterInfrastructureReady] = v1alpha2.ValueReady - - // Store KubeConfig for Cluster API NodeRef controller to use. - kubeConfigSecretName := remote.KubeConfigSecretName(cluster.Name) - secretClient := a.coreClient.Secrets(cluster.Namespace) - if _, err := secretClient.Get(kubeConfigSecretName, metav1.GetOptions{}); err != nil && apierrors.IsNotFound(err) { - kubeConfig, err := a.Deployer.GetKubeConfig(cluster, nil) - if err != nil { - return errors.Wrapf(err, "failed to get kubeconfig for cluster %q", cluster.Name) - } - - kubeConfigSecret := &apiv1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: kubeConfigSecretName, - }, - StringData: map[string]string{ - "value": kubeConfig, - }, - } - - if _, err := secretClient.Create(kubeConfigSecret); err != nil { - return errors.Wrapf(err, "failed to create kubeconfig secret for cluster %q", cluster.Name) - } - } else if err != nil { - return errors.Wrapf(err, "failed to get kubeconfig secret for cluster %q", cluster.Name) - } - - // If the control plane is ready, try to delete the control plane configmap lock, if it exists, and return. - if cluster.Annotations[v1alpha2.AnnotationControlPlaneReady] == v1alpha2.ValueReady { - configMapName := scope.ControlPlaneConfigMapName() - log.Info("Checking for existence of control plane configmap lock", "configmap-name", configMapName) - - _, err := a.coreClient.ConfigMaps(cluster.Namespace).Get(configMapName, metav1.GetOptions{}) - switch { - case apierrors.IsNotFound(err): - // It doesn't exist - no-op - case err != nil: - return errors.Wrapf(err, "Error retrieving control plane configmap lock %q", configMapName) - default: - if err := a.coreClient.ConfigMaps(cluster.Namespace).Delete(configMapName, nil); err != nil { - return errors.Wrapf(err, "Error deleting control plane configmap lock %q", configMapName) - } - } - - // Nothing more to reconcile - return early. - return nil - } - - log.Info("Cluster does not have ready annotation - checking for ready control plane machines") - - machineList := &clusterv1.MachineList{} - if err := a.List(context.Background(), machineList, scope.ListOptionsLabelSelector()); err != nil { - return errors.Wrapf(err, "failed to retrieve machines in cluster %q", cluster.Name) - } - - controlPlaneMachines := util.GetControlPlaneMachinesFromList(machineList) - - machineReady := false - for _, machine := range controlPlaneMachines { - if machine.Status.NodeRef != nil { - machineReady = true - break - } - } - - if !machineReady { - log.Info("No control plane machines are ready - requeuing cluster") - return &controllerError.RequeueAfterError{RequeueAfter: waitForControlPlaneMachineDuration} - } - - log.Info("Setting cluster ready annotation") - cluster.Annotations[v1alpha2.AnnotationControlPlaneReady] = v1alpha2.ValueReady - - return nil -} - -// Delete deletes a cluster and is invoked by the Cluster Controller -func (a *Actuator) Delete(cluster *clusterv1.Cluster) error { - a.log.Info("Deleting cluster", "cluster-name", cluster.Name, "cluster-namespace", cluster.Namespace) - - scope, err := scope.NewClusterScope(scope.ClusterScopeParams{ - Cluster: cluster, - Client: a.Client, - Logger: a.log, - }) - if err != nil { - return errors.Errorf("failed to create scope: %+v", err) - } - - defer scope.Close() - - ec2svc := ec2.NewService(scope) - elbsvc := elb.NewService(scope) - - if err := elbsvc.DeleteLoadbalancers(); err != nil { - return errors.Errorf("unable to delete load balancers: %+v", err) - } - - if err := ec2svc.DeleteBastion(); err != nil { - return errors.Errorf("unable to delete bastion: %+v", err) - } - - if err := ec2svc.DeleteNetwork(); err != nil { - a.log.Error(err, "Error deleting cluster", "cluster-name", cluster.Name, "cluster-namespace", cluster.Namespace) - return &controllerError.RequeueAfterError{ - RequeueAfter: 5 * time.Second, - } - } - - return nil -} diff --git a/pkg/cloud/scope/BUILD.bazel b/pkg/cloud/scope/BUILD.bazel index 8ca498410f..08f2c2d400 100644 --- a/pkg/cloud/scope/BUILD.bazel +++ b/pkg/cloud/scope/BUILD.bazel @@ -23,7 +23,6 @@ go_library( "//vendor/github.com/pkg/errors:go_default_library", "//vendor/k8s.io/klog/klogr:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/noderefutil:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", diff --git a/pkg/cloud/scope/cluster.go b/pkg/cloud/scope/cluster.go index c072e206ea..74009f3d4b 100644 --- a/pkg/cloud/scope/cluster.go +++ b/pkg/cloud/scope/cluster.go @@ -26,38 +26,34 @@ import ( "github.com/pkg/errors" "k8s.io/klog/klogr" "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" - clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" + clusterv1alpha2 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/controller-runtime/pkg/client" ) -const apiEndpointPort = 6443 - // ClusterScopeParams defines the input parameters used to create a new Scope. type ClusterScopeParams struct { AWSClients - Client client.Client - Logger logr.Logger - Cluster *clusterv1.Cluster + Client client.Client + Logger logr.Logger + Cluster *clusterv1alpha2.Cluster + AWSCluster *v1alpha2.AWSCluster } // NewClusterScope creates a new Scope from the supplied parameters. -// This is meant to be called for each different actuator iteration. +// This is meant to be called for each reconcile iteration. func NewClusterScope(params ClusterScopeParams) (*ClusterScope, error) { if params.Cluster == nil { - return nil, errors.New("failed to generate new scope from nil cluster") + return nil, errors.New("failed to generate new scope from nil Cluster") } - - clusterConfig, err := v1alpha2.ClusterConfigFromProviderSpec(params.Cluster.Spec.ProviderSpec) - if err != nil { - return nil, errors.Errorf("failed to load cluster provider config: %v", err) + if params.AWSCluster == nil { + return nil, errors.New("failed to generate new scope from nil AWSCluster") } - clusterStatus, err := v1alpha2.ClusterStatusFromProviderStatus(params.Cluster.Status.ProviderStatus) - if err != nil { - return nil, errors.Errorf("failed to load cluster provider status: %v", err) + if params.Logger == nil { + params.Logger = klogr.New() } - session, err := sessionForRegion(clusterConfig.Region) + session, err := sessionForRegion(params.AWSCluster.Spec.Region) if err != nil { return nil, errors.Errorf("failed to create aws session: %v", err) } @@ -70,55 +66,44 @@ func NewClusterScope(params ClusterScopeParams) (*ClusterScope, error) { params.AWSClients.ELB = elb.New(session) } - if params.Logger == nil { - params.Logger = klogr.New() - } - return &ClusterScope{ - client: params.Client, - clusterPatch: client.MergeFrom(params.Cluster.DeepCopy()), - - AWSClients: params.AWSClients, - Cluster: params.Cluster, - ClusterConfig: clusterConfig, - ClusterStatus: clusterStatus, - Logger: params.Logger. - WithName(params.Cluster.APIVersion). - WithName(fmt.Sprintf("namespace=%s", params.Cluster.Namespace)). - WithName(fmt.Sprintf("cluster=%s", params.Cluster.Name)), + Logger: params.Logger, + client: params.Client, + AWSClients: params.AWSClients, + Cluster: params.Cluster, + AWSCluster: params.AWSCluster, + awsClusterPatch: client.MergeFrom(params.AWSCluster.DeepCopy()), }, nil } // ClusterScope defines the basic context for an actuator to operate upon. type ClusterScope struct { logr.Logger - client client.Client - clusterPatch client.Patch - + client client.Client AWSClients - Cluster *clusterv1.Cluster - ClusterConfig *v1alpha2.AWSClusterProviderSpec - ClusterStatus *v1alpha2.AWSClusterProviderStatus + Cluster *clusterv1alpha2.Cluster + AWSCluster *v1alpha2.AWSCluster + awsClusterPatch client.Patch } // Network returns the cluster network object. func (s *ClusterScope) Network() *v1alpha2.Network { - return &s.ClusterStatus.Network + return &s.AWSCluster.Status.Network } // VPC returns the cluster VPC. func (s *ClusterScope) VPC() *v1alpha2.VPCSpec { - return &s.ClusterConfig.NetworkSpec.VPC + return &s.AWSCluster.Spec.NetworkSpec.VPC } // Subnets returns the cluster subnets. func (s *ClusterScope) Subnets() v1alpha2.Subnets { - return s.ClusterConfig.NetworkSpec.Subnets + return s.AWSCluster.Spec.NetworkSpec.Subnets } // SecurityGroups returns the cluster security groups as a map, it creates the map if empty. func (s *ClusterScope) SecurityGroups() map[v1alpha2.SecurityGroupRole]v1alpha2.SecurityGroup { - return s.ClusterStatus.Network.SecurityGroups + return s.AWSCluster.Status.Network.SecurityGroups } // Name returns the cluster name. @@ -133,7 +118,7 @@ func (s *ClusterScope) Namespace() string { // Region returns the cluster region. func (s *ClusterScope) Region() string { - return s.ClusterConfig.Region + return s.AWSCluster.Spec.Region } // ControlPlaneConfigMapName returns the name of the ConfigMap used to @@ -145,43 +130,23 @@ func (s *ClusterScope) ControlPlaneConfigMapName() string { // ListOptionsLabelSelector returns a ListOptions with a label selector for clusterName. func (s *ClusterScope) ListOptionsLabelSelector() client.ListOptionFunc { return client.MatchingLabels(map[string]string{ - clusterv1.MachineClusterLabelName: s.Cluster.Name, + clusterv1alpha2.MachineClusterLabelName: s.Cluster.Name, }) } // Close closes the current scope persisting the cluster configuration and status. -func (s *ClusterScope) Close() { - ctx := context.Background() +func (s *ClusterScope) Close() error { + ctx := context.TODO() // Patch Cluster object. - ext, err := v1alpha2.EncodeClusterSpec(s.ClusterConfig) - if err != nil { - s.Error(err, "failed encoding cluster spec") - return - } - s.Cluster.Spec.ProviderSpec.Value = ext - if err := s.client.Patch(ctx, s.Cluster, s.clusterPatch); err != nil { - s.Error(err, "failed to patch object") - return + if err := s.client.Patch(ctx, s.AWSCluster, s.awsClusterPatch); err != nil { + return errors.Wrapf(err, "error patching AWSCluster %s/%s", s.Cluster.Namespace, s.Cluster.Name) } // Patch Cluster status. - newStatus, err := v1alpha2.EncodeClusterStatus(s.ClusterStatus) - if err != nil { - s.Error(err, "failed encoding cluster status") - return - } - if s.ClusterStatus.Network.APIServerELB.DNSName != "" { - s.Cluster.Status.APIEndpoints = []clusterv1.APIEndpoint{ - { - Host: s.ClusterStatus.Network.APIServerELB.DNSName, - Port: apiEndpointPort, - }, - } - } - s.Cluster.Status.ProviderStatus = newStatus - if err := s.client.Status().Patch(ctx, s.Cluster, s.clusterPatch); err != nil { - s.Error(err, "failed to patch object status") - return + if err := s.client.Status().Patch(ctx, s.AWSCluster, s.awsClusterPatch); err != nil { + return errors.Wrapf(err, "error patching AWSCluster %s/%s status", s.Cluster.Namespace, s.Cluster.Name) } + + return nil } diff --git a/pkg/cloud/scope/machine.go b/pkg/cloud/scope/machine.go index 5a2965e400..54b0ad183d 100644 --- a/pkg/cloud/scope/machine.go +++ b/pkg/cloud/scope/machine.go @@ -18,8 +18,6 @@ package scope import ( "context" - "fmt" - "time" "github.com/pkg/errors" "k8s.io/klog/klogr" @@ -27,7 +25,6 @@ import ( "github.com/go-logr/logr" "k8s.io/utils/pointer" infrav1 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/controller/noderefutil" capierrors "sigs.k8s.io/cluster-api/pkg/errors" @@ -38,65 +35,37 @@ import ( // MachineScopeParams defines the input parameters used to create a new MachineScope. type MachineScopeParams struct { AWSClients - Client client.Client - Logger logr.Logger - ProviderMachine *infrav1.AWSMachine + Client client.Client + Logger logr.Logger + Cluster *clusterv1.Cluster + //AWSCluster *infrav1.AWSCluster + Machine *clusterv1.Machine + AWSMachine *infrav1.AWSMachine } // NewMachineScope creates a new MachineScope from the supplied parameters. -// This is meant to be called for each machine actuator operation. +// This is meant to be called for each reconcile iteration. func NewMachineScope(params MachineScopeParams) (*MachineScope, error) { if params.Client == nil { return nil, errors.New("client is required when creating a MachineScope") } - if params.ProviderMachine == nil { - return nil, errors.New("provider machine is required when creating a MachineScope") + if params.Machine == nil { + return nil, errors.New("machine is required when creating a MachineScope") + } + if params.AWSMachine == nil { + return nil, errors.New("aws machine is required when creating a MachineScope") } if params.Logger == nil { params.Logger = klogr.New() } - ctx := context.Background() - - // Fetch the Machine. - machine, err := util.GetOwnerMachine(ctx, params.Client, params.ProviderMachine.ObjectMeta) - if err != nil { - return nil, err - } - if machine == nil { - params.Logger.Info("Waiting for Machine Controller to set OwnerRef on AWSMachine", - "namespace", params.ProviderMachine.Namespace, - "name", params.ProviderMachine.Name) - - return nil, &capierrors.RequeueAfterError{RequeueAfter: 10 * time.Second} - } - - // Fetch the cluster. - cluster, err := util.GetClusterFromMetadata(ctx, params.Client, machine.ObjectMeta) - if err != nil { - return nil, err - } - - clusterScope, err := NewClusterScope(ClusterScopeParams{ - AWSClients: params.AWSClients, - Client: params.Client, - Cluster: cluster, - Logger: params.Logger, - }) - if err != nil { - return nil, err - } - return &MachineScope{ - client: params.Client, - patch: client.MergeFrom(params.ProviderMachine.DeepCopy()), - Parent: clusterScope, - Machine: machine, - ProviderMachine: params.ProviderMachine, - Logger: clusterScope.Logger. - WithName(fmt.Sprintf("machine=%s", machine.Name)). - WithName(fmt.Sprintf("providerMachine=%s", params.ProviderMachine.Name)), + client: params.Client, + patch: client.MergeFrom(params.AWSMachine.DeepCopy()), + Machine: params.Machine, + AWSMachine: params.AWSMachine, + Logger: params.Logger, }, nil } @@ -106,24 +75,19 @@ type MachineScope struct { patch client.Patch client client.Client - Parent *ClusterScope - Machine *clusterv1.Machine - ProviderMachine *infrav1.AWSMachine + Cluster *clusterv1.Cluster + Machine *clusterv1.Machine + AWSMachine *infrav1.AWSMachine } // Name returns the AWSMachine name. func (m *MachineScope) Name() string { - return m.ProviderMachine.Name + return m.AWSMachine.Name } // Namespace returns the namespace name. func (m *MachineScope) Namespace() string { - return m.ProviderMachine.Namespace -} - -// ClusterName returns the parent Cluster name. -func (m *MachineScope) ClusterName() string { - return m.Parent.Name() + return m.AWSMachine.Namespace } // IsControlPlane returns true if the machine is a control plane. @@ -139,11 +103,6 @@ func (m *MachineScope) Role() string { return "node" } -// Region returns the machine region. -func (m *MachineScope) Region() string { - return m.Parent.Region() -} - // GetInstanceID returns the AWSMachine instance id by parsing Spec.ProviderID. func (m *MachineScope) GetInstanceID() *string { parsed, err := noderefutil.NewProviderID(m.GetProviderID()) @@ -155,60 +114,60 @@ func (m *MachineScope) GetInstanceID() *string { // GetProviderID returns the AWSMachine providerID from the spec. func (m *MachineScope) GetProviderID() string { - if m.ProviderMachine.Spec.ProviderID != nil { - return *m.ProviderMachine.Spec.ProviderID + if m.AWSMachine.Spec.ProviderID != nil { + return *m.AWSMachine.Spec.ProviderID } return "" } // SetProviderID sets the AWSMachine providerID in spec. func (m *MachineScope) SetProviderID(v string) { - m.ProviderMachine.Spec.ProviderID = pointer.StringPtr(v) + m.AWSMachine.Spec.ProviderID = pointer.StringPtr(v) } // GetInstanceID returns the AWSMachine instance state from the status. func (m *MachineScope) GetInstanceState() *infrav1.InstanceState { - return m.ProviderMachine.Status.InstanceState + return m.AWSMachine.Status.InstanceState } // SetInstanceID sets the AWSMachine instance id. func (m *MachineScope) SetInstanceState(v infrav1.InstanceState) { - m.ProviderMachine.Status.InstanceState = &v + m.AWSMachine.Status.InstanceState = &v } // SetErrorMessage sets the AWSMachine status error message. func (m *MachineScope) SetErrorMessage(v error) { - m.ProviderMachine.Status.ErrorMessage = pointer.StringPtr(v.Error()) + m.AWSMachine.Status.ErrorMessage = pointer.StringPtr(v.Error()) } // SetErrorReason sets the AWSMachine status error reason. -func (m *MachineScope) SetErrorReason(v common.MachineStatusError) { - m.ProviderMachine.Status.ErrorReason = &v +func (m *MachineScope) SetErrorReason(v capierrors.MachineStatusError) { + m.AWSMachine.Status.ErrorReason = &v } // SetAnnotation sets a key value annotation on the AWSMachine. func (m *MachineScope) SetAnnotation(key, value string) { - if m.ProviderMachine.Annotations == nil { - m.ProviderMachine.Annotations = map[string]string{} + if m.AWSMachine.Annotations == nil { + m.AWSMachine.Annotations = map[string]string{} } - m.ProviderMachine.Annotations[key] = value + m.AWSMachine.Annotations[key] = value } // Close the MachineScope by updating the machine spec, machine status. func (m *MachineScope) Close() error { ctx := context.Background() - gvk := m.ProviderMachine.GroupVersionKind() + gvk := m.AWSMachine.GroupVersionKind() - if err := m.client.Patch(ctx, m.ProviderMachine, m.patch); err != nil { + if err := m.client.Patch(ctx, m.AWSMachine, m.patch); err != nil { return errors.WithStack(err) } // TODO(ncdc): This is a hack because after a Patch, the object loses TypeMeta information. // Remove when https://github.com/kubernetes-sigs/controller-runtime/issues/526 is fixed. - m.ProviderMachine.SetGroupVersionKind(gvk) + m.AWSMachine.SetGroupVersionKind(gvk) - if err := m.client.Status().Patch(ctx, m.ProviderMachine, m.patch); err != nil { + if err := m.client.Status().Patch(ctx, m.AWSMachine, m.patch); err != nil { return errors.WithStack(err) } diff --git a/pkg/cloud/services/BUILD.bazel b/pkg/cloud/services/BUILD.bazel index d8f9a9e0de..23820ac458 100644 --- a/pkg/cloud/services/BUILD.bazel +++ b/pkg/cloud/services/BUILD.bazel @@ -8,6 +8,5 @@ go_library( deps = [ "//pkg/apis/infrastructure/v1alpha2:go_default_library", "//pkg/cloud/scope:go_default_library", - "//vendor/github.com/aws/aws-sdk-go/aws/session:go_default_library", ], ) diff --git a/pkg/cloud/services/certificates/BUILD.bazel b/pkg/cloud/services/certificates/BUILD.bazel deleted file mode 100644 index 04a2231fde..0000000000 --- a/pkg/cloud/services/certificates/BUILD.bazel +++ /dev/null @@ -1,27 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = [ - "certificates.go", - "service.go", - ], - importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/certificates", - visibility = ["//visibility:public"], - deps = [ - "//pkg/apis/infrastructure/v1alpha2:go_default_library", - "//pkg/cloud/scope:go_default_library", - "//vendor/github.com/pkg/errors:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["certificates_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/apis/infrastructure/v1alpha2:go_default_library", - "//vendor/github.com/pkg/errors:go_default_library", - ], -) diff --git a/pkg/cloud/services/certificates/certificates.go b/pkg/cloud/services/certificates/certificates.go deleted file mode 100644 index 115c3cac33..0000000000 --- a/pkg/cloud/services/certificates/certificates.go +++ /dev/null @@ -1,336 +0,0 @@ -/* -Copyright 2018 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 certificates - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/sha256" - "crypto/x509" - "crypto/x509/pkix" - "encoding/hex" - "encoding/pem" - "fmt" - "math" - "math/big" - "net" - "strings" - "time" - - "github.com/pkg/errors" - "k8s.io/client-go/tools/clientcmd/api" - "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" -) - -const ( - rsaKeySize = 2048 - duration365d = time.Hour * 24 * 365 - clusterCA = "cluster-ca" - etcdCA = "etcd-ca" - frontProxyCA = "front-proxy-ca" - serviceAccount = "service-account" -) - -// NewPrivateKey creates an RSA private key -func NewPrivateKey() (*rsa.PrivateKey, error) { - return rsa.GenerateKey(rand.Reader, rsaKeySize) -} - -// AltNames contains the domain names and IP addresses that will be added -// to the API Server's x509 certificate SubAltNames field. The values will -// be passed directly to the x509.Certificate object. -type AltNames struct { - DNSNames []string - IPs []net.IP -} - -// Config contains the basic fields required for creating a certificate -type Config struct { - CommonName string - Organization []string - AltNames AltNames - Usages []x509.ExtKeyUsage -} - -// ReconcileCertificates generate certificates if none exists. -func (s *Service) ReconcileCertificates() error { - s.scope.V(2).Info("Reconciling certificates", "cluster-name", s.scope.Cluster.Name, "cluster-namespace", s.scope.Cluster.Namespace) - - if s.scope.ClusterConfig.CAKeyPair == nil || !s.scope.ClusterConfig.CAKeyPair.HasCertAndKey() { - s.scope.V(2).Info("Generating keypair for", "user", clusterCA) - clusterCAKeyPair, err := generateCACert(s.scope.ClusterConfig.CAKeyPair, clusterCA) - if err != nil { - return errors.Wrapf(err, "Failed to generate certs for %q", clusterCA) - } - s.scope.ClusterConfig.CAKeyPair = clusterCAKeyPair - } - - if s.scope.ClusterConfig.EtcdCAKeyPair == nil || !s.scope.ClusterConfig.EtcdCAKeyPair.HasCertAndKey() { - s.scope.V(2).Info("Generating keypair", "user", etcdCA) - etcdCAKeyPair, err := generateCACert(s.scope.ClusterConfig.EtcdCAKeyPair, etcdCA) - if err != nil { - return errors.Wrapf(err, "Failed to generate certs for %q", etcdCA) - } - s.scope.ClusterConfig.EtcdCAKeyPair = etcdCAKeyPair - } - if s.scope.ClusterConfig.FrontProxyCAKeyPair == nil || !s.scope.ClusterConfig.FrontProxyCAKeyPair.HasCertAndKey() { - s.scope.V(2).Info("Generating keypair", "user", frontProxyCA) - fpCAKeyPair, err := generateCACert(s.scope.ClusterConfig.FrontProxyCAKeyPair, frontProxyCA) - if err != nil { - return errors.Wrapf(err, "Failed to generate certs for %q", frontProxyCA) - } - s.scope.ClusterConfig.FrontProxyCAKeyPair = fpCAKeyPair - } - - if s.scope.ClusterConfig.SAKeyPair == nil || !s.scope.ClusterConfig.SAKeyPair.HasCertAndKey() { - s.scope.V(2).Info("Generating service account keys", "user", serviceAccount) - saKeyPair, err := generateServiceAccountKeys(s.scope.ClusterConfig.SAKeyPair, serviceAccount) - if err != nil { - return errors.Wrapf(err, "Failed to generate keyPair for %q", serviceAccount) - } - s.scope.ClusterConfig.SAKeyPair = saKeyPair - } - return nil -} - -func generateCACert(kp *v1alpha2.KeyPair, user string) (*v1alpha2.KeyPair, error) { - x509Cert, privKey, err := NewCertificateAuthority() - if err != nil { - return nil, errors.Wrapf(err, "failed to generate CA cert for %q", user) - } - if kp == nil { - return &v1alpha2.KeyPair{ - Cert: EncodeCertPEM(x509Cert), - Key: EncodePrivateKeyPEM(privKey), - }, nil - } - kp.Cert = EncodeCertPEM(x509Cert) - kp.Key = EncodePrivateKeyPEM(privKey) - return kp, nil -} - -func generateServiceAccountKeys(kp *v1alpha2.KeyPair, user string) (*v1alpha2.KeyPair, error) { - saCreds, err := NewPrivateKey() - if err != nil { - return nil, errors.Wrapf(err, "failed to create service account public and private keys") - } - saPub, err := EncodePublicKeyPEM(&saCreds.PublicKey) - if err != nil { - return nil, errors.Wrapf(err, "failed to encode service account public key to PEM") - } - if kp == nil { - return &v1alpha2.KeyPair{ - Cert: saPub, - Key: EncodePrivateKeyPEM(saCreds), - }, nil - } - kp.Cert = saPub - kp.Key = EncodePrivateKeyPEM(saCreds) - return kp, nil -} - -// NewSignedCert creates a signed certificate using the given CA certificate and key -func (cfg *Config) NewSignedCert(key *rsa.PrivateKey, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*x509.Certificate, error) { - serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64)) - if err != nil { - return nil, errors.Wrap(err, "failed to generate random integer for signed cerficate") - } - - if len(cfg.CommonName) == 0 { - return nil, errors.New("must specify a CommonName") - } - - if len(cfg.Usages) == 0 { - return nil, errors.New("must specify at least one ExtKeyUsage") - } - - tmpl := x509.Certificate{ - Subject: pkix.Name{ - CommonName: cfg.CommonName, - Organization: cfg.Organization, - }, - DNSNames: cfg.AltNames.DNSNames, - IPAddresses: cfg.AltNames.IPs, - SerialNumber: serial, - NotBefore: caCert.NotBefore, - NotAfter: time.Now().Add(duration365d).UTC(), - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, - ExtKeyUsage: cfg.Usages, - } - - b, err := x509.CreateCertificate(rand.Reader, &tmpl, caCert, key.Public(), caKey) - if err != nil { - return nil, errors.Wrapf(err, "failed to create signed certificate: %+v", tmpl) - } - - return x509.ParseCertificate(b) -} - -// NewCertificateAuthority creates new certificate and private key for the certificate authority -func NewCertificateAuthority() (*x509.Certificate, *rsa.PrivateKey, error) { - key, err := NewPrivateKey() - if err != nil { - return nil, nil, errors.Wrap(err, "unable to create private key") - } - - cert, err := NewSelfSignedCACert(key) - if err != nil { - return nil, nil, errors.Wrap(err, "unable to create self-signed certificate") - } - - return cert, key, nil -} - -// NewSelfSignedCACert creates a CA certificate. -func NewSelfSignedCACert(key *rsa.PrivateKey) (*x509.Certificate, error) { - cfg := Config{ - CommonName: "kubernetes", - } - - now := time.Now().UTC() - - tmpl := x509.Certificate{ - SerialNumber: new(big.Int).SetInt64(0), - Subject: pkix.Name{ - CommonName: cfg.CommonName, - Organization: cfg.Organization, - }, - NotBefore: now, - NotAfter: now.Add(duration365d * 10), - KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, - MaxPathLenZero: true, - BasicConstraintsValid: true, - MaxPathLen: 0, - IsCA: true, - } - - b, err := x509.CreateCertificate(rand.Reader, &tmpl, &tmpl, key.Public(), key) - if err != nil { - return nil, errors.Wrapf(err, "failed to create self signed CA certificate: %+v", tmpl) - } - - return x509.ParseCertificate(b) -} - -// NewKubeconfig creates a new Kubeconfig where endpoint is the ELB endpoint. -func NewKubeconfig(clusterName, endpoint string, caCert *x509.Certificate, caKey *rsa.PrivateKey) (*api.Config, error) { - cfg := &Config{ - CommonName: "kubernetes-admin", - Organization: []string{"system:masters"}, - Usages: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth}, - } - - clientKey, err := NewPrivateKey() - if err != nil { - return nil, errors.Wrap(err, "unable to create private key") - } - - clientCert, err := cfg.NewSignedCert(clientKey, caCert, caKey) - if err != nil { - return nil, errors.Wrap(err, "unable to sign certificate") - } - - userName := "kubernetes-admin" - contextName := fmt.Sprintf("%s@%s", userName, clusterName) - - return &api.Config{ - Clusters: map[string]*api.Cluster{ - clusterName: { - Server: endpoint, - CertificateAuthorityData: EncodeCertPEM(caCert), - }, - }, - Contexts: map[string]*api.Context{ - contextName: { - Cluster: clusterName, - AuthInfo: userName, - }, - }, - AuthInfos: map[string]*api.AuthInfo{ - userName: { - ClientKeyData: EncodePrivateKeyPEM(clientKey), - ClientCertificateData: EncodeCertPEM(clientCert), - }, - }, - CurrentContext: contextName, - }, nil -} - -// EncodeCertPEM returns PEM-endcoded certificate data. -func EncodeCertPEM(cert *x509.Certificate) []byte { - block := pem.Block{ - Type: "CERTIFICATE", - Bytes: cert.Raw, - } - return pem.EncodeToMemory(&block) -} - -// EncodePrivateKeyPEM returns PEM-encoded private key data. -func EncodePrivateKeyPEM(key *rsa.PrivateKey) []byte { - block := pem.Block{ - Type: "RSA PRIVATE KEY", - Bytes: x509.MarshalPKCS1PrivateKey(key), - } - - return pem.EncodeToMemory(&block) -} - -// EncodePublicKeyPEM returns PEM-encoded public key data. -func EncodePublicKeyPEM(key *rsa.PublicKey) ([]byte, error) { - der, err := x509.MarshalPKIXPublicKey(key) - if err != nil { - return []byte{}, err - } - block := pem.Block{ - Type: "PUBLIC KEY", - Bytes: der, - } - return pem.EncodeToMemory(&block), nil -} - -// DecodeCertPEM attempts to return a decoded certificate or nil -// if the encoded input does not contain a certificate. -func DecodeCertPEM(encoded []byte) (*x509.Certificate, error) { - block, _ := pem.Decode(encoded) - if block == nil { - return nil, nil - } - - return x509.ParseCertificate(block.Bytes) -} - -// DecodePrivateKeyPEM attempts to return a decoded key or nil -// if the encoded input does not contain a private key. -func DecodePrivateKeyPEM(encoded []byte) (*rsa.PrivateKey, error) { - block, _ := pem.Decode(encoded) - if block == nil { - return nil, nil - } - - return x509.ParsePKCS1PrivateKey(block.Bytes) -} - -// GenerateCertificateHash returns the encoded sha256 hash for the certificate provided -func GenerateCertificateHash(encoded []byte) (string, error) { - cert, err := DecodeCertPEM(encoded) - if err != nil || cert == nil { - return "", errors.Errorf("failed to parse PEM block containing the public key") - } - - certHash := sha256.Sum256(cert.RawSubjectPublicKeyInfo) - return "sha256:" + strings.ToLower(hex.EncodeToString(certHash[:])), nil -} diff --git a/pkg/cloud/services/certificates/certificates_test.go b/pkg/cloud/services/certificates/certificates_test.go deleted file mode 100644 index 3074c24f02..0000000000 --- a/pkg/cloud/services/certificates/certificates_test.go +++ /dev/null @@ -1,223 +0,0 @@ -/* -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 certificates - -import ( - "crypto/x509" - "testing" - - "github.com/pkg/errors" - "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" -) - -func TestGenerateCACert(t *testing.T) { - testCases := []struct { - name string - inputKeyPair *v1alpha2.KeyPair - inputUser string - expectKeyPairGen bool - expectedError error - }{ - { - name: "should generate keypair when inputKeyPair==nil", - inputKeyPair: nil, - inputUser: "foo-ca", - expectKeyPairGen: true, - expectedError: nil, - }, - { - name: "should generate keypair when inputKeyPair has no cert", - inputKeyPair: &v1alpha2.KeyPair{Key: []byte("foo-key")}, - inputUser: "foo-ca", - expectKeyPairGen: true, - expectedError: nil, - }, - { - name: "should generate keypair when inputKeyPair has no key", - inputKeyPair: &v1alpha2.KeyPair{Cert: []byte("foo-cert")}, - inputUser: "foo-ca", - expectKeyPairGen: true, - expectedError: nil, - }, - { - name: "should generate keypair when inputKeyPair has no cert and nokey", - inputKeyPair: &v1alpha2.KeyPair{}, - inputUser: "foo-ca", - expectKeyPairGen: true, - expectedError: nil, - }, - { - name: "should not generate keypair when inputKeyPair has cert and key", - inputKeyPair: &v1alpha2.KeyPair{Cert: []byte("foo-cert"), Key: []byte("foo-key")}, - inputUser: "foo-ca", - expectKeyPairGen: false, - expectedError: nil, - }, - } - for _, tc := range testCases { - actualKeyPair, actualError := generateCACert(tc.inputKeyPair, tc.inputUser) - if tc.expectedError != nil { - if tc.expectedError.Error() != actualError.Error() { - t.Fatalf("[%s], Unexpected error, Want [%v], Got: [%v]", tc.name, tc.expectedError, actualError) - } - continue - } - if !tc.expectKeyPairGen { - if len(tc.inputKeyPair.Cert) != len(actualKeyPair.Cert) || string(tc.inputKeyPair.Cert) != string(actualKeyPair.Cert) { - t.Fatalf("[%s] Want cert=%q, Got cert=%q", tc.name, string(tc.inputKeyPair.Cert), string(actualKeyPair.Cert)) - } - if len(tc.inputKeyPair.Key) != len(actualKeyPair.Key) || string(tc.inputKeyPair.Key) != string(actualKeyPair.Key) { - t.Fatalf("[%s] Want key=%q, Got key=%q", tc.name, string(tc.inputKeyPair.Key), string(actualKeyPair.Key)) - } - } else { - _, decodeErr := DecodeCertPEM(actualKeyPair.Cert) - if decodeErr != nil { - t.Fatalf("[%s], Expected to decode generated cert, Got decode failure %v", tc.name, decodeErr) - } - _, decodeErr = DecodePrivateKeyPEM(actualKeyPair.Key) - if decodeErr != nil { - t.Fatalf("[%s], Expected to decode generated private key, Got decode failure failed %v", tc.name, decodeErr) - } - } - } -} - -func TestGenerateServiceAccountKeys(t *testing.T) { - testCases := []struct { - name string - inputKeyPair *v1alpha2.KeyPair - inputUser string - expectKeyPairGen bool - expectedError error - }{ - { - name: "should generate keypair when inputKeyPair==nil", - inputKeyPair: nil, - inputUser: "foo-sa", - expectKeyPairGen: true, - expectedError: nil, - }, - { - name: "should generate keypair when inputKeyPair has no cert", - inputKeyPair: &v1alpha2.KeyPair{Key: []byte("foo-key")}, - inputUser: "foo-sa", - expectKeyPairGen: true, - expectedError: nil, - }, - { - name: "should generate keypair when inputKeyPair has no key", - inputKeyPair: &v1alpha2.KeyPair{Cert: []byte("foo-cert")}, - inputUser: "foo-sa", - expectKeyPairGen: true, - expectedError: nil, - }, - { - name: "should generate keypair when inputKeyPair has no cert and nokey", - inputKeyPair: &v1alpha2.KeyPair{}, - inputUser: "foo-ca", - expectKeyPairGen: true, - expectedError: nil, - }, - { - name: "should not generate keypair when inputKeyPair has cert and key", - inputKeyPair: &v1alpha2.KeyPair{Cert: []byte("foo-cert"), Key: []byte("foo-key")}, - inputUser: "foo-sa", - expectKeyPairGen: false, - expectedError: nil, - }, - } - for _, tc := range testCases { - actualKeyPair, actualError := generateServiceAccountKeys(tc.inputKeyPair, tc.inputUser) - if tc.expectedError != nil { - if tc.expectedError.Error() != actualError.Error() { - t.Fatalf("[%s], Unexpected error, Want [%v], Got: [%v]", tc.name, tc.expectedError, actualError) - } - continue - } - if !tc.expectKeyPairGen { - if len(tc.inputKeyPair.Cert) != len(actualKeyPair.Cert) || string(tc.inputKeyPair.Cert) != string(actualKeyPair.Cert) { - t.Fatalf("[%s] Want cert=%q, Got cert=%q", tc.name, string(tc.inputKeyPair.Cert), string(actualKeyPair.Cert)) - } - if len(tc.inputKeyPair.Key) != len(actualKeyPair.Key) || string(tc.inputKeyPair.Key) != string(actualKeyPair.Key) { - t.Fatalf("[%s] Want key=%q, Got key=%q", tc.name, string(tc.inputKeyPair.Key), string(actualKeyPair.Key)) - } - } else { - _, decodeErr := DecodePrivateKeyPEM(actualKeyPair.Key) - if decodeErr != nil { - t.Fatalf("[%s], Expected to decode generated private key, Got decode failure failed %v", tc.name, decodeErr) - } - - // TODO: find a stronger check - if len(actualKeyPair.Key) <= 0 { - t.Fatalf("[%s], Expected to public key of length > 0, Got public key of length %d", tc.name, len(actualKeyPair.Key)) - } - } - } -} - -func TestNewCertificateAuthority(t *testing.T) { - testCases := []struct { - name string - testFunc func() error - }{ - { - name: "should generate conformant ca certificate", - testFunc: func() error { - cert, _, err := NewCertificateAuthority() - if err != nil { - return err - } - - if !cert.MaxPathLenZero { - return errors.Errorf("Unexpected value for MaxPathLenZero, Want: [true]; Got: [%t]", cert.MaxPathLenZero) - } - - if cert.MaxPathLen != 0 { - return errors.Errorf("Unexpected value for MaxPathLen, Want: [0]; Got: [%d]", cert.MaxPathLen) - } - - if !cert.BasicConstraintsValid { - return errors.Errorf("Unexpected value for BasicConstraintsValid, Want: [true]; Got: [%t]", cert.BasicConstraintsValid) - } - - expectedUsage := x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign - actualUsage := cert.KeyUsage - if expectedUsage != actualUsage { - return errors.Errorf("Unexpected value for KeyUsage, Want: [%d]; Got: [%d]", expectedUsage, actualUsage) - } - - expectedCommonName := "kubernetes" - actualCommonName := cert.Subject.CommonName - if expectedCommonName != actualCommonName { - return errors.Errorf("Unexpected CommonName, Want: [%s]; Got: [%s]", expectedCommonName, actualCommonName) - } - - if !cert.IsCA { - return errors.Errorf("Unexpected value for IsCA, Want: [true]; Got: [%t]", cert.IsCA) - } - - return nil - }, - }, - } - - for _, tc := range testCases { - if err := tc.testFunc(); err != nil { - t.Fatalf("[%s] failed: %v", tc.name, err) - } - } -} diff --git a/pkg/cloud/services/ec2/ami_test.go b/pkg/cloud/services/ec2/ami_test.go index 11f5dfe61f..a9626aed25 100644 --- a/pkg/cloud/services/ec2/ami_test.go +++ b/pkg/cloud/services/ec2/ami_test.go @@ -19,6 +19,8 @@ package ec2 import ( "testing" + "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" + "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/service/ec2" "github.com/golang/mock/gomock" @@ -64,7 +66,8 @@ func TestAMIs(t *testing.T) { ec2Mock := mock_ec2iface.NewMockEC2API(mockCtrl) scope, err := scope.NewClusterScope(scope.ClusterScopeParams{ - Cluster: &clusterv1.Cluster{}, + Cluster: &clusterv1.Cluster{}, + AWSCluster: &v1alpha2.AWSCluster{}, AWSClients: scope.AWSClients{ EC2: ec2Mock, }, diff --git a/pkg/cloud/services/ec2/bastion.go b/pkg/cloud/services/ec2/bastion.go index 4e9e28b1fd..1ad0c028fd 100644 --- a/pkg/cloud/services/ec2/bastion.go +++ b/pkg/cloud/services/ec2/bastion.go @@ -69,7 +69,7 @@ func (s *Service) ReconcileBastion() error { // TODO(vincepri): check for possible changes between the default spec and the instance. - instance.DeepCopyInto(&s.scope.ClusterStatus.Bastion) + instance.DeepCopyInto(&s.scope.AWSCluster.Status.Bastion) s.scope.V(2).Info("Reconcile bastion completed successfully") return nil } @@ -129,14 +129,14 @@ func (s *Service) getDefaultBastion() *v1alpha2.Instance { userData, _ := userdata.NewBastion(&userdata.BastionInput{}) keyName := defaultSSHKeyName - if s.scope.ClusterConfig.SSHKeyName != "" { - keyName = s.scope.ClusterConfig.SSHKeyName + if s.scope.AWSCluster.Spec.SSHKeyName != "" { + keyName = s.scope.AWSCluster.Spec.SSHKeyName } i := &v1alpha2.Instance{ Type: "t2.micro", SubnetID: s.scope.Subnets().FilterPublic()[0].ID, - ImageID: s.defaultBastionAMILookup(s.scope.ClusterConfig.Region), + ImageID: s.defaultBastionAMILookup(s.scope.AWSCluster.Spec.Region), KeyName: aws.String(keyName), UserData: aws.String(base64.StdEncoding.EncodeToString([]byte(userData))), SecurityGroupIDs: []string{ diff --git a/pkg/cloud/services/ec2/gateways_test.go b/pkg/cloud/services/ec2/gateways_test.go index 87a4e39d03..e912e08b10 100644 --- a/pkg/cloud/services/ec2/gateways_test.go +++ b/pkg/cloud/services/ec2/gateways_test.go @@ -114,12 +114,13 @@ func TestReconcileInternetGateways(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: *tc.input, + }, + }, }) - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: *tc.input, - } - if err != nil { t.Fatalf("Failed to create test context: %v", err) } diff --git a/pkg/cloud/services/ec2/instances.go b/pkg/cloud/services/ec2/instances.go index c067cfcef2..e3a6c89a64 100644 --- a/pkg/cloud/services/ec2/instances.go +++ b/pkg/cloud/services/ec2/instances.go @@ -103,9 +103,9 @@ func (s *Service) CreateInstance(scope *scope.MachineScope) (*v1alpha2.Instance, s.scope.V(2).Info("Creating an instance for a machine") input := &v1alpha2.Instance{ - Type: scope.ProviderMachine.Spec.InstanceType, - IAMProfile: scope.ProviderMachine.Spec.IAMInstanceProfile, - RootDeviceSize: scope.ProviderMachine.Spec.RootDeviceSize, + Type: scope.AWSMachine.Spec.InstanceType, + IAMProfile: scope.AWSMachine.Spec.IAMInstanceProfile, + RootDeviceSize: scope.AWSMachine.Spec.RootDeviceSize, } input.Tags = v1alpha2.Build(v1alpha2.BuildParams{ @@ -120,10 +120,10 @@ func (s *Service) CreateInstance(scope *scope.MachineScope) (*v1alpha2.Instance, var err error // Pick image from the machine configuration, or use a default one. - if scope.ProviderMachine.Spec.AMI.ID != nil { - input.ImageID = *scope.ProviderMachine.Spec.AMI.ID + if scope.AWSMachine.Spec.AMI.ID != nil { + input.ImageID = *scope.AWSMachine.Spec.AMI.ID } else { - input.ImageID, err = s.defaultAMILookup(scope.ProviderMachine.Spec.ImageLookupOrg, "ubuntu", "18.04", *scope.Machine.Spec.Version) + input.ImageID, err = s.defaultAMILookup(scope.AWSMachine.Spec.ImageLookupOrg, "ubuntu", "18.04", *scope.Machine.Spec.Version) if err != nil { return nil, err } @@ -132,15 +132,15 @@ func (s *Service) CreateInstance(scope *scope.MachineScope) (*v1alpha2.Instance, // Pick subnet from the machine configuration, or based on the availability zone specified, // or default to the first private subnet available. // TODO(vincepri): Move subnet picking logic to its own function/method. - if scope.ProviderMachine.Spec.Subnet != nil && scope.ProviderMachine.Spec.Subnet.ID != nil { - input.SubnetID = *scope.ProviderMachine.Spec.Subnet.ID - } else if scope.ProviderMachine.Spec.AvailabilityZone != nil { - sns := s.scope.Subnets().FilterPrivate().FilterByZone(*scope.ProviderMachine.Spec.AvailabilityZone) + if scope.AWSMachine.Spec.Subnet != nil && scope.AWSMachine.Spec.Subnet.ID != nil { + input.SubnetID = *scope.AWSMachine.Spec.Subnet.ID + } else if scope.AWSMachine.Spec.AvailabilityZone != nil { + sns := s.scope.Subnets().FilterPrivate().FilterByZone(*scope.AWSMachine.Spec.AvailabilityZone) if len(sns) == 0 { return nil, awserrors.NewFailedDependency( errors.Errorf("failed to run machine %q, no subnets available in availaibility zone %q", scope.Name(), - *scope.ProviderMachine.Spec.AvailabilityZone, + *scope.AWSMachine.Spec.AvailabilityZone, ), ) } @@ -155,12 +155,6 @@ func (s *Service) CreateInstance(scope *scope.MachineScope) (*v1alpha2.Instance, input.SubnetID = sns[0].ID } - if !s.scope.ClusterConfig.CAKeyPair.HasCertAndKey() { - return nil, awserrors.NewFailedDependency( - errors.New("failed to run controlplane, missing CACertificate"), - ) - } - if s.scope.Network().APIServerELB.DNSName == "" { return nil, awserrors.NewFailedDependency( errors.New("failed to run controlplane, APIServer ELB not available"), @@ -178,8 +172,8 @@ func (s *Service) CreateInstance(scope *scope.MachineScope) (*v1alpha2.Instance, input.SecurityGroupIDs = append(input.SecurityGroupIDs, ids...) // Pick SSH key, if any. - if scope.ProviderMachine.Spec.KeyName != "" { - input.KeyName = aws.String(scope.ProviderMachine.Spec.KeyName) + if scope.AWSMachine.Spec.KeyName != "" { + input.KeyName = aws.String(scope.AWSMachine.Spec.KeyName) } else { input.KeyName = aws.String(defaultSSHKeyName) } diff --git a/pkg/cloud/services/ec2/instances_test.go b/pkg/cloud/services/ec2/instances_test.go index c62187773c..1e15526d9f 100644 --- a/pkg/cloud/services/ec2/instances_test.go +++ b/pkg/cloud/services/ec2/instances_test.go @@ -134,16 +134,16 @@ func TestInstanceIfExists(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, - }) - - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: v1alpha2.NetworkSpec{ - VPC: v1alpha2.VPCSpec{ - ID: "test-vpc", + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: v1alpha2.NetworkSpec{ + VPC: v1alpha2.VPCSpec{ + ID: "test-vpc", + }, + }, }, }, - } - + }) if err != nil { t.Fatalf("Failed to create test context: %v", err) } @@ -207,11 +207,12 @@ func TestTerminateInstance(t *testing.T) { elbMock := mock_elbiface.NewMockELBAPI(mockCtrl) scope, err := scope.NewClusterScope(scope.ClusterScopeParams{ - Cluster: &clusterv1.Cluster{}, AWSClients: scope.AWSClients{ EC2: ec2Mock, ELB: elbMock, }, + Cluster: &clusterv1.Cluster{}, + AWSCluster: &v1alpha2.AWSCluster{}, }) if err != nil { @@ -228,38 +229,11 @@ func TestTerminateInstance(t *testing.T) { } func TestCreateInstance(t *testing.T) { - testCaCert := []byte(` ------BEGIN CERTIFICATE----- -MIID6jCCAtICCQCa6H6nD76FxzANBgkqhkiG9w0BAQsFADCBtjELMAkGA1UEBhMC -VVMxCzAJBgNVBAgMAldBMRMwEQYDVQQHDAprdWJlcm5ldGVzMRQwEgYDVQQKDAtj -bHVzdGVyLWFwaTEhMB8GA1UECwwYY2x1c3Rlci1hcGktcHJvdmlkZXItYXdzMTAw -LgYDVQQDDCdzaWdzLms4cy5pby5jbHVzdGVyLWFwaS1wcm92aWRlci1hd3MuYWYx -GjAYBgkqhkiG9w0BCQEWC2Zvb0BiYXIuY29tMB4XDTE5MDExMTA5MTgxNVoXDTIx -MTAwNzA5MTgxNVowgbYxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJXQTETMBEGA1UE -BwwKa3ViZXJuZXRlczEUMBIGA1UECgwLY2x1c3Rlci1hcGkxITAfBgNVBAsMGGNs -dXN0ZXItYXBpLXByb3ZpZGVyLWF3czEwMC4GA1UEAwwnc2lncy5rOHMuaW8uY2x1 -c3Rlci1hcGktcHJvdmlkZXItYXdzLmFmMRowGAYJKoZIhvcNAQkBFgtmb29AYmFy -LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKHVoYcq6NiS2lch -ai62dDU+wStXJzFkF3URQ7auYDmL3Xz+01yxdARdafO3fweXSsfuxcGZ/DDBzRBB -ROXeJI1zxV6xk+OlI0puOabo6m5ji4RdTTFqt94afnK43qcDMDOnh0u6F5UZXZlr -T7XNnO++6e7elZ+9jJJ/NKPXDGKo9+M7kmypTLcI5b5pH4qn1coe8a5Li+FQONEM -j+Ttomqr0s84DyFBSNZYKvRVL1AdH/6r213pco5Qm9RDkw9HZr83Y1PjyQ77C7FQ -IPquny5XkjZjq65Bz8I8s+MoPQgBOr8JvVfc3Jt8u10qD4JOeRFnhZOygaApgswg -9XZhdMsCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAVfucXOzEy88NQ+fz5FV1D1PO -No6uqi2Q9fqGU9Lfnj3PhXr0sb0tAXGnZEg8i1317xMXqzA9J9umqg3ADsOsR3sL -NR41dkjP2ROfTW1wkEGBaRzp/TOagMy1IeeS9MPd4gRH3cZqgUvrQJCrX8878gxk -jor3R8gPhjvV74KrZD4lIF7IHHv4cCBaejm+3GwOIbTNoHXa4PadVwbcjWp6P8UB -dTga1FiyISsMchVaVKD5aX7hkxMP1/C98KdVzWQ4k12TBOhZDYUS67M4ibBtw/og -vuO9LYxDXLVY9F7W4ccyCqe27Cj1xyAvdZxwhITrib8Wg5CMqoRpqTw5V3+TpA== ------END CERTIFICATE----- - `) - testcases := []struct { name string machine clusterv1.Machine machineConfig *v1alpha2.AWSMachineSpec - clusterStatus *v1alpha2.AWSClusterProviderStatus - clusterConfig *v1alpha2.AWSClusterProviderSpec + awsCluster *v1alpha2.AWSCluster expect func(m *mock_ec2iface.MockEC2APIMockRecorder) check func(instance *v1alpha2.Instance, err error) }{ @@ -281,40 +255,38 @@ vuO9LYxDXLVY9F7W4ccyCqe27Cj1xyAvdZxwhITrib8Wg5CMqoRpqTw5V3+TpA== }, InstanceType: "m5.large", }, - clusterStatus: &v1alpha2.AWSClusterProviderStatus{ - Network: v1alpha2.Network{ - SecurityGroups: map[v1alpha2.SecurityGroupRole]v1alpha2.SecurityGroup{ - v1alpha2.SecurityGroupControlPlane: { - ID: "1", - }, - v1alpha2.SecurityGroupNode: { - ID: "2", - }, - v1alpha2.SecurityGroupLB: { - ID: "3", + awsCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: v1alpha2.NetworkSpec{ + Subnets: v1alpha2.Subnets{ + &v1alpha2.SubnetSpec{ + ID: "subnet-1", + IsPublic: false, + }, + &v1alpha2.SubnetSpec{ + IsPublic: false, + }, }, }, - APIServerELB: v1alpha2.ClassicELB{ - DNSName: "test-apiserver.us-east-1.aws", - }, }, - }, - clusterConfig: &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: v1alpha2.NetworkSpec{ - Subnets: v1alpha2.Subnets{ - &v1alpha2.SubnetSpec{ - ID: "subnet-1", - IsPublic: false, + Status: v1alpha2.AWSClusterStatus{ + Network: v1alpha2.Network{ + SecurityGroups: map[v1alpha2.SecurityGroupRole]v1alpha2.SecurityGroup{ + v1alpha2.SecurityGroupControlPlane: { + ID: "1", + }, + v1alpha2.SecurityGroupNode: { + ID: "2", + }, + v1alpha2.SecurityGroupLB: { + ID: "3", + }, }, - &v1alpha2.SubnetSpec{ - IsPublic: false, + APIServerELB: v1alpha2.ClassicELB{ + DNSName: "test-apiserver.us-east-1.aws", }, }, }, - CAKeyPair: &v1alpha2.KeyPair{ - Cert: testCaCert, - Key: []byte("y"), - }, }, expect: func(m *mock_ec2iface.MockEC2APIMockRecorder) { m. @@ -372,53 +344,51 @@ vuO9LYxDXLVY9F7W4ccyCqe27Cj1xyAvdZxwhITrib8Wg5CMqoRpqTw5V3+TpA== InstanceType: "m5.2xlarge", AvailabilityZone: aws.String("us-east-1c"), }, - clusterStatus: &v1alpha2.AWSClusterProviderStatus{ - Network: v1alpha2.Network{ - SecurityGroups: map[v1alpha2.SecurityGroupRole]v1alpha2.SecurityGroup{ - v1alpha2.SecurityGroupControlPlane: { - ID: "1", - }, - v1alpha2.SecurityGroupNode: { - ID: "2", - }, - v1alpha2.SecurityGroupLB: { - ID: "3", + awsCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: v1alpha2.NetworkSpec{ + Subnets: v1alpha2.Subnets{ + &v1alpha2.SubnetSpec{ + ID: "subnet-1", + AvailabilityZone: "us-east-1a", + IsPublic: false, + }, + &v1alpha2.SubnetSpec{ + ID: "subnet-2", + AvailabilityZone: "us-east-1b", + IsPublic: false, + }, + &v1alpha2.SubnetSpec{ + ID: "subnet-3", + AvailabilityZone: "us-east-1c", + IsPublic: false, + }, + &v1alpha2.SubnetSpec{ + ID: "subnet-3-public", + AvailabilityZone: "us-east-1c", + IsPublic: true, + }, }, }, - APIServerELB: v1alpha2.ClassicELB{ - DNSName: "test-apiserver.us-east-1.aws", - }, }, - }, - clusterConfig: &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: v1alpha2.NetworkSpec{ - Subnets: v1alpha2.Subnets{ - &v1alpha2.SubnetSpec{ - ID: "subnet-1", - AvailabilityZone: "us-east-1a", - IsPublic: false, - }, - &v1alpha2.SubnetSpec{ - ID: "subnet-2", - AvailabilityZone: "us-east-1b", - IsPublic: false, - }, - &v1alpha2.SubnetSpec{ - ID: "subnet-3", - AvailabilityZone: "us-east-1c", - IsPublic: false, + Status: v1alpha2.AWSClusterStatus{ + Network: v1alpha2.Network{ + SecurityGroups: map[v1alpha2.SecurityGroupRole]v1alpha2.SecurityGroup{ + v1alpha2.SecurityGroupControlPlane: { + ID: "1", + }, + v1alpha2.SecurityGroupNode: { + ID: "2", + }, + v1alpha2.SecurityGroupLB: { + ID: "3", + }, }, - &v1alpha2.SubnetSpec{ - ID: "subnet-3-public", - AvailabilityZone: "us-east-1c", - IsPublic: true, + APIServerELB: v1alpha2.ClassicELB{ + DNSName: "test-apiserver.us-east-1.aws", }, }, }, - CAKeyPair: &v1alpha2.KeyPair{ - Cert: testCaCert, - Key: []byte("y"), - }, }, expect: func(m *mock_ec2iface.MockEC2APIMockRecorder) { m. @@ -504,7 +474,7 @@ vuO9LYxDXLVY9F7W4ccyCqe27Cj1xyAvdZxwhITrib8Wg5CMqoRpqTw5V3+TpA== }, } - awsmachine := &v1alpha2.AWSMachine{ + awsMachine := &v1alpha2.AWSMachine{ ObjectMeta: metav1.ObjectMeta{ OwnerReferences: []metav1.OwnerReference{ { @@ -516,26 +486,34 @@ vuO9LYxDXLVY9F7W4ccyCqe27Cj1xyAvdZxwhITrib8Wg5CMqoRpqTw5V3+TpA== }, } - scope, err := scope.NewMachineScope(scope.MachineScopeParams{ - ProviderMachine: awsmachine, + machineScope, err := scope.NewMachineScope(scope.MachineScopeParams{ + Client: fake.NewFakeClient(cluster, machine), AWSClients: scope.AWSClients{ EC2: ec2Mock, ELB: elbMock, }, - Client: fake.NewFakeClient(cluster, machine), + Cluster: cluster, + Machine: machine, + AWSMachine: awsMachine, }) - if err != nil { t.Fatalf("Failed to create test context: %v", err) } - - scope.Parent.ClusterConfig = tc.clusterConfig - scope.Parent.ClusterStatus = tc.clusterStatus - scope.ProviderMachine.Spec = *tc.machineConfig + machineScope.AWSMachine.Spec = *tc.machineConfig tc.expect(ec2Mock.EXPECT()) - s := NewService(scope.Parent) - instance, err := s.CreateInstance(scope) + clusterScope, err := scope.NewClusterScope(scope.ClusterScopeParams{ + Client: fake.NewFakeClient(cluster, machine), + AWSClients: scope.AWSClients{ + EC2: ec2Mock, + ELB: elbMock, + }, + Cluster: cluster, + AWSCluster: tc.awsCluster, + }) + + s := NewService(clusterScope) + instance, err := s.CreateInstance(machineScope) tc.check(instance, err) }) } diff --git a/pkg/cloud/services/ec2/natgateways_test.go b/pkg/cloud/services/ec2/natgateways_test.go index ef071609fa..33ce35177c 100644 --- a/pkg/cloud/services/ec2/natgateways_test.go +++ b/pkg/cloud/services/ec2/natgateways_test.go @@ -288,7 +288,7 @@ func TestReconcileNatGateways(t *testing.T) { ec2Mock := mock_ec2iface.NewMockEC2API(mockCtrl) elbMock := mock_elbiface.NewMockELBAPI(mockCtrl) - scope, err := scope.NewClusterScope(scope.ClusterScopeParams{ + clusterScope, err := scope.NewClusterScope(scope.ClusterScopeParams{ Cluster: &clusterv1.Cluster{ ObjectMeta: metav1.ObjectMeta{Name: "test-cluster"}, }, @@ -296,27 +296,27 @@ func TestReconcileNatGateways(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, - }) - - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: v1alpha2.NetworkSpec{ - VPC: v1alpha2.VPCSpec{ - ID: subnetsVPCID, - Tags: v1alpha2.Tags{ - v1alpha2.ClusterTagKey("test-cluster"): "owned", + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: v1alpha2.NetworkSpec{ + VPC: v1alpha2.VPCSpec{ + ID: subnetsVPCID, + Tags: v1alpha2.Tags{ + v1alpha2.ClusterTagKey("test-cluster"): "owned", + }, + }, + Subnets: tc.input, }, }, - Subnets: tc.input, }, - } - + }) if err != nil { t.Fatalf("Failed to create test context: %v", err) } tc.expect(ec2Mock.EXPECT()) - s := NewService(scope) + s := NewService(clusterScope) if err := s.reconcileNatGateways(); err != nil { t.Fatalf("got an unexpected error: %v", err) } diff --git a/pkg/cloud/services/ec2/routetables_test.go b/pkg/cloud/services/ec2/routetables_test.go index 281c8b4d7a..2b72207d6f 100644 --- a/pkg/cloud/services/ec2/routetables_test.go +++ b/pkg/cloud/services/ec2/routetables_test.go @@ -156,16 +156,17 @@ func TestReconcileRouteTables(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: *tc.input, + }, + }, }) if err != nil { t.Fatalf("Failed to create test context: %v", err) } - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: *tc.input, - } - tc.expect(ec2Mock.EXPECT()) s := NewService(scope) diff --git a/pkg/cloud/services/ec2/securitygroups_test.go b/pkg/cloud/services/ec2/securitygroups_test.go index 76e1375e36..1a396705c4 100644 --- a/pkg/cloud/services/ec2/securitygroups_test.go +++ b/pkg/cloud/services/ec2/securitygroups_test.go @@ -148,16 +148,17 @@ func TestReconcileSecurityGroups(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: *tc.input, + }, + }, }) if err != nil { t.Fatalf("Failed to create test context: %v", err) } - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: *tc.input, - } - tc.expect(ec2Mock.EXPECT()) s := NewService(scope) diff --git a/pkg/cloud/services/ec2/subnets.go b/pkg/cloud/services/ec2/subnets.go index d9298dc9d0..380f535a04 100644 --- a/pkg/cloud/services/ec2/subnets.go +++ b/pkg/cloud/services/ec2/subnets.go @@ -40,7 +40,7 @@ func (s *Service) reconcileSubnets() error { subnets := s.scope.Subnets() defer func() { - s.scope.ClusterConfig.NetworkSpec.Subnets = subnets + s.scope.AWSCluster.Spec.NetworkSpec.Subnets = subnets }() // Describe subnets in the vpc. diff --git a/pkg/cloud/services/ec2/subnets_test.go b/pkg/cloud/services/ec2/subnets_test.go index 4d3621c59c..0bd555ce20 100644 --- a/pkg/cloud/services/ec2/subnets_test.go +++ b/pkg/cloud/services/ec2/subnets_test.go @@ -503,12 +503,12 @@ func TestReconcileSubnets(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: *tc.input, + }, + }, }) - - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: *tc.input, - } - if err != nil { t.Fatalf("Failed to create test context: %v", err) } @@ -673,12 +673,12 @@ func TestDiscoverSubnets(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: *tc.input, + }, + }, }) - - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: *tc.input, - } - if err != nil { t.Fatalf("Failed to create test context: %v", err) } @@ -690,7 +690,7 @@ func TestDiscoverSubnets(t *testing.T) { t.Fatalf("got an unexpected error: %v", err) } - subnets := s.scope.ClusterConfig.NetworkSpec.Subnets + subnets := s.scope.AWSCluster.Spec.NetworkSpec.Subnets out := make(map[string]*v1alpha2.SubnetSpec) for _, sn := range subnets { out[sn.ID] = sn diff --git a/pkg/cloud/services/ec2/vpc_test.go b/pkg/cloud/services/ec2/vpc_test.go index 37fa83e521..9896b0a4da 100644 --- a/pkg/cloud/services/ec2/vpc_test.go +++ b/pkg/cloud/services/ec2/vpc_test.go @@ -138,18 +138,18 @@ func TestReconcileVPC(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: v1alpha2.NetworkSpec{ + VPC: *tc.input, + }, + }, + }, }) - if err != nil { t.Fatalf("Failed to create test context: %v", err) } - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: v1alpha2.NetworkSpec{ - VPC: *tc.input, - }, - } - tc.expect(ec2Mock.EXPECT()) s := NewService(scope) diff --git a/pkg/cloud/services/elb/BUILD.bazel b/pkg/cloud/services/elb/BUILD.bazel index ce46d8096e..5c4647c658 100644 --- a/pkg/cloud/services/elb/BUILD.bazel +++ b/pkg/cloud/services/elb/BUILD.bazel @@ -24,10 +24,7 @@ go_library( go_test( name = "go_default_test", - srcs = [ - "loadbalancer_test.go", - "service_test.go", - ], + srcs = ["loadbalancer_test.go"], embed = [":go_default_library"], deps = [ "//pkg/apis/infrastructure/v1alpha2:go_default_library", diff --git a/pkg/cloud/services/elb/loadbalancer_test.go b/pkg/cloud/services/elb/loadbalancer_test.go index d7fba4658e..ae3866f4c5 100644 --- a/pkg/cloud/services/elb/loadbalancer_test.go +++ b/pkg/cloud/services/elb/loadbalancer_test.go @@ -77,15 +77,16 @@ func TestDeleteLoadBalancers(t *testing.T) { EC2: ec2Mock, ELB: elbMock, }, - }) - - scope.ClusterConfig = &v1alpha2.AWSClusterProviderSpec{ - NetworkSpec: v1alpha2.NetworkSpec{ - VPC: v1alpha2.VPCSpec{ - ID: "test-vpc", + AWSCluster: &v1alpha2.AWSCluster{ + Spec: v1alpha2.AWSClusterSpec{ + NetworkSpec: v1alpha2.NetworkSpec{ + VPC: v1alpha2.VPCSpec{ + ID: "test-vpc", + }, + }, }, }, - } + }) if err != nil { t.Fatalf("Failed to create test context: %v", err) } diff --git a/pkg/cloud/services/elb/service_test.go b/pkg/cloud/services/elb/service_test.go deleted file mode 100644 index ccf2bbfc70..0000000000 --- a/pkg/cloud/services/elb/service_test.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2018 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 elb - -import ( - "testing" - - "github.com/golang/mock/gomock" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2/mock_ec2iface" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb/mock_elbiface" - clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" - //nolint -) - -func TestNewService(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - ec2Mock := mock_ec2iface.NewMockEC2API(mockCtrl) - elbMock := mock_elbiface.NewMockELBAPI(mockCtrl) - - scope, err := scope.NewClusterScope(scope.ClusterScopeParams{ - Cluster: &clusterv1.Cluster{}, - AWSClients: scope.AWSClients{ - EC2: ec2Mock, - ELB: elbMock, - }, - }) - - if err != nil { - t.Fatalf("Failed to create test context: %v", err) - } - - s := NewService(scope) - if s == nil { - t.Fatalf("Service shouldn't be nil") - } -} diff --git a/pkg/cloud/services/interfaces.go b/pkg/cloud/services/interfaces.go index 622c180881..bf0b749bf8 100644 --- a/pkg/cloud/services/interfaces.go +++ b/pkg/cloud/services/interfaces.go @@ -17,48 +17,10 @@ limitations under the License. package services import ( - "github.com/aws/aws-sdk-go/aws/session" providerv1 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" ) -// Getter is a unified interfaces that includes all the getters. -type Getter interface { - SDKSessionGetter - EC2Getter - ELBGetter -} - -// SDKSessionGetter has a single method that returns an AWS session. -type SDKSessionGetter interface { - Session(*providerv1.AWSClusterProviderSpec) *session.Session -} - -// EC2Getter has a single method that returns an EC2 service interface. -type EC2Getter interface { - EC2(*session.Session) EC2Interface -} - -// ELBGetter has a single method that returns an ELB service interface. -type ELBGetter interface { - ELB(*session.Session) ELBInterface -} - -// EC2Interface encapsulates the methods exposed by the ec2 service. -type EC2Interface interface { - EC2ClusterInterface - EC2MachineInterface -} - -// EC2ClusterInterface encapsulates the methods exposed to the cluster -// actuator -type EC2ClusterInterface interface { - ReconcileNetwork() error - ReconcileBastion() error - DeleteNetwork() error - DeleteBastion() error -} - // EC2MachineInterface encapsulates the methods exposed to the machine // actuator type EC2MachineInterface interface { @@ -69,11 +31,3 @@ type EC2MachineInterface interface { UpdateInstanceSecurityGroups(id string, securityGroups []string) error UpdateResourceTags(resourceID *string, create map[string]string, remove map[string]string) error } - -// ELBInterface encapsulates the methods exposed by the elb service. -type ELBInterface interface { - ReconcileLoadbalancers() error - DeleteLoadbalancers() error - RegisterInstanceWithAPIServerELB(instanceID string) error - GetAPIServerDNSName() (string, error) -} diff --git a/pkg/cloud/services/mocks/BUILD.bazel b/pkg/cloud/services/mocks/BUILD.bazel deleted file mode 100644 index 252e2e5084..0000000000 --- a/pkg/cloud/services/mocks/BUILD.bazel +++ /dev/null @@ -1,31 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") -load("@bazel_gomock//:gomock.bzl", "gomock") - -go_library( - name = "go_default_library", - srcs = [ - "getters.go", - "services_mock.go", - ], - importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/mocks", - visibility = ["//visibility:public"], - deps = [ - "//pkg/apis/infrastructure/v1alpha2:go_default_library", - "//pkg/cloud/scope:go_default_library", - "//pkg/cloud/services:go_default_library", - "//vendor/github.com/aws/aws-sdk-go/aws/session:go_default_library", - "//vendor/github.com/golang/mock/gomock:go_default_library", - ], -) - -gomock( - name = "mocks", - out = "services_mock.go", - interfaces = [ - "EC2Interface", - "ELBInterface", - ], - library = "//pkg/cloud/services:go_default_library", - package = "mocks", - visibility = ["//visibility:public"], -) diff --git a/pkg/cloud/services/mocks/getters.go b/pkg/cloud/services/mocks/getters.go deleted file mode 100644 index 45cb635747..0000000000 --- a/pkg/cloud/services/mocks/getters.go +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright 2018 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 mocks - -import ( - "github.com/aws/aws-sdk-go/aws/session" - gomock "github.com/golang/mock/gomock" - v1alpha2 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services" -) - -// SDKGetter is a mocked getter. -type SDKGetter struct { - EC2Mock *MockEC2Interface - ELBMock *MockELBInterface -} - -// Session returns a nil session. -func (*SDKGetter) Session(clusterConfig *v1alpha2.AWSClusterProviderSpec) *session.Session { - return nil -} - -// EC2 returns a mocked EC2 service client. -func (t *SDKGetter) EC2(session *session.Session) services.EC2Interface { - return t.EC2Mock -} - -// ELB returns a mocked EC2 service client. -func (t *SDKGetter) ELB(session *session.Session) services.ELBInterface { - return t.ELBMock -} - -// NewSDKGetter returns a new SDKGetter. -func NewSDKGetter(ctrl *gomock.Controller) *SDKGetter { - return &SDKGetter{ - EC2Mock: NewMockEC2Interface(ctrl), - ELBMock: NewMockELBInterface(ctrl), - } -} diff --git a/pkg/cloud/services/mocks/services_mock.go b/pkg/cloud/services/mocks/services_mock.go deleted file mode 100644 index c801ca19a3..0000000000 --- a/pkg/cloud/services/mocks/services_mock.go +++ /dev/null @@ -1,274 +0,0 @@ -/* -Copyright The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Code generated by MockGen. DO NOT EDIT. -// Source: sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services (interfaces: EC2Interface,ELBInterface) - -// Package mocks is a generated GoMock package. -package mocks - -import ( - gomock "github.com/golang/mock/gomock" - reflect "reflect" - v1alpha2 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" - scope "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" -) - -// MockEC2Interface is a mock of EC2Interface interface -type MockEC2Interface struct { - ctrl *gomock.Controller - recorder *MockEC2InterfaceMockRecorder -} - -// MockEC2InterfaceMockRecorder is the mock recorder for MockEC2Interface -type MockEC2InterfaceMockRecorder struct { - mock *MockEC2Interface -} - -// NewMockEC2Interface creates a new mock instance -func NewMockEC2Interface(ctrl *gomock.Controller) *MockEC2Interface { - mock := &MockEC2Interface{ctrl: ctrl} - mock.recorder = &MockEC2InterfaceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockEC2Interface) EXPECT() *MockEC2InterfaceMockRecorder { - return m.recorder -} - -// DeleteBastion mocks base method -func (m *MockEC2Interface) DeleteBastion() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteBastion") - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteBastion indicates an expected call of DeleteBastion -func (mr *MockEC2InterfaceMockRecorder) DeleteBastion() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBastion", reflect.TypeOf((*MockEC2Interface)(nil).DeleteBastion)) -} - -// DeleteNetwork mocks base method -func (m *MockEC2Interface) DeleteNetwork() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteNetwork") - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteNetwork indicates an expected call of DeleteNetwork -func (mr *MockEC2InterfaceMockRecorder) DeleteNetwork() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteNetwork", reflect.TypeOf((*MockEC2Interface)(nil).DeleteNetwork)) -} - -// GetCoreSecurityGroups mocks base method -func (m *MockEC2Interface) GetCoreSecurityGroups(arg0 *scope.MachineScope) ([]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetCoreSecurityGroups", arg0) - ret0, _ := ret[0].([]string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetCoreSecurityGroups indicates an expected call of GetCoreSecurityGroups -func (mr *MockEC2InterfaceMockRecorder) GetCoreSecurityGroups(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetCoreSecurityGroups", reflect.TypeOf((*MockEC2Interface)(nil).GetCoreSecurityGroups), arg0) -} - -// GetInstanceSecurityGroups mocks base method -func (m *MockEC2Interface) GetInstanceSecurityGroups(arg0 string) (map[string][]string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetInstanceSecurityGroups", arg0) - ret0, _ := ret[0].(map[string][]string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetInstanceSecurityGroups indicates an expected call of GetInstanceSecurityGroups -func (mr *MockEC2InterfaceMockRecorder) GetInstanceSecurityGroups(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInstanceSecurityGroups", reflect.TypeOf((*MockEC2Interface)(nil).GetInstanceSecurityGroups), arg0) -} - -// InstanceIfExists mocks base method -func (m *MockEC2Interface) InstanceIfExists(arg0 *string) (*v1alpha2.Instance, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "InstanceIfExists", arg0) - ret0, _ := ret[0].(*v1alpha2.Instance) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// InstanceIfExists indicates an expected call of InstanceIfExists -func (mr *MockEC2InterfaceMockRecorder) InstanceIfExists(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "InstanceIfExists", reflect.TypeOf((*MockEC2Interface)(nil).InstanceIfExists), arg0) -} - -// ReconcileBastion mocks base method -func (m *MockEC2Interface) ReconcileBastion() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReconcileBastion") - ret0, _ := ret[0].(error) - return ret0 -} - -// ReconcileBastion indicates an expected call of ReconcileBastion -func (mr *MockEC2InterfaceMockRecorder) ReconcileBastion() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReconcileBastion", reflect.TypeOf((*MockEC2Interface)(nil).ReconcileBastion)) -} - -// ReconcileNetwork mocks base method -func (m *MockEC2Interface) ReconcileNetwork() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReconcileNetwork") - ret0, _ := ret[0].(error) - return ret0 -} - -// ReconcileNetwork indicates an expected call of ReconcileNetwork -func (mr *MockEC2InterfaceMockRecorder) ReconcileNetwork() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReconcileNetwork", reflect.TypeOf((*MockEC2Interface)(nil).ReconcileNetwork)) -} - -// TerminateInstance mocks base method -func (m *MockEC2Interface) TerminateInstance(arg0 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "TerminateInstance", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// TerminateInstance indicates an expected call of TerminateInstance -func (mr *MockEC2InterfaceMockRecorder) TerminateInstance(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TerminateInstance", reflect.TypeOf((*MockEC2Interface)(nil).TerminateInstance), arg0) -} - -// UpdateInstanceSecurityGroups mocks base method -func (m *MockEC2Interface) UpdateInstanceSecurityGroups(arg0 string, arg1 []string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateInstanceSecurityGroups", arg0, arg1) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateInstanceSecurityGroups indicates an expected call of UpdateInstanceSecurityGroups -func (mr *MockEC2InterfaceMockRecorder) UpdateInstanceSecurityGroups(arg0, arg1 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateInstanceSecurityGroups", reflect.TypeOf((*MockEC2Interface)(nil).UpdateInstanceSecurityGroups), arg0, arg1) -} - -// UpdateResourceTags mocks base method -func (m *MockEC2Interface) UpdateResourceTags(arg0 *string, arg1, arg2 map[string]string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "UpdateResourceTags", arg0, arg1, arg2) - ret0, _ := ret[0].(error) - return ret0 -} - -// UpdateResourceTags indicates an expected call of UpdateResourceTags -func (mr *MockEC2InterfaceMockRecorder) UpdateResourceTags(arg0, arg1, arg2 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateResourceTags", reflect.TypeOf((*MockEC2Interface)(nil).UpdateResourceTags), arg0, arg1, arg2) -} - -// MockELBInterface is a mock of ELBInterface interface -type MockELBInterface struct { - ctrl *gomock.Controller - recorder *MockELBInterfaceMockRecorder -} - -// MockELBInterfaceMockRecorder is the mock recorder for MockELBInterface -type MockELBInterfaceMockRecorder struct { - mock *MockELBInterface -} - -// NewMockELBInterface creates a new mock instance -func NewMockELBInterface(ctrl *gomock.Controller) *MockELBInterface { - mock := &MockELBInterface{ctrl: ctrl} - mock.recorder = &MockELBInterfaceMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use -func (m *MockELBInterface) EXPECT() *MockELBInterfaceMockRecorder { - return m.recorder -} - -// DeleteLoadbalancers mocks base method -func (m *MockELBInterface) DeleteLoadbalancers() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "DeleteLoadbalancers") - ret0, _ := ret[0].(error) - return ret0 -} - -// DeleteLoadbalancers indicates an expected call of DeleteLoadbalancers -func (mr *MockELBInterfaceMockRecorder) DeleteLoadbalancers() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteLoadbalancers", reflect.TypeOf((*MockELBInterface)(nil).DeleteLoadbalancers)) -} - -// GetAPIServerDNSName mocks base method -func (m *MockELBInterface) GetAPIServerDNSName() (string, error) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "GetAPIServerDNSName") - ret0, _ := ret[0].(string) - ret1, _ := ret[1].(error) - return ret0, ret1 -} - -// GetAPIServerDNSName indicates an expected call of GetAPIServerDNSName -func (mr *MockELBInterfaceMockRecorder) GetAPIServerDNSName() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetAPIServerDNSName", reflect.TypeOf((*MockELBInterface)(nil).GetAPIServerDNSName)) -} - -// ReconcileLoadbalancers mocks base method -func (m *MockELBInterface) ReconcileLoadbalancers() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "ReconcileLoadbalancers") - ret0, _ := ret[0].(error) - return ret0 -} - -// ReconcileLoadbalancers indicates an expected call of ReconcileLoadbalancers -func (mr *MockELBInterfaceMockRecorder) ReconcileLoadbalancers() *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ReconcileLoadbalancers", reflect.TypeOf((*MockELBInterface)(nil).ReconcileLoadbalancers)) -} - -// RegisterInstanceWithAPIServerELB mocks base method -func (m *MockELBInterface) RegisterInstanceWithAPIServerELB(arg0 string) error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RegisterInstanceWithAPIServerELB", arg0) - ret0, _ := ret[0].(error) - return ret0 -} - -// RegisterInstanceWithAPIServerELB indicates an expected call of RegisterInstanceWithAPIServerELB -func (mr *MockELBInterfaceMockRecorder) RegisterInstanceWithAPIServerELB(arg0 interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RegisterInstanceWithAPIServerELB", reflect.TypeOf((*MockELBInterface)(nil).RegisterInstanceWithAPIServerELB), arg0) -} diff --git a/pkg/controller/BUILD.bazel b/pkg/controller/BUILD.bazel index a6d341a8e1..6f623b844b 100644 --- a/pkg/controller/BUILD.bazel +++ b/pkg/controller/BUILD.bazel @@ -3,12 +3,14 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ + "add_awscluster.go", "add_awsmachine.go", "controller.go", ], importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/controller", visibility = ["//visibility:public"], deps = [ + "//pkg/controller/awscluster:go_default_library", "//pkg/controller/awsmachine:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/manager:go_default_library", ], diff --git a/pkg/cloud/services/certificates/service.go b/pkg/controller/add_awscluster.go similarity index 57% rename from pkg/cloud/services/certificates/service.go rename to pkg/controller/add_awscluster.go index 3d6635919e..eacdd03a92 100644 --- a/pkg/cloud/services/certificates/service.go +++ b/pkg/controller/add_awscluster.go @@ -14,21 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -package certificates +package controller import ( - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" + "sigs.k8s.io/cluster-api-provider-aws/pkg/controller/awscluster" ) -// Service groups certificate related operations together and allows -// certificate updates to be applied to the actuator scope. -type Service struct { - scope *scope.ClusterScope -} - -// NewService returns a new certificates service for the given actuators scope. -func NewService(scope *scope.ClusterScope) *Service { - return &Service{ - scope: scope, - } +func init() { + // AddToManagerFuncs is a list of functions to create controllers and add them to a manager. + AddToManagerFuncs = append(AddToManagerFuncs, awscluster.Add) } diff --git a/pkg/controller/awscluster/BUILD.bazel b/pkg/controller/awscluster/BUILD.bazel new file mode 100644 index 0000000000..8b6a35ee21 --- /dev/null +++ b/pkg/controller/awscluster/BUILD.bazel @@ -0,0 +1,50 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") + +go_library( + name = "go_default_library", + srcs = ["awscluster_controller.go"], + importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/controller/awscluster", + visibility = ["//visibility:public"], + deps = [ + "//pkg/apis/infrastructure/v1alpha2:go_default_library", + "//pkg/cloud/scope:go_default_library", + "//pkg/cloud/services/ec2:go_default_library", + "//pkg/cloud/services/elb:go_default_library", + "//vendor/github.com/pkg/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/util:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/controller:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/handler:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/log:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/manager:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/reconcile:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/source:go_default_library", + ], +) + +go_test( + name = "go_default_test", + srcs = [ + "awscluster_controller_suite_test.go", + "awscluster_controller_test.go", + ], + embed = [":go_default_library"], + deps = [ + "//pkg/apis:go_default_library", + "//pkg/apis/infrastructure/v1alpha2:go_default_library", + "//vendor/github.com/onsi/gomega:go_default_library", + "//vendor/golang.org/x/net/context:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", + "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/apis:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/envtest:go_default_library", + "//vendor/sigs.k8s.io/controller-runtime/pkg/manager:go_default_library", + ], +) diff --git a/pkg/controller/awscluster/awscluster_controller.go b/pkg/controller/awscluster/awscluster_controller.go new file mode 100644 index 0000000000..7441d18a48 --- /dev/null +++ b/pkg/controller/awscluster/awscluster_controller.go @@ -0,0 +1,234 @@ +/* +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 awscluster + +import ( + "context" + "fmt" + "time" + + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb" + + "sigs.k8s.io/cluster-api/pkg/util" + + "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/record" + infrastructurev1alpha2 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" + "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" + "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +const ( + controllerName = "awscluster-controller" + apiEndpointPort = 6443 +) + +// Add creates a new AWSCluster Controller and adds it to the Manager with default RBAC. The Manager will set fields on the Controller +// and Start it when the Manager is Started. +func Add(mgr manager.Manager) error { + return add(mgr, newReconciler(mgr)) +} + +// newReconciler returns a new reconcile.Reconciler +func newReconciler(mgr manager.Manager) reconcile.Reconciler { + return &ReconcileAWSCluster{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + recorder: mgr.GetEventRecorderFor(controllerName), + } +} + +// add adds a new Controller to mgr with r as the reconcile.Reconciler +func add(mgr manager.Manager, r reconcile.Reconciler) error { + // Create a new controller + c, err := controller.New(controllerName, mgr, controller.Options{Reconciler: r}) + if err != nil { + return err + } + + // Watch for changes to AWSCluster + err = c.Watch( + &source.Kind{Type: &infrastructurev1alpha2.AWSCluster{}}, + &handler.EnqueueRequestForObject{}, + ) + if err != nil { + return err + } + + // Watch for changes to Cluster and enqueue the associated AWSCluster + return c.Watch( + &source.Kind{Type: &v1alpha2.Cluster{}}, + &handler.EnqueueRequestsFromMapFunc{ + ToRequests: util.ClusterToInfrastructureMapFunc(schema.GroupVersionKind{ + Group: infrastructurev1alpha2.SchemeGroupVersion.Group, + Version: infrastructurev1alpha2.SchemeGroupVersion.Version, + Kind: "AWSCluster", + }), + }, + ) +} + +var _ reconcile.Reconciler = &ReconcileAWSCluster{} + +// ReconcileAWSCluster reconciles a AWSCluster object +type ReconcileAWSCluster struct { + client.Client + scheme *runtime.Scheme + recorder record.EventRecorder +} + +// Reconcile reads that state of the cluster for a AWSCluster object and makes changes based on the state read +// and what is in the AWSCluster.Spec +func (r *ReconcileAWSCluster) Reconcile(request reconcile.Request) (_ reconcile.Result, reterr error) { + ctx := context.TODO() + logger := log.Log.WithName(controllerName). + WithName(fmt.Sprintf("namespace=%s", request.Namespace)). + WithName(fmt.Sprintf("awsCluster=%s", request.Name)) + + // Fetch the AWSCluster instance + awsCluster := &infrastructurev1alpha2.AWSCluster{} + err := r.Get(ctx, request.NamespacedName, awsCluster) + if err != nil { + if apierrors.IsNotFound(err) { + return reconcile.Result{}, nil + } + return reconcile.Result{}, err + } + + logger = logger.WithName(awsCluster.APIVersion) + + // Fetch the Cluster. + cluster, err := util.GetOwnerCluster(ctx, r.Client, awsCluster.ObjectMeta) + if err != nil { + return reconcile.Result{}, err + } + if cluster == nil { + logger.Info("Waiting for Cluster Controller to set OwnerRef on AWSCluster") + return reconcile.Result{RequeueAfter: 10 * time.Second}, nil + } + + logger = logger.WithName(fmt.Sprintf("cluster=%s", cluster.Name)) + + // Create the scope. + clusterScope, err := scope.NewClusterScope(scope.ClusterScopeParams{ + Client: r.Client, + Logger: logger, + Cluster: cluster, + AWSCluster: awsCluster, + }) + if err != nil { + return reconcile.Result{}, errors.Errorf("failed to create scope: %+v", err) + } + + // Always close the scope when exiting this function so we can persist any AWSMachine changes. + defer func() { + if err := clusterScope.Close(); err != nil && reterr == nil { + reterr = err + } + }() + + // Handle deleted clusters + if !awsCluster.DeletionTimestamp.IsZero() { + return reconcileDelete(clusterScope) + } + + // Handle non-deleted clusters + return reconcileNormal(clusterScope) +} + +// TODO(ncdc): should this be a function on ClusterScope? +func reconcileDelete(clusterScope *scope.ClusterScope) (reconcile.Result, error) { + clusterScope.Info("Reconciling AWSCluster delete") + + ec2svc := ec2.NewService(clusterScope) + elbsvc := elb.NewService(clusterScope) + awsCluster := clusterScope.AWSCluster + + if err := elbsvc.DeleteLoadbalancers(); err != nil { + return reconcile.Result{}, errors.Wrapf(err, "error deleting load balancer for AWSCluster %s/%s", awsCluster.Namespace, awsCluster.Name) + } + + if err := ec2svc.DeleteBastion(); err != nil { + return reconcile.Result{}, errors.Wrapf(err, "error deleting bastion for AWSCluster %s/%s", awsCluster.Namespace, awsCluster.Name) + } + + if err := ec2svc.DeleteNetwork(); err != nil { + return reconcile.Result{}, errors.Wrapf(err, "error deleting network for AWSCluster %s/%s", awsCluster.Namespace, awsCluster.Name) + } + + // Cluster is deleted so remove the finalizer. + clusterScope.AWSCluster.Finalizers = util.Filter(clusterScope.AWSCluster.Finalizers, infrastructurev1alpha2.ClusterFinalizer) + + return reconcile.Result{}, nil +} + +// TODO(ncdc): should this be a function on ClusterScope? +func reconcileNormal(clusterScope *scope.ClusterScope) (reconcile.Result, error) { + clusterScope.Info("Reconciling AWSCluster") + + awsCluster := clusterScope.AWSCluster + + // If the AWSCluster doesn't have our finalizer, add it. + if !util.Contains(awsCluster.Finalizers, infrastructurev1alpha2.ClusterFinalizer) { + awsCluster.Finalizers = append(awsCluster.Finalizers, infrastructurev1alpha2.ClusterFinalizer) + } + + ec2Service := ec2.NewService(clusterScope) + elbService := elb.NewService(clusterScope) + + if err := ec2Service.ReconcileNetwork(); err != nil { + return reconcile.Result{}, errors.Wrapf(err, "failed to reconcile network for AWSCluster %s/%s", awsCluster.Namespace, awsCluster.Name) + } + + if err := ec2Service.ReconcileBastion(); err != nil { + return reconcile.Result{}, errors.Wrapf(err, "failed to reconcile bastion host for AWSCluster %s/%s", awsCluster.Namespace, awsCluster.Name) + } + + if err := elbService.ReconcileLoadbalancers(); err != nil { + return reconcile.Result{}, errors.Wrapf(err, "failed to reconcile load balancers for AWSCluster %s/%s", awsCluster.Namespace, awsCluster.Name) + } + + if awsCluster.Status.Network.APIServerELB.DNSName == "" { + clusterScope.Info("Waiting on API server ELB DNS name") + return reconcile.Result{RequeueAfter: 15 * time.Second}, nil + } + + // Set APIEndpoints so the Cluster API Cluster Controller can pull them + awsCluster.Status.APIEndpoints = []infrastructurev1alpha2.APIEndpoint{ + { + Host: awsCluster.Status.Network.APIServerELB.DNSName, + // TODO(ncdc): should this come from awsCluster.Status.Network.APIServerELB.Listeners[0].Port? + Port: apiEndpointPort, + }, + } + + // No errors, so mark us ready so the Cluster API Cluster Controller can pull it + awsCluster.Status.Ready = true + + return reconcile.Result{}, nil +} diff --git a/pkg/controller/awscluster/awscluster_controller_suite_test.go b/pkg/controller/awscluster/awscluster_controller_suite_test.go new file mode 100644 index 0000000000..62b4616b7d --- /dev/null +++ b/pkg/controller/awscluster/awscluster_controller_suite_test.go @@ -0,0 +1,67 @@ +/* +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 awscluster + +import ( + stdlog "log" + "os" + "path/filepath" + "sync" + "testing" + + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/cluster-api-provider-aws/pkg/apis" + capi "sigs.k8s.io/cluster-api/pkg/apis" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +var cfg *rest.Config + +func TestMain(m *testing.M) { + t := &envtest.Environment{ + CRDDirectoryPaths: []string{ + filepath.Join("..", "..", "..", "vendor", "sigs.k8s.io", "cluster-api", "config", "crds"), + filepath.Join("..", "..", "..", "config", "crds"), + }, + } + capi.AddToScheme(scheme.Scheme) + apis.AddToScheme(scheme.Scheme) + + var err error + if cfg, err = t.Start(); err != nil { + stdlog.Fatal(err) + } + + code := m.Run() + t.Stop() + os.Exit(code) +} + +// StartTestManager adds recFn +func StartTestManager(mgr manager.Manager) (chan struct{}, *sync.WaitGroup) { + stop := make(chan struct{}) + wg := &sync.WaitGroup{} + wg.Add(1) + go func() { + defer wg.Done() + Expect(mgr.Start(stop)).NotTo(HaveOccurred()) + }() + return stop, wg +} diff --git a/pkg/controller/awscluster/awscluster_controller_test.go b/pkg/controller/awscluster/awscluster_controller_test.go new file mode 100644 index 0000000000..74e23bc3da --- /dev/null +++ b/pkg/controller/awscluster/awscluster_controller_test.go @@ -0,0 +1,65 @@ +/* +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 awscluster + +import ( + "testing" + "time" + + . "github.com/onsi/gomega" + "golang.org/x/net/context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + infrastructurev1alpha2 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +const timeout = time.Second * 5 + +func TestReconcile(t *testing.T) { + RegisterTestingT(t) + ctx := context.Background() + instance := &infrastructurev1alpha2.AWSCluster{ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}} + + // Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a + // channel when it is finished. + mgr, err := manager.New(cfg, manager.Options{}) + Expect(err).NotTo(HaveOccurred()) + c := mgr.GetClient() + Expect(add(mgr, newReconciler(mgr))).To(Succeed()) + + stopMgr, mgrStopped := StartTestManager(mgr) + + defer func() { + close(stopMgr) + mgrStopped.Wait() + }() + + // Create the AWSCluster object and expect the Reconcile and Deployment to be created + err = c.Create(ctx, instance) + Expect(err).NotTo(HaveOccurred()) + defer c.Delete(context.TODO(), instance) + + Eventually(func() bool { + key := client.ObjectKey{Name: instance.Name, Namespace: instance.Namespace} + if err := c.Get(ctx, key, instance); err != nil { + return false + } + return true + }, timeout).Should(BeTrue()) + +} diff --git a/pkg/controller/awsmachine/BUILD.bazel b/pkg/controller/awsmachine/BUILD.bazel index 17dd2c278d..c737bec9e1 100644 --- a/pkg/controller/awsmachine/BUILD.bazel +++ b/pkg/controller/awsmachine/BUILD.bazel @@ -22,10 +22,10 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/noderefutil:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", diff --git a/pkg/controller/awsmachine/awsmachine_controller.go b/pkg/controller/awsmachine/awsmachine_controller.go index 570c938fa6..439d521064 100644 --- a/pkg/controller/awsmachine/awsmachine_controller.go +++ b/pkg/controller/awsmachine/awsmachine_controller.go @@ -21,6 +21,8 @@ import ( "fmt" "time" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/log" "github.com/aws/aws-sdk-go/aws" @@ -36,7 +38,6 @@ import ( "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2" "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/controller/noderefutil" capierrors "sigs.k8s.io/cluster-api/pkg/errors" @@ -110,8 +111,11 @@ type ReconcileAWSMachine struct { // Reconcile reads that state of the cluster for a AWSMachine object and makes changes based on the state read // and what is in the AWSMachine.Spec func (r *ReconcileAWSMachine) Reconcile(request reconcile.Request) (_ reconcile.Result, reterr error) { - ctx := context.Background() - log := log.Log.WithName(controllerName) + ctx := context.TODO() + logger := log.Log. + WithName(controllerName). + WithName(fmt.Sprintf("namespace=%s", request.Namespace)). + WithName(fmt.Sprintf("awsMachine=%s", request.Name)) // Fetch the AWSMachine instance. awsMachine := &infrav1.AWSMachine{} @@ -123,116 +127,161 @@ func (r *ReconcileAWSMachine) Reconcile(request reconcile.Request) (_ reconcile. return reconcile.Result{}, err } - // Create the scope. - scope, err := scope.NewMachineScope(scope.MachineScopeParams{ - Logger: log, - ProviderMachine: awsMachine, - Client: r.Client, + logger = logger.WithName(awsMachine.APIVersion) + + // Fetch the Machine. + machine, err := util.GetOwnerMachine(ctx, r.Client, awsMachine.ObjectMeta) + if err != nil { + return reconcile.Result{}, err + } + if machine == nil { + logger.Info("Waiting for Machine Controller to set OwnerRef on AWSMachine") + return reconcile.Result{RequeueAfter: 10 * time.Second}, nil + } + + logger = logger.WithName(fmt.Sprintf("machine=%s", machine.Name)) + + // Fetch the Cluster. + cluster, err := util.GetClusterFromMetadata(ctx, r.Client, machine.ObjectMeta) + if err != nil { + logger.Info("Machine is missing cluster label or cluster does not exist") + return reconcile.Result{}, nil + } + + logger = logger.WithName(fmt.Sprintf("cluster=%s", cluster.Name)) + + awsCluster := &infrav1.AWSCluster{} + awsClusterName := types.NamespacedName{ + Namespace: awsMachine.Namespace, + Name: cluster.Spec.InfrastructureRef.Name, + } + if err := r.Client.Get(ctx, awsClusterName, awsCluster); err != nil { + logger.Info("Waiting for AWSCluster") + return reconcile.Result{RequeueAfter: 10 * time.Second}, nil + } + + logger = logger.WithName(fmt.Sprintf("awsCluster=%s", awsCluster.Name)) + + // Create the cluster scope + clusterScope, err := scope.NewClusterScope(scope.ClusterScopeParams{ + Client: r.Client, + Logger: logger, + Cluster: cluster, + AWSCluster: awsCluster, + }) + if err != nil { + return reconcile.Result{}, err + } + + // Create the machine scope + machineScope, err := scope.NewMachineScope(scope.MachineScopeParams{ + Logger: logger, + Client: r.Client, + Cluster: cluster, + Machine: machine, + AWSMachine: awsMachine, }) if err != nil { - if requeueErr, ok := errors.Cause(err).(capierrors.HasRequeueAfterError); ok { - return reconcile.Result{RequeueAfter: requeueErr.GetRequeueAfter()}, nil - } return reconcile.Result{}, errors.Errorf("failed to create scope: %+v", err) } // Always close the scope when exiting this function so we can persist any AWSMachine changes. defer func() { - if err := scope.Close(); err != nil && reterr == nil { + if err := machineScope.Close(); err != nil && reterr == nil { reterr = err } }() // Handle deleted machines if !awsMachine.ObjectMeta.DeletionTimestamp.IsZero() { - return r.reconcileDelete(scope, awsMachine) + return r.reconcileDelete(machineScope, clusterScope) } // Handle non-deleted machines - return r.reconcileNormal(ctx, scope, awsMachine) + return r.reconcileNormal(ctx, machineScope, clusterScope) } -func (r *ReconcileAWSMachine) reconcileNormal(ctx context.Context, scope *scope.MachineScope, awsMachine *infrav1.AWSMachine) (reconcile.Result, error) { +func (r *ReconcileAWSMachine) reconcileNormal(ctx context.Context, machineScope *scope.MachineScope, clusterScope *scope.ClusterScope) (reconcile.Result, error) { // If the AWSMachine is in an error state, return early. - if scope.ProviderMachine.Status.ErrorReason != nil || scope.ProviderMachine.Status.ErrorMessage != nil { - scope.Info("Error state detected, skipping reconciliation") + if machineScope.AWSMachine.Status.ErrorReason != nil || machineScope.AWSMachine.Status.ErrorMessage != nil { + machineScope.Info("Error state detected, skipping reconciliation") return reconcile.Result{}, nil } // If the AWSMachine doesn't have our finalizer, add it. - if !util.Contains(awsMachine.Finalizers, infrav1.MachineFinalizer) { - awsMachine.Finalizers = append(awsMachine.ObjectMeta.Finalizers, infrav1.MachineFinalizer) + if !util.Contains(machineScope.AWSMachine.Finalizers, infrav1.MachineFinalizer) { + machineScope.AWSMachine.Finalizers = append(machineScope.AWSMachine.Finalizers, infrav1.MachineFinalizer) } - if scope.Parent.Cluster.Annotations[infrav1.AnnotationClusterInfrastructureReady] != infrav1.ValueReady { - scope.Info("Cluster infrastructure is not ready yet, requeuing machine") + if !machineScope.Cluster.Status.InfrastructureReady { + machineScope.Info("Cluster infrastructure is not ready yet, requeuing machine") return reconcile.Result{RequeueAfter: waitForClusterInfrastructureReadyDuration}, nil } // Make sure bootstrap data is available and populated. - if scope.Machine.Spec.Bootstrap.Data == nil { - scope.Info("Waiting for bootstrap data to be available") + if machineScope.Machine.Spec.Bootstrap.Data == nil { + machineScope.Info("Waiting for bootstrap data to be available") return reconcile.Result{RequeueAfter: 10 * time.Second}, nil } - ec2svc := ec2.NewService(scope.Parent) + ec2svc := ec2.NewService(clusterScope) // Get or create the instance. - instance, err := r.getOrCreate(scope, ec2svc) + instance, err := r.getOrCreate(machineScope, ec2svc) if err != nil { return reconcile.Result{}, err } // Set an error message if we couldn't find the instance. if instance == nil { - scope.SetErrorReason(common.UpdateMachineError) - scope.SetErrorMessage(errors.New("EC2 instance cannot be found")) + machineScope.SetErrorReason(capierrors.UpdateMachineError) + machineScope.SetErrorMessage(errors.New("EC2 instance cannot be found")) return reconcile.Result{}, nil } // TODO(ncdc): move this validation logic into a validating webhook - if errs := r.validateUpdate(&awsMachine.Spec, instance); len(errs) > 0 { + if errs := r.validateUpdate(&machineScope.AWSMachine.Spec, instance); len(errs) > 0 { agg := kerrors.NewAggregate(errs) - r.recorder.Eventf(awsMachine, corev1.EventTypeWarning, "InvalidUpdate", "Invalid update: %s", agg.Error()) + r.recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "InvalidUpdate", "Invalid update: %s", agg.Error()) return reconcile.Result{}, nil } // Make sure Spec.ProviderID is always set. - scope.SetProviderID(fmt.Sprintf("aws:////%s", instance.ID)) + machineScope.SetProviderID(fmt.Sprintf("aws:////%s", instance.ID)) // Proceed to reconcile the AWSMachine state. - scope.SetInstanceState(instance.State) + machineScope.SetInstanceState(instance.State) // TODO(vincepri): Remove this annotation when clusterctl is no longer relevant. - scope.SetAnnotation("cluster-api-provider-aws", "true") + machineScope.SetAnnotation("cluster-api-provider-aws", "true") switch instance.State { case infrav1.InstanceStateRunning: - scope.Info("Machine instance is running", "instance-id", *scope.GetInstanceID()) + machineScope.Info("Machine instance is running", "instance-id", *machineScope.GetInstanceID()) case infrav1.InstanceStatePending: - scope.Info("Machine instance is pending", "instance-id", *scope.GetInstanceID()) + machineScope.Info("Machine instance is pending", "instance-id", *machineScope.GetInstanceID()) default: - scope.SetErrorReason(common.UpdateMachineError) - scope.SetErrorMessage(errors.Errorf("EC2 instance state %q is unexpected", instance.State)) + machineScope.SetErrorReason(capierrors.UpdateMachineError) + machineScope.SetErrorMessage(errors.Errorf("EC2 instance state %q is unexpected", instance.State)) } - if err := r.reconcileLBAttachment(scope, instance); err != nil { + if err := r.reconcileLBAttachment(machineScope, clusterScope, instance); err != nil { return reconcile.Result{}, errors.Errorf("failed to reconcile LB attachment: %+v", err) } - existingSecurityGroups, err := ec2svc.GetInstanceSecurityGroups(*scope.GetInstanceID()) + existingSecurityGroups, err := ec2svc.GetInstanceSecurityGroups(*machineScope.GetInstanceID()) if err != nil { return reconcile.Result{}, err } // Ensure that the security groups are correct. - _, err = r.ensureSecurityGroups(ec2svc, scope, scope.ProviderMachine.Spec.AdditionalSecurityGroups, existingSecurityGroups) + _, err = r.ensureSecurityGroups(ec2svc, machineScope, machineScope.AWSMachine.Spec.AdditionalSecurityGroups, existingSecurityGroups) if err != nil { return reconcile.Result{}, errors.Errorf("failed to apply security groups: %+v", err) } // Ensure that the tags are correct. - _, err = r.ensureTags(ec2svc, scope.ProviderMachine, scope.GetInstanceID(), scope.ProviderMachine.Spec.AdditionalTags) + _, err = r.ensureTags(ec2svc, machineScope.AWSMachine, machineScope.GetInstanceID(), machineScope.AWSMachine.Spec.AdditionalTags) if err != nil { return reconcile.Result{}, errors.Errorf("failed to ensure tags: %+v", err) } @@ -240,19 +289,19 @@ func (r *ReconcileAWSMachine) reconcileNormal(ctx context.Context, scope *scope. return reconcile.Result{}, nil } -func (r *ReconcileAWSMachine) reconcileDelete(scope *scope.MachineScope, awsMachine *infrav1.AWSMachine) (reconcile.Result, error) { - scope.Info("Handling deleted AWSMachine") +func (r *ReconcileAWSMachine) reconcileDelete(machineScope *scope.MachineScope, clusterScope *scope.ClusterScope) (reconcile.Result, error) { + machineScope.Info("Handling deleted AWSMachine") - ec2Service := ec2.NewService(scope.Parent) + ec2Service := ec2.NewService(clusterScope) - instance, err := r.findInstance(scope, ec2Service) + instance, err := r.findInstance(machineScope, ec2Service) if err != nil { return reconcile.Result{}, err } if instance == nil { // The machine was never created or was deleted by some other entity - scope.V(3).Info("Unable to locate instance by ID or tags") + machineScope.V(3).Info("Unable to locate instance by ID or tags") return reconcile.Result{}, nil } @@ -262,19 +311,19 @@ func (r *ReconcileAWSMachine) reconcileDelete(scope *scope.MachineScope, awsMach // https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html switch instance.State { case infrav1.InstanceStateShuttingDown, infrav1.InstanceStateTerminated: - scope.Info("Instance is shutting down or already terminated") + machineScope.Info("Instance is shutting down or already terminated") return reconcile.Result{}, nil default: - scope.Info("Terminating instance") + machineScope.Info("Terminating instance") if err := ec2Service.TerminateInstanceAndWait(instance.ID); err != nil { - r.recorder.Eventf(awsMachine, corev1.EventTypeWarning, "FailedTerminate", "Failed to terminate instance %q: %v", instance.ID, err) + r.recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeWarning, "FailedTerminate", "Failed to terminate instance %q: %v", instance.ID, err) return reconcile.Result{}, errors.Errorf("failed to terminate instance: %+v", err) } - r.recorder.Eventf(awsMachine, corev1.EventTypeNormal, "SuccessfulTerminate", "Terminated instance %q", instance.ID) + r.recorder.Eventf(machineScope.AWSMachine, corev1.EventTypeNormal, "SuccessfulTerminate", "Terminated instance %q", instance.ID) } // Instance is deleted so remove the finalizer. - awsMachine.Finalizers = util.Filter(awsMachine.Finalizers, infrav1.MachineFinalizer) + machineScope.AWSMachine.Finalizers = util.Filter(machineScope.AWSMachine.Finalizers, infrav1.MachineFinalizer) return reconcile.Result{}, nil } @@ -322,12 +371,12 @@ func (r *ReconcileAWSMachine) getOrCreate(scope *scope.MachineScope, ec2svc *ec2 return instance, nil } -func (r *ReconcileAWSMachine) reconcileLBAttachment(scope *scope.MachineScope, i *infrav1.Instance) error { - if !scope.IsControlPlane() { +func (r *ReconcileAWSMachine) reconcileLBAttachment(machineScope *scope.MachineScope, clusterScope *scope.ClusterScope, i *infrav1.Instance) error { + if !machineScope.IsControlPlane() { return nil } - elbsvc := elb.NewService(scope.Parent) + elbsvc := elb.NewService(clusterScope) if err := elbsvc.RegisterInstanceWithAPIServerELB(i.ID); err != nil { return errors.Wrapf(err, "could not register control plane instance %q with load balancer", i.ID) } diff --git a/pkg/controller/awsmachine/security_groups.go b/pkg/controller/awsmachine/security_groups.go index f057da59e7..18343c920b 100644 --- a/pkg/controller/awsmachine/security_groups.go +++ b/pkg/controller/awsmachine/security_groups.go @@ -39,7 +39,7 @@ const ( // Bool indicates if changes were made or not, allowing the caller to decide // if the machine should be updated. func (r *ReconcileAWSMachine) ensureSecurityGroups(ec2svc service.EC2MachineInterface, scope *scope.MachineScope, additional []infrav1.AWSResourceReference, existing map[string][]string) (bool, error) { - annotation, err := r.machineAnnotationJSON(scope.ProviderMachine, SecurityGroupsLastAppliedAnnotation) + annotation, err := r.machineAnnotationJSON(scope.AWSMachine, SecurityGroupsLastAppliedAnnotation) if err != nil { return false, err } @@ -63,7 +63,7 @@ func (r *ReconcileAWSMachine) ensureSecurityGroups(ec2svc service.EC2MachineInte newAnnotation[*id.ID] = struct{}{} } - if err := r.updateMachineAnnotationJSON(scope.ProviderMachine, SecurityGroupsLastAppliedAnnotation, newAnnotation); err != nil { + if err := r.updateMachineAnnotationJSON(scope.AWSMachine, SecurityGroupsLastAppliedAnnotation, newAnnotation); err != nil { return false, err } diff --git a/pkg/deployer/BUILD.bazel b/pkg/deployer/BUILD.bazel deleted file mode 100644 index 78daadacf4..0000000000 --- a/pkg/deployer/BUILD.bazel +++ /dev/null @@ -1,35 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") - -go_library( - name = "go_default_library", - srcs = ["deployer.go"], - importpath = "sigs.k8s.io/cluster-api-provider-aws/pkg/deployer", - visibility = ["//visibility:public"], - deps = [ - "//pkg/apis/infrastructure/v1alpha2:go_default_library", - "//pkg/cloud/scope:go_default_library", - "//pkg/cloud/services/certificates:go_default_library", - "//pkg/cloud/services/elb:go_default_library", - "//vendor/github.com/pkg/errors:go_default_library", - "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", - ], -) - -go_test( - name = "go_default_test", - srcs = ["deployer_test.go"], - embed = [":go_default_library"], - deps = [ - "//pkg/apis/infrastructure/v1alpha2:go_default_library", - "//pkg/cloud/scope:go_default_library", - "//pkg/cloud/services/ec2/mock_ec2iface:go_default_library", - "//pkg/cloud/services/elb/mock_elbiface:go_default_library", - "//pkg/cloudtest:go_default_library", - "//vendor/github.com/aws/aws-sdk-go/aws:go_default_library", - "//vendor/github.com/aws/aws-sdk-go/service/elb:go_default_library", - "//vendor/github.com/golang/mock/gomock:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", - ], -) diff --git a/pkg/deployer/deployer.go b/pkg/deployer/deployer.go deleted file mode 100644 index 94549be7cc..0000000000 --- a/pkg/deployer/deployer.go +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright 2018 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 deployer - -import ( - "fmt" - - "github.com/pkg/errors" - "k8s.io/client-go/tools/clientcmd" - providerv1 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/certificates" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb" - clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" -) - -// Deployer satisfies the ProviderDeployer(https://github.com/kubernetes-sigs/cluster-api/blob/master/cmd/clusterctl/clusterdeployer/clusterdeployer.go) interface. -type Deployer struct { - scopeGetter scope.ClusterScopeGetter -} - -// Params is used to create a new deployer. -type Params struct { - ClusterScopeGetter scope.ClusterScopeGetter -} - -// New returns a new Deployer. -func New(params Params) *Deployer { - return &Deployer{ - scopeGetter: params.ClusterScopeGetter, - } -} - -// GetIP returns the IP of a machine, but this is going away. -func (d *Deployer) GetIP(cluster *clusterv1.Cluster, _ *clusterv1.Machine) (string, error) { - scope, err := d.scopeGetter.ClusterScope(scope.ClusterScopeParams{Cluster: cluster}) - if err != nil { - return "", err - } - - if scope.ClusterStatus != nil && scope.ClusterStatus.Network.APIServerELB.DNSName != "" { - return scope.ClusterStatus.Network.APIServerELB.DNSName, nil - } - - elbsvc := elb.NewService(scope) - return elbsvc.GetAPIServerDNSName() -} - -// GetKubeConfig returns the kubeconfig after the bootstrap process is complete. -func (d *Deployer) GetKubeConfig(cluster *clusterv1.Cluster, _ *clusterv1.Machine) (string, error) { - - // Load provider config. - config, err := providerv1.ClusterConfigFromProviderSpec(cluster.Spec.ProviderSpec) - if err != nil { - return "", errors.Errorf("failed to load cluster provider spec: %v", err) - } - - cert, err := certificates.DecodeCertPEM(config.CAKeyPair.Cert) - if err != nil { - return "", errors.Wrap(err, "failed to decode CA Cert") - } else if cert == nil { - return "", errors.New("certificate not found in config") - } - - key, err := certificates.DecodePrivateKeyPEM(config.CAKeyPair.Key) - if err != nil { - return "", errors.Wrap(err, "failed to decode private key") - } else if key == nil { - return "", errors.New("CA private key not found") - } - - dnsName, err := d.GetIP(cluster, nil) - if err != nil { - return "", errors.Wrap(err, "failed to get DNS address") - } - - server := fmt.Sprintf("https://%s:6443", dnsName) - - cfg, err := certificates.NewKubeconfig(cluster.Name, server, cert, key) - if err != nil { - return "", errors.Wrap(err, "failed to generate a kubeconfig") - } - - yaml, err := clientcmd.Write(*cfg) - if err != nil { - return "", errors.Wrap(err, "failed to serialize config to yaml") - } - - return string(yaml), nil -} diff --git a/pkg/deployer/deployer_test.go b/pkg/deployer/deployer_test.go deleted file mode 100644 index 3311b42b96..0000000000 --- a/pkg/deployer/deployer_test.go +++ /dev/null @@ -1,166 +0,0 @@ -/* -Copyright 2018 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 deployer_test - -import ( - "testing" - - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/service/elb" - "github.com/golang/mock/gomock" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - providerv1 "sigs.k8s.io/cluster-api-provider-aws/pkg/apis/infrastructure/v1alpha2" // nolint - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/scope" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/ec2/mock_ec2iface" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloud/services/elb/mock_elbiface" - "sigs.k8s.io/cluster-api-provider-aws/pkg/cloudtest" - "sigs.k8s.io/cluster-api-provider-aws/pkg/deployer" - clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" -) - -type scopeGetter struct { - scope.AWSClients -} - -func (s *scopeGetter) ClusterScope(params scope.ClusterScopeParams) (*scope.ClusterScope, error) { - params.AWSClients = s.AWSClients - return scope.NewClusterScope(params) -} - -func TestGetIP(t *testing.T) { - testcases := []struct { - name string - cluster *clusterv1.Cluster - expectedIP string - elbExpects func(*mock_elbiface.MockELBAPIMockRecorder) - }{ - { - name: "sunny day test", - cluster: &clusterv1.Cluster{ - ObjectMeta: metav1.ObjectMeta{Name: "test", ClusterName: "test", Namespace: "default"}, - Spec: clusterv1.ClusterSpec{ - ProviderSpec: clusterv1.ProviderSpec{ - Value: cloudtest.RuntimeRawExtension(t, &providerv1.AWSClusterProviderSpec{}), - }, - }, - Status: clusterv1.ClusterStatus{ - ProviderStatus: cloudtest.RuntimeRawExtension(t, &providerv1.AWSClusterProviderStatus{}), - }, - }, - expectedIP: "something", - elbExpects: func(m *mock_elbiface.MockELBAPIMockRecorder) { - m.DescribeLoadBalancers(&elb.DescribeLoadBalancersInput{ - LoadBalancerNames: []*string{aws.String("test-apiserver")}, - }).Return(&elb.DescribeLoadBalancersOutput{ - LoadBalancerDescriptions: []*elb.LoadBalancerDescription{ - { - Scheme: aws.String("internet-facing"), - DNSName: aws.String("something"), - VPCId: aws.String("test-vpc"), - }, - }, - }, nil) - - m.DescribeLoadBalancerAttributes(gomock.Any()). - Return(&elb.DescribeLoadBalancerAttributesOutput{ - LoadBalancerAttributes: &elb.LoadBalancerAttributes{}, - }, nil) - }, - }, - { - name: "lookup IP if the status is empty", - cluster: &clusterv1.Cluster{ - ObjectMeta: metav1.ObjectMeta{Name: "test", ClusterName: "test", Namespace: "default"}, - Spec: clusterv1.ClusterSpec{ - ProviderSpec: clusterv1.ProviderSpec{ - Value: cloudtest.RuntimeRawExtension(t, &providerv1.AWSClusterProviderSpec{}), - }, - }, - }, - expectedIP: "dunno", - elbExpects: func(m *mock_elbiface.MockELBAPIMockRecorder) { - m.DescribeLoadBalancers(&elb.DescribeLoadBalancersInput{ - LoadBalancerNames: []*string{aws.String("test-apiserver")}, - }).Return(&elb.DescribeLoadBalancersOutput{ - LoadBalancerDescriptions: []*elb.LoadBalancerDescription{ - { - Scheme: aws.String("internet-facing"), - DNSName: aws.String("dunno"), - VPCId: aws.String("test-vpc"), - }, - }, - }, nil) - - m.DescribeLoadBalancerAttributes(gomock.Any()). - Return(&elb.DescribeLoadBalancerAttributesOutput{ - LoadBalancerAttributes: &elb.LoadBalancerAttributes{}, - }, nil) - }, - }, - { - name: "return the IP if it is stored in the status", - cluster: &clusterv1.Cluster{ - ObjectMeta: metav1.ObjectMeta{Name: "test", ClusterName: "test", Namespace: "default"}, - Spec: clusterv1.ClusterSpec{ - ProviderSpec: clusterv1.ProviderSpec{ - Value: cloudtest.RuntimeRawExtension(t, &providerv1.AWSClusterProviderSpec{}), - }, - }, - Status: clusterv1.ClusterStatus{ - ProviderStatus: cloudtest.RuntimeRawExtension(t, &providerv1.AWSClusterProviderStatus{ - Network: providerv1.Network{ - APIServerELB: providerv1.ClassicELB{ - DNSName: "banana", - }, - }, - }), - }, - }, - expectedIP: "banana", - }, - } - - for _, tc := range testcases { - t.Run(tc.name, func(t *testing.T) { - mockCtrl := gomock.NewController(t) - defer mockCtrl.Finish() - - ec2Mock := mock_ec2iface.NewMockEC2API(mockCtrl) - elbMock := mock_elbiface.NewMockELBAPI(mockCtrl) - - deployer := deployer.New(deployer.Params{ClusterScopeGetter: &scopeGetter{ - scope.AWSClients{ - EC2: ec2Mock, - ELB: elbMock, - }, - }}) - - if tc.elbExpects != nil { - tc.elbExpects(elbMock.EXPECT()) - } - - ip, err := deployer.GetIP(tc.cluster, nil) - if err != nil { - t.Fatalf("failed to get API server address: %v", err) - } - - if ip != tc.expectedIP { - t.Fatalf("got the wrong IP. Found %v, wanted %v", ip, tc.expectedIP) - } - }) - } -} diff --git a/scripts/ci-bazel-integration.sh b/scripts/ci-bazel-integration.sh index c83ed7e031..fc0c877e31 100755 --- a/scripts/ci-bazel-integration.sh +++ b/scripts/ci-bazel-integration.sh @@ -21,7 +21,7 @@ REPO_ROOT=$(dirname "${BASH_SOURCE[0]}")/.. source "${REPO_ROOT}/hack/ensure-go.sh" cd "${REPO_ROOT}" || exit 1 -bazel test --define='gotags=integration' --test_output all //test/integration/... +bazel test --define='gotags=integration' --test_output all --host_force_python=PY2 //test/integration/... bazel_status="${?}" python hack/coalesce.py exit "${bazel_status}" diff --git a/vendor/gomodules.xyz/jsonpatch/v2/.gitignore b/vendor/gomodules.xyz/jsonpatch/v2/.gitignore new file mode 100644 index 0000000000..5f90593a04 --- /dev/null +++ b/vendor/gomodules.xyz/jsonpatch/v2/.gitignore @@ -0,0 +1,27 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof + +/.idea +/vendor diff --git a/vendor/gomodules.xyz/jsonpatch/v2/.travis.yml b/vendor/gomodules.xyz/jsonpatch/v2/.travis.yml new file mode 100644 index 0000000000..9e4597bca6 --- /dev/null +++ b/vendor/gomodules.xyz/jsonpatch/v2/.travis.yml @@ -0,0 +1,17 @@ +language: go +go: + - 1.x + - tip + +go_import_path: gomodules.xyz/jsonpatch + +cache: + directories: + - $HOME/.cache/go-build + - $GOPATH/pkg/mod + +env: + - GO111MODULE=on + +script: + - go test -v diff --git a/vendor/gomodules.xyz/jsonpatch/v2/CHANGELOG.md b/vendor/gomodules.xyz/jsonpatch/v2/CHANGELOG.md new file mode 100644 index 0000000000..579351906c --- /dev/null +++ b/vendor/gomodules.xyz/jsonpatch/v2/CHANGELOG.md @@ -0,0 +1,37 @@ +# Change Log + +## [v2.0.0](https://github.com/gomodules/jsonpatch/tree/v2.0.0) (2019-06-25) +[Full Changelog](https://github.com/gomodules/jsonpatch/compare/1.0.0...v2.0.0) + +**Merged pull requests:** + +- Update go.mod and remove vendor folder [\#18](https://github.com/gomodules/jsonpatch/pull/18) ([tamalsaha](https://github.com/tamalsaha)) +- Change package path to gomodules.xyz/jsonpath [\#17](https://github.com/gomodules/jsonpatch/pull/17) ([tamalsaha](https://github.com/tamalsaha)) +- \[Emergency\] correct array index in backtrace [\#16](https://github.com/gomodules/jsonpatch/pull/16) ([kdada](https://github.com/kdada)) +- Added support for arrays at the root [\#15](https://github.com/gomodules/jsonpatch/pull/15) ([e-nikolov](https://github.com/e-nikolov)) +- Fix the example code in readme [\#14](https://github.com/gomodules/jsonpatch/pull/14) ([pytimer](https://github.com/pytimer)) + +## [1.0.0](https://github.com/gomodules/jsonpatch/tree/1.0.0) (2019-01-08) +**Fixed bugs:** + +- Correctly generate patch for nested object [\#8](https://github.com/gomodules/jsonpatch/issues/8) + +**Closed issues:** + +- Do releases and in SemVer [\#12](https://github.com/gomodules/jsonpatch/issues/12) +- Generated patch incorrect for Array replacement [\#1](https://github.com/gomodules/jsonpatch/issues/1) + +**Merged pull requests:** + +- Add JsonPatchOperation as type alias for Operation [\#13](https://github.com/gomodules/jsonpatch/pull/13) ([tamalsaha](https://github.com/tamalsaha)) +- Migrate to go mod [\#10](https://github.com/gomodules/jsonpatch/pull/10) ([tamalsaha](https://github.com/tamalsaha)) +- Add test for nested object [\#9](https://github.com/gomodules/jsonpatch/pull/9) ([tamalsaha](https://github.com/tamalsaha)) +- Add test for edit distance computation [\#7](https://github.com/gomodules/jsonpatch/pull/7) ([tamalsaha](https://github.com/tamalsaha)) +- Append edit distance operations from end to start [\#6](https://github.com/gomodules/jsonpatch/pull/6) ([tamalsaha](https://github.com/tamalsaha)) +- Add travis file [\#4](https://github.com/gomodules/jsonpatch/pull/4) ([tamalsaha](https://github.com/tamalsaha)) +- Run go fmt [\#3](https://github.com/gomodules/jsonpatch/pull/3) ([tamalsaha](https://github.com/tamalsaha)) +- Fix array comparison [\#2](https://github.com/gomodules/jsonpatch/pull/2) ([tamalsaha](https://github.com/tamalsaha)) + + + +\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file diff --git a/vendor/gomodules.xyz/jsonpatch/v2/README.md b/vendor/gomodules.xyz/jsonpatch/v2/README.md new file mode 100644 index 0000000000..a51d95aa02 --- /dev/null +++ b/vendor/gomodules.xyz/jsonpatch/v2/README.md @@ -0,0 +1,52 @@ +# jsonpatch + +[![Build Status](https://travis-ci.org/gomodules/jsonpatch.svg?branch=master)](https://travis-ci.org/gomodules/jsonpatch) +[![Go Report Card](https://goreportcard.com/badge/gomodules.xyz/jsonpatch "Go Report Card")](https://goreportcard.com/report/gomodules.xyz/jsonpatch) +[![GoDoc](https://godoc.org/gomodules.xyz/jsonpatch?status.svg "GoDoc")](https://godoc.org/gomodules.xyz/jsonpatch) + +As per http://jsonpatch.com JSON Patch is specified in RFC 6902 from the IETF. + +JSON Patch allows you to generate JSON that describes changes you want to make to a document, so you don't have to send the whole doc. JSON Patch format is supported by HTTP PATCH method, allowing for standards based partial updates via REST APIs. + +```console +go get gomodules.xyz/jsonpatch/v2 +``` + +I tried some of the other "jsonpatch" go implementations, but none of them could diff two json documents and generate format like jsonpatch.com specifies. Here's an example of the patch format: + +```json +[ + { "op": "replace", "path": "/baz", "value": "boo" }, + { "op": "add", "path": "/hello", "value": ["world"] }, + { "op": "remove", "path": "/foo"} +] + +``` +The API is super simple + +## example + +```go +package main + +import ( + "fmt" + "gomodules.xyz/jsonpatch/v2" +) + +var simpleA = `{"a":100, "b":200, "c":"hello"}` +var simpleB = `{"a":100, "b":200, "c":"goodbye"}` + +func main() { + patch, e := jsonpatch.CreatePatch([]byte(simpleA), []byte(simpleB)) + if e != nil { + fmt.Printf("Error creating JSON patch:%v", e) + return + } + for _, operation := range patch { + fmt.Printf("%s\n", operation.Json()) + } +} +``` + +This code needs more tests, as it's a highly recursive, type-fiddly monster. It's not a lot of code, but it has to deal with a lot of complexity. diff --git a/vendor/modules.txt b/vendor/modules.txt index 266b2d1927..a7dfb065c8 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -299,21 +299,20 @@ k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/apimachinery/pkg/runtime k8s.io/apimachinery/pkg/runtime/schema k8s.io/apimachinery/pkg/util/json -k8s.io/apimachinery/pkg/api/errors k8s.io/apimachinery/pkg/runtime/serializer k8s.io/apimachinery/pkg/util/wait +k8s.io/apimachinery/pkg/api/errors +k8s.io/apimachinery/pkg/types +k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/api/resource k8s.io/apimachinery/pkg/conversion k8s.io/apimachinery/pkg/fields k8s.io/apimachinery/pkg/labels k8s.io/apimachinery/pkg/selection -k8s.io/apimachinery/pkg/types k8s.io/apimachinery/pkg/util/intstr k8s.io/apimachinery/pkg/util/runtime k8s.io/apimachinery/pkg/watch -k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/util/validation -k8s.io/apimachinery/pkg/util/net k8s.io/apimachinery/pkg/api/meta k8s.io/apimachinery/pkg/conversion/queryparams k8s.io/apimachinery/pkg/util/naming @@ -327,6 +326,7 @@ k8s.io/apimachinery/pkg/runtime/serializer/json k8s.io/apimachinery/pkg/runtime/serializer/protobuf k8s.io/apimachinery/pkg/runtime/serializer/recognizer k8s.io/apimachinery/pkg/runtime/serializer/versioning +k8s.io/apimachinery/pkg/util/net k8s.io/apimachinery/pkg/util/version k8s.io/apimachinery/pkg/util/clock k8s.io/apimachinery/pkg/util/strategicpatch @@ -342,23 +342,23 @@ k8s.io/apimachinery/pkg/util/diff k8s.io/apimachinery/pkg/apis/meta/internalversion # k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible k8s.io/client-go/tools/clientcmd -k8s.io/client-go/kubernetes/typed/core/v1 -k8s.io/client-go/tools/clientcmd/api k8s.io/client-go/tools/record +k8s.io/client-go/kubernetes/typed/core/v1 k8s.io/client-go/kubernetes k8s.io/client-go/rest k8s.io/client-go/tools/auth +k8s.io/client-go/tools/clientcmd/api k8s.io/client-go/tools/clientcmd/api/latest k8s.io/client-go/util/homedir k8s.io/client-go/discovery k8s.io/client-go/util/flowcontrol k8s.io/client-go/kubernetes/scheme -k8s.io/client-go/tools/reference k8s.io/client-go/tools/leaderelection k8s.io/client-go/tools/leaderelection/resourcelock k8s.io/client-go/dynamic -k8s.io/client-go/util/workqueue k8s.io/client-go/tools/record/util +k8s.io/client-go/tools/reference +k8s.io/client-go/util/workqueue k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1 k8s.io/client-go/kubernetes/typed/apps/v1 k8s.io/client-go/kubernetes/typed/apps/v1beta1 @@ -476,18 +476,15 @@ k8s.io/utils/exec k8s.io/utils/integer k8s.io/utils/buffer k8s.io/utils/trace -# sigs.k8s.io/cluster-api v0.0.0-20190723164546-bf8541c6acdf => sigs.k8s.io/cluster-api v0.0.0-20190723164546-bf8541c6acdf +# sigs.k8s.io/cluster-api v0.0.0-20190731140622-3be3a5776b37 => sigs.k8s.io/cluster-api v0.0.0-20190731140622-3be3a5776b37 sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset sigs.k8s.io/cluster-api/pkg/apis -sigs.k8s.io/cluster-api/pkg/controller/cluster sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1 -sigs.k8s.io/cluster-api/pkg/apis/cluster/common sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2 -sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha2 -sigs.k8s.io/cluster-api/pkg/controller/remote sigs.k8s.io/cluster-api/pkg/errors -sigs.k8s.io/cluster-api/pkg/util sigs.k8s.io/cluster-api/pkg/controller/noderefutil +sigs.k8s.io/cluster-api/pkg/util +sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha2 sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/deprecated/v1alpha1 sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/scheme # sigs.k8s.io/controller-runtime v0.2.0-beta.4 @@ -499,6 +496,7 @@ sigs.k8s.io/controller-runtime/pkg/runtime/scheme sigs.k8s.io/controller-runtime/pkg/client sigs.k8s.io/controller-runtime/pkg/controller sigs.k8s.io/controller-runtime/pkg/handler +sigs.k8s.io/controller-runtime/pkg/log sigs.k8s.io/controller-runtime/pkg/reconcile sigs.k8s.io/controller-runtime/pkg/source sigs.k8s.io/controller-runtime/pkg/internal/log @@ -510,7 +508,6 @@ sigs.k8s.io/controller-runtime/pkg/metrics sigs.k8s.io/controller-runtime/pkg/recorder sigs.k8s.io/controller-runtime/pkg/runtime/inject sigs.k8s.io/controller-runtime/pkg/webhook -sigs.k8s.io/controller-runtime/pkg/log sigs.k8s.io/controller-runtime/pkg/log/zap sigs.k8s.io/controller-runtime/pkg/manager/signals sigs.k8s.io/controller-runtime/pkg/scheme diff --git a/vendor/sigs.k8s.io/cluster-api/.gitignore b/vendor/sigs.k8s.io/cluster-api/.gitignore index 2629c11a95..d2b8800aea 100644 --- a/vendor/sigs.k8s.io/cluster-api/.gitignore +++ b/vendor/sigs.k8s.io/cluster-api/.gitignore @@ -42,3 +42,6 @@ config/ci/rbac/role_binding.yaml config/ci/rbac/role.yaml config/ci/manager/manager.yaml config/crds-v1alpha1 + +# Sample config files auto-generated by kubebuilder +config/samples diff --git a/vendor/sigs.k8s.io/cluster-api/README.md b/vendor/sigs.k8s.io/cluster-api/README.md index d404a7fe06..3283f9be72 100644 --- a/vendor/sigs.k8s.io/cluster-api/README.md +++ b/vendor/sigs.k8s.io/cluster-api/README.md @@ -67,6 +67,7 @@ are also sponsored by SIG-cluster-lifecycle: * GCP, https://github.com/kubernetes-sigs/cluster-api-provider-gcp * IBM Cloud, https://github.com/kubernetes-sigs/cluster-api-provider-ibmcloud * OpenStack, https://github.com/kubernetes-sigs/cluster-api-provider-openstack + * Packet, https://github.com/packethost/cluster-api-provider-packet * Talos, https://github.com/talos-systems/cluster-api-provider-talos * Tencent Cloud, https://github.com/TencentCloud/cluster-api-provider-tencent * vSphere, https://github.com/kubernetes-sigs/cluster-api-provider-vsphere diff --git a/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/clusterdeployer/clusterclient/clusterclient.go b/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/clusterdeployer/clusterclient/clusterclient.go index 4f11aef0a3..eac71d432a 100644 --- a/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/clusterdeployer/clusterclient/clusterclient.go +++ b/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/clusterdeployer/clusterclient/clusterclient.go @@ -680,8 +680,8 @@ func (c *client) WaitForResourceStatuses() error { klog.V(10).Info("retrying: cluster status is empty") return false, nil } - if cluster.Status.ProviderStatus == nil { - klog.V(10).Info("retrying: cluster.Status.ProviderStatus is not set") + if !cluster.Status.InfrastructureReady { + klog.V(10).Info("retrying: cluster.Status.InfrastructureReady is false") return false, nil } } diff --git a/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/BUILD.bazel index be87722c07..def63679c6 100644 --- a/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/BUILD.bazel @@ -13,9 +13,9 @@ go_library( "//vendor/github.com/pkg/errors:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/noderefutil:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", ], ) @@ -35,10 +35,11 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", + "//vendor/k8s.io/utils/pointer:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/testutil:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/envtest:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/manager:go_default_library", diff --git a/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/validate_cluster_api_objects.go b/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/validate_cluster_api_objects.go index a252fbbfc1..47e4dda4f3 100644 --- a/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/validate_cluster_api_objects.go +++ b/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/validate_cluster_api_objects.go @@ -24,10 +24,10 @@ import ( "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" clusterv1alpha2 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/controller/noderefutil" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -73,9 +73,17 @@ func getClusterObject(ctx context.Context, c client.Reader, clusterName string, func validateClusterObject(w io.Writer, cluster *v1alpha2.Cluster) error { fmt.Fprintf(w, "Checking cluster object %q... ", cluster.Name) - if cluster.Status.ErrorReason != "" || cluster.Status.ErrorMessage != "" { + if cluster.Status.ErrorReason != nil || cluster.Status.ErrorMessage != nil { + var reason capierrors.ClusterStatusError + if cluster.Status.ErrorReason != nil { + reason = *cluster.Status.ErrorReason + } + var message string + if cluster.Status.ErrorMessage != nil { + message = *cluster.Status.ErrorMessage + } fmt.Fprintf(w, "FAIL\n") - fmt.Fprintf(w, "\t[%v]: %s\n", cluster.Status.ErrorReason, cluster.Status.ErrorMessage) + fmt.Fprintf(w, "\t[%v]: %s\n", reason, message) return errors.Errorf("cluster %q failed the validation", cluster.Name) } fmt.Fprintf(w, "PASS\n") @@ -98,7 +106,7 @@ func validateMachineObjects(ctx context.Context, w io.Writer, machines *v1alpha2 func validateMachineObject(ctx context.Context, w io.Writer, machine v1alpha2.Machine, client client.Client) bool { fmt.Fprintf(w, "Checking machine object %q... ", machine.Name) if machine.Status.ErrorReason != nil || machine.Status.ErrorMessage != nil { - var reason common.MachineStatusError + var reason capierrors.MachineStatusError if machine.Status.ErrorReason != nil { reason = *machine.Status.ErrorReason } diff --git a/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/validate_cluster_api_objects_test.go b/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/validate_cluster_api_objects_test.go index 5e11f38218..bce895f2c0 100644 --- a/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/validate_cluster_api_objects_test.go +++ b/vendor/sigs.k8s.io/cluster-api/cmd/clusterctl/validation/validate_cluster_api_objects_test.go @@ -27,23 +27,24 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + "k8s.io/utils/pointer" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/testutil" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" ) var c client.Client -func newClusterStatus(errorReason common.ClusterStatusError, errorMessage string) v1alpha2.ClusterStatus { +func newClusterStatus(errorReason *capierrors.ClusterStatusError, errorMessage *string) v1alpha2.ClusterStatus { return v1alpha2.ClusterStatus{ ErrorReason: errorReason, ErrorMessage: errorMessage, } } -func newMachineStatus(nodeRef *v1.ObjectReference, errorReason *common.MachineStatusError, errorMessage *string) v1alpha2.MachineStatus { +func newMachineStatus(nodeRef *v1.ObjectReference, errorReason *capierrors.MachineStatusError, errorMessage *string) v1alpha2.MachineStatus { return v1alpha2.MachineStatus{ NodeRef: nodeRef, ErrorReason: errorReason, @@ -51,7 +52,7 @@ func newMachineStatus(nodeRef *v1.ObjectReference, errorReason *common.MachineSt } } -func getMachineWithError(machineName, namespace string, nodeRef *v1.ObjectReference, errorReason *common.MachineStatusError, errorMessage *string) v1alpha2.Machine { +func getMachineWithError(machineName, namespace string, nodeRef *v1.ObjectReference, errorReason *capierrors.MachineStatusError, errorMessage *string) v1alpha2.Machine { return v1alpha2.Machine{ ObjectMeta: metav1.ObjectMeta{ Name: machineName, @@ -59,7 +60,7 @@ func getMachineWithError(machineName, namespace string, nodeRef *v1.ObjectRefere }, Spec: v1alpha2.MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureRef", Name: "machine-infrastructure", }, @@ -225,32 +226,32 @@ func TestGetClusterObjectWithMoreThanOneCluster(t *testing.T) { func TestValidateClusterObject(t *testing.T) { var testcases = []struct { name string - errorReason common.ClusterStatusError - errorMessage string + errorReason *capierrors.ClusterStatusError + errorMessage *string expectErr bool }{ { name: "Cluster has no error", - errorReason: "", - errorMessage: "", + errorReason: nil, + errorMessage: nil, expectErr: false, }, { name: "Cluster has error reason", - errorReason: common.CreateClusterError, - errorMessage: "", + errorReason: capierrors.ClusterStatusErrorPtr(capierrors.CreateClusterError), + errorMessage: nil, expectErr: true, }, { name: "Cluster has error message", - errorReason: "", - errorMessage: "Failed to create cluster", + errorReason: nil, + errorMessage: pointer.StringPtr("Failed to create cluster"), expectErr: true, }, { name: "Cluster has error reason and message", - errorReason: common.CreateClusterError, - errorMessage: "Failed to create cluster", + errorReason: capierrors.ClusterStatusErrorPtr(capierrors.CreateClusterError), + errorMessage: pointer.StringPtr("Failed to create cluster"), expectErr: true, }, } @@ -289,12 +290,12 @@ func TestValidateMachineObjects(t *testing.T) { defer c.Delete(context.TODO(), &testNode) testNodeRef := v1.ObjectReference{Kind: "Node", Name: testNodeName} - machineErrorReason := common.CreateMachineError + machineErrorReason := capierrors.CreateMachineError machineErrorMessage := "Failed to create machine" var testcases = []struct { name string nodeRef *v1.ObjectReference - errorReason *common.MachineStatusError + errorReason *capierrors.MachineStatusError errorMessage *string expectErr bool }{ @@ -443,7 +444,7 @@ func TestValidateClusterAPIObjectsOutput(t *testing.T) { testNodeRef2 := v1.ObjectReference{Kind: "Node", Name: testNode2Name} testNodeRefNotReady := v1.ObjectReference{Kind: "Node", Name: testNodeNotReadyName} testNodeRefNotExist := v1.ObjectReference{Kind: "Node", Name: "test-node-not-exist"} - machineErrorReason := common.CreateMachineError + machineErrorReason := capierrors.CreateMachineError machineErrorMessage := "Failed to create machine" var testcases = []struct { @@ -465,9 +466,12 @@ func TestValidateClusterAPIObjectsOutput(t *testing.T) { outputFileName: "validate-cluster-api-object-output-pass.golden", }, { - name: "Failed to validate cluster object", - namespace: "validate-cluster-objects-errors", - clusterStatus: newClusterStatus(common.CreateClusterError, "Failed to create cluster"), + name: "Failed to validate cluster object", + namespace: "validate-cluster-objects-errors", + clusterStatus: newClusterStatus( + capierrors.ClusterStatusErrorPtr(capierrors.CreateClusterError), + pointer.StringPtr("Failed to create cluster"), + ), machine1Status: newMachineStatus(&testNodeRef1, nil, nil), machine2Status: newMachineStatus(&testNodeRef2, nil, nil), expectErr: true, diff --git a/vendor/sigs.k8s.io/cluster-api/cmd/example-provider/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/cmd/example-provider/BUILD.bazel index fd287d115d..9743e8607e 100644 --- a/vendor/sigs.k8s.io/cluster-api/cmd/example-provider/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/cmd/example-provider/BUILD.bazel @@ -9,10 +9,8 @@ go_library( deps = [ "//vendor/k8s.io/klog:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/machine:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/client/config:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/manager:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/runtime/signals:go_default_library", diff --git a/vendor/sigs.k8s.io/cluster-api/cmd/example-provider/main.go b/vendor/sigs.k8s.io/cluster-api/cmd/example-provider/main.go index 5372c7ca03..d82e3f9106 100644 --- a/vendor/sigs.k8s.io/cluster-api/cmd/example-provider/main.go +++ b/vendor/sigs.k8s.io/cluster-api/cmd/example-provider/main.go @@ -21,10 +21,8 @@ import ( "k8s.io/klog" clusterapis "sigs.k8s.io/cluster-api/pkg/apis" - "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset" capicluster "sigs.k8s.io/cluster-api/pkg/controller/cluster" capimachine "sigs.k8s.io/cluster-api/pkg/controller/machine" - "sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster" "sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/runtime/signals" @@ -32,7 +30,6 @@ import ( func main() { klog.InitFlags(nil) - flag.Set("logtostderr", "true") flag.Parse() cfg := config.GetConfigOrDie() @@ -43,22 +40,12 @@ func main() { klog.Fatalf("Failed to set up controller manager: %v", err) } - cs, err := clientset.NewForConfig(cfg) - if err != nil { - klog.Fatalf("Failed to create client from configuration: %v", err) - } - - recorder := mgr.GetEventRecorderFor("clusterapi-controller") - - // Initialize cluster actuator. - clusterActuator, _ := cluster.NewClusterActuator(cs.ClusterV1alpha2(), recorder) - if err := clusterapis.AddToScheme(mgr.GetScheme()); err != nil { klog.Fatal(err) } capimachine.Add(mgr) - capicluster.AddWithActuator(mgr, clusterActuator) + capicluster.Add(mgr) if err := mgr.Start(signals.SetupSignalHandler()); err != nil { klog.Fatalf("Failed to run manager: %v", err) diff --git a/vendor/sigs.k8s.io/cluster-api/config/crds/cluster.x-k8s.io_clusters.yaml b/vendor/sigs.k8s.io/cluster-api/config/crds/cluster.x-k8s.io_clusters.yaml index d457ad609e..c9e65a2489 100644 --- a/vendor/sigs.k8s.io/cluster-api/config/crds/cluster.x-k8s.io_clusters.yaml +++ b/vendor/sigs.k8s.io/cluster-api/config/crds/cluster.x-k8s.io_clusters.yaml @@ -65,18 +65,43 @@ spec: - serviceDomain - services type: object - providerSpec: - description: Provider-specific serialized configuration to use during - cluster creation. It is recommended that providers maintain their - own versioned API types that should be serialized/deserialized from - this field. + infrastructureRef: + description: InfrastructureRef is a reference to a provider-specific + resource that holds the details for provisioning infrastructure for + a cluster in said provider. properties: - value: - description: Value is an inlined, serialized representation of the - resource configuration. It is recommended that providers maintain - their own versioned API types that should be serialized/deserialized - from this field, akin to component config. - type: object + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of an + entire object, this string should contain a valid JSON/Go field + access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen only + to have some well-defined way of referencing a part of an object. + TODO: this design is not final and this field is subject to change + in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference is + made, if any. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string type: object type: object status: @@ -84,8 +109,8 @@ spec: of Cluster properties: apiEndpoints: - description: APIEndpoint represents the endpoint to communicate with - the IP. + description: APIEndpoints represents the endpoints to communicate with + the control plane. items: description: / [APIEndpoint] APIEndpoint represents a reachable Kubernetes API endpoint. @@ -102,19 +127,22 @@ spec: type: object type: array errorMessage: - description: If set, indicates that there is a problem reconciling the - state, and will be set to a descriptive error message. + description: ErrorMessage indicates that there is a problem reconciling + the state, and will be set to a descriptive error message. type: string errorReason: - description: If set, indicates that there is a problem reconciling the - state, and will be set to a token value suitable for programmatic + description: ErrorReason indicates that there is a problem reconciling + the state, and will be set to a token value suitable for programmatic interpretation. type: string - providerStatus: - description: Provider-specific status. It is recommended that providers - maintain their own versioned API types that should be serialized/deserialized - from this field. - type: object + infrastructureReady: + description: InfrastructureReady is the state of the infrastructure + provider. + type: boolean + phase: + description: Phase represents the current phase of cluster actuation. + E.g. Pending, Running, Terminating, Failed etc. + type: string type: object type: object versions: diff --git a/vendor/sigs.k8s.io/cluster-api/config/default/kustomization.yaml b/vendor/sigs.k8s.io/cluster-api/config/default/kustomization.yaml index edf8c7b3a3..9ff239f49f 100644 --- a/vendor/sigs.k8s.io/cluster-api/config/default/kustomization.yaml +++ b/vendor/sigs.k8s.io/cluster-api/config/default/kustomization.yaml @@ -13,5 +13,5 @@ bases: - ../rbac/ - ../manager/ -patches: +patchesStrategicMerge: - manager_image_patch.yaml diff --git a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_cluster.yaml b/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_cluster.yaml deleted file mode 100644 index a0bd6b52e5..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_cluster.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha2 -kind: Cluster -metadata: - labels: - controller-tools.k8s.io: "1.0" - name: cluster-sample -spec: - # Add fields here - foo: bar diff --git a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machine.yaml b/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machine.yaml deleted file mode 100644 index 54aac83fd9..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machine.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha2 -kind: Machine -metadata: - labels: - controller-tools.k8s.io: "1.0" - name: machine-sample -spec: - # Add fields here - foo: bar - providerSpec: - test: 1 diff --git a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machinedeployment.yaml b/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machinedeployment.yaml deleted file mode 100644 index ce1f911214..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machinedeployment.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha2 -kind: MachineDeployment -metadata: - labels: - controller-tools.k8s.io: "1.0" - name: machinedeployment-sample -spec: - replicas: 3 - selector: - matchLabels: - # Add fields here - foo: bar - template: - metadata: - labels: - foo: bar diff --git a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machineset.yaml b/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machineset.yaml deleted file mode 100644 index 2b26deb239..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha1_machineset.yaml +++ /dev/null @@ -1,16 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha2 -kind: MachineSet -metadata: - labels: - controller-tools.k8s.io: "1.0" - name: machineset-sample -spec: - replicas: 3 - selector: - matchLabels: - # Add fields here - foo: bar - template: - metadata: - labels: - foo: bar diff --git a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_cluster.yaml b/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_cluster.yaml deleted file mode 100644 index a0bd6b52e5..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_cluster.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha2 -kind: Cluster -metadata: - labels: - controller-tools.k8s.io: "1.0" - name: cluster-sample -spec: - # Add fields here - foo: bar diff --git a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machine.yaml b/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machine.yaml deleted file mode 100644 index a200a0b675..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machine.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha2 -kind: Machine -metadata: - labels: - controller-tools.k8s.io: "1.0" - name: machine-sample -spec: - # Add fields here - foo: bar diff --git a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machinedeployment.yaml b/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machinedeployment.yaml deleted file mode 100644 index aceba6fec7..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machinedeployment.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha2 -kind: MachineDeployment -metadata: - labels: - controller-tools.k8s.io: "1.0" - name: machinedeployment-sample -spec: - # Add fields here - foo: bar diff --git a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machineset.yaml b/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machineset.yaml deleted file mode 100644 index 1df96753ac..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/config/samples/cluster_v1alpha2_machineset.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: cluster.k8s.io/v1alpha2 -kind: MachineSet -metadata: - labels: - controller-tools.k8s.io: "1.0" - name: machineset-sample -spec: - # Add fields here - foo: bar diff --git a/vendor/sigs.k8s.io/cluster-api/docs/proposals/20190709-cluster-spec-crds.md b/vendor/sigs.k8s.io/cluster-api/docs/proposals/20190709-cluster-spec-crds.md index 250cd1d6b2..458d8143db 100644 --- a/vendor/sigs.k8s.io/cluster-api/docs/proposals/20190709-cluster-spec-crds.md +++ b/vendor/sigs.k8s.io/cluster-api/docs/proposals/20190709-cluster-spec-crds.md @@ -133,7 +133,7 @@ When the cluster object is created, the cluster controller will retrieve the inf When an infrastructure object is updated, the provider controller will check the owner reference. If it is set, it will retrieve the cluster object to obtain the required cluster specification and starts the provisioning process. When the process finishes, it sets the `Infrastructure.Status.Ready` to true. -When the cluster controller detects the `Infrastructure.Status.Ready` is set to true, it updates `Cluster.Status.APIEndpoint` from `Infrastructure.Status.APIEndpoint` and sets `Cluster.Status.InfrastructureReady` to true. +When the cluster controller detects the `Infrastructure.Status.Ready` is set to true, it updates `Cluster.Status.APIEndpoints` from `Infrastructure.Status.APIEndpoints` and sets `Cluster.Status.InfrastructureReady` to true. ### States and Transitions diff --git a/vendor/sigs.k8s.io/cluster-api/docs/proposals/images/Makefile b/vendor/sigs.k8s.io/cluster-api/docs/proposals/images/Makefile index 909c1623b4..a6c8d412db 100644 --- a/vendor/sigs.k8s.io/cluster-api/docs/proposals/images/Makefile +++ b/vendor/sigs.k8s.io/cluster-api/docs/proposals/images/Makefile @@ -26,7 +26,7 @@ diagrams: $(DIAGRAMS) --rm \ --volume ${ROOT_DIR}:/diagrams \ --user $(shell id -u):$(shell id -g) \ - dpf9/plantuml:1.2019.6 \ + us.gcr.io/k8s-artifacts-prod/cluster-api/plantuml:1.2019.6 \ -v /diagrams/$(shell basename $(shell dirname $^))/$(notdir $^) .PHONY: diagrams diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common/BUILD.bazel deleted file mode 100644 index 5d2bbadbe8..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common/BUILD.bazel +++ /dev/null @@ -1,9 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["consts.go"], - importmap = "sigs.k8s.io/cluster-api-provider-aws/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common", - importpath = "sigs.k8s.io/cluster-api/pkg/apis/cluster/common", - visibility = ["//visibility:public"], -) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/BUILD.bazel index 31e5d73381..db29da49c1 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/BUILD.bazel @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ + "cluster_phase_types.go", "cluster_types.go", "common_types.go", "defaults.go", @@ -26,7 +27,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/scheme:go_default_library", ], ) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/cluster_phase_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/cluster_phase_types.go new file mode 100644 index 0000000000..500365e683 --- /dev/null +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/cluster_phase_types.go @@ -0,0 +1,61 @@ +/* +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 v1alpha2 + +// ClusterPhase is a string representation of a Cluster Phase. +// +// This type is a high-level indicator of the status of the Cluster as it is provisioned, +// from the API user’s perspective. +// +// The value should not be interpreted by any software components as a reliable indication +// of the actual state of the Cluster, and controllers should not use the Cluster Phase field +// value when making decisions about what action to take. +// +// Controllers should always look at the actual state of the Cluster’s fields to make those decisions. +type ClusterPhase string + +var ( + // ClusterPhasePending is the first state a Cluster is assigned by + // Cluster API Cluster controller after being created. + ClusterPhasePending = ClusterPhase("pending") + + // ClusterPhaseProvisioning is the state when the Cluster has a provider infrastructure + // object associated and can start provisioning. + ClusterPhaseProvisioning = ClusterPhase("provisioning") + + // ClusterPhaseProvisioned is the state when its + // infrastructure has been created and configured. + ClusterPhaseProvisioned = ClusterPhase("provisioned") + + // ClusterPhaseDeleting is the Cluster state when a delete + // request has been sent to the API Server, + // but its infrastructure has not yet been fully deleted. + ClusterPhaseDeleting = ClusterPhase("deleting") + + // ClusterPhaseFailed is the Cluster state when the system + // might require user intervention. + ClusterPhaseFailed = ClusterPhase("failed") + + // ClusterPhaseUnknown is returned if the Cluster state cannot be determined. + ClusterPhaseUnknown = ClusterPhase("") +) + +// ClusterPhaseStringPtr is a helper method to convert ClusterPhase to a string pointer. +func ClusterPhaseStringPtr(p ClusterPhase) *string { + s := string(p) + return &s +} diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/cluster_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/cluster_types.go index 11025f3fe4..7588432a12 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/cluster_types.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/cluster_types.go @@ -17,10 +17,9 @@ limitations under the License. package v1alpha2 import ( + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/util/validation/field" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" ) const ( @@ -54,25 +53,10 @@ type ClusterSpec struct { // +optional ClusterNetwork *ClusterNetworkingConfig `json:"clusterNetwork,omitempty"` - // Provider-specific serialized configuration to use during - // cluster creation. It is recommended that providers maintain - // their own versioned API types that should be - // serialized/deserialized from this field. + // InfrastructureRef is a reference to a provider-specific resource that holds the details + // for provisioning infrastructure for a cluster in said provider. // +optional - ProviderSpec ProviderSpec `json:"providerSpec,omitempty"` -} - -// ProviderSpec defines the configuration to use during node creation. -type ProviderSpec struct { - - // No more than one of the following may be specified. - - // Value is an inlined, serialized representation of the resource - // configuration. It is recommended that providers maintain their own - // versioned API types that should be serialized/deserialized from this - // field, akin to component config. - // +optional - Value *runtime.RawExtension `json:"value,omitempty"` + InfrastructureRef *corev1.ObjectReference `json:"infrastructureRef,omitempty"` } /// [ClusterSpec] @@ -104,31 +88,54 @@ type NetworkRanges struct { /// [ClusterStatus] // ClusterStatus defines the observed state of Cluster type ClusterStatus struct { - // APIEndpoint represents the endpoint to communicate with the IP. + // APIEndpoints represents the endpoints to communicate with the control plane. // +optional APIEndpoints []APIEndpoint `json:"apiEndpoints,omitempty"` - // NB: Eventually we will redefine ErrorReason as ClusterStatusError once the - // following issue is fixed. - // https://github.com/kubernetes-incubator/apiserver-builder/issues/176 - - // If set, indicates that there is a problem reconciling the + // ErrorReason indicates that there is a problem reconciling the // state, and will be set to a token value suitable for // programmatic interpretation. // +optional - ErrorReason common.ClusterStatusError `json:"errorReason,omitempty"` + ErrorReason *capierrors.ClusterStatusError `json:"errorReason,omitempty"` - // If set, indicates that there is a problem reconciling the + // ErrorMessage indicates that there is a problem reconciling the // state, and will be set to a descriptive error message. // +optional - ErrorMessage string `json:"errorMessage,omitempty"` + ErrorMessage *string `json:"errorMessage,omitempty"` + + // Phase represents the current phase of cluster actuation. + // E.g. Pending, Running, Terminating, Failed etc. + // +optional + Phase *string `json:"phase,omitempty"` - // Provider-specific status. - // It is recommended that providers maintain their - // own versioned API types that should be - // serialized/deserialized from this field. + // InfrastructureReady is the state of the infrastructure provider. // +optional - ProviderStatus *runtime.RawExtension `json:"providerStatus,omitempty"` + InfrastructureReady bool `json:"infrastructureReady"` +} + +// SetTypedPhase sets the Phase field to the string representation of ClusterPhase. +func (c *ClusterStatus) SetTypedPhase(p ClusterPhase) { + c.Phase = ClusterPhaseStringPtr(p) +} + +// GetTypedPhase attempts to parse the Phase field and return +// the typed ClusterPhase representation as described in `machine_phase_types.go`. +func (c *ClusterStatus) GetTypedPhase() ClusterPhase { + if c.Phase == nil { + return ClusterPhaseUnknown + } + + switch phase := ClusterPhase(*c.Phase); phase { + case + ClusterPhasePending, + ClusterPhaseProvisioning, + ClusterPhaseProvisioned, + ClusterPhaseDeleting, + ClusterPhaseFailed: + return phase + default: + return ClusterPhaseUnknown + } } /// [ClusterStatus] @@ -145,30 +152,6 @@ type APIEndpoint struct { /// [APIEndpoint] -func (o *Cluster) Validate() field.ErrorList { - errors := field.ErrorList{} - // perform validation here and add to errors using field.Invalid - if o.Spec.ClusterNetwork.ServiceDomain == "" { - errors = append(errors, field.Invalid( - field.NewPath("Spec", "ClusterNetwork", "ServiceDomain"), - o.Spec.ClusterNetwork.ServiceDomain, - "invalid cluster configuration: missing Cluster.Spec.ClusterNetwork.ServiceDomain")) - } - if len(o.Spec.ClusterNetwork.Pods.CIDRBlocks) == 0 { - errors = append(errors, field.Invalid( - field.NewPath("Spec", "ClusterNetwork", "Pods"), - o.Spec.ClusterNetwork.Pods, - "invalid cluster configuration: missing Cluster.Spec.ClusterNetwork.Pods")) - } - if len(o.Spec.ClusterNetwork.Services.CIDRBlocks) == 0 { - errors = append(errors, field.Invalid( - field.NewPath("Spec", "ClusterNetwork", "Services"), - o.Spec.ClusterNetwork.Services, - "invalid cluster configuration: missing Cluster.Spec.ClusterNetwork.Services")) - } - return errors -} - // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // ClusterList contains a list of Cluster diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/defaults.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/defaults.go index fa3e20238a..15c40afdaa 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/defaults.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/defaults.go @@ -19,7 +19,6 @@ package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" ) // PopulateDefaultsMachineDeployment fills in default field values @@ -50,11 +49,11 @@ func PopulateDefaultsMachineDeployment(d *MachineDeployment) { } if d.Spec.Strategy.Type == "" { - d.Spec.Strategy.Type = common.RollingUpdateMachineDeploymentStrategyType + d.Spec.Strategy.Type = RollingUpdateMachineDeploymentStrategyType } // Default RollingUpdate strategy only if strategy type is RollingUpdate. - if d.Spec.Strategy.Type == common.RollingUpdateMachineDeploymentStrategyType { + if d.Spec.Strategy.Type == RollingUpdateMachineDeploymentStrategyType { if d.Spec.Strategy.RollingUpdate == nil { d.Spec.Strategy.RollingUpdate = &MachineRollingUpdateDeployment{} } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machine_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machine_types.go index fff0b233d2..88a647d260 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machine_types.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machine_types.go @@ -19,7 +19,7 @@ package v1alpha2 import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" ) const ( @@ -125,7 +125,7 @@ type MachineStatus struct { // can be added as events to the Machine object and/or logged in the // controller's output. // +optional - ErrorReason *common.MachineStatusError `json:"errorReason,omitempty"` + ErrorReason *capierrors.MachineStatusError `json:"errorReason,omitempty"` // ErrorMessage will be set in the event that there is a terminal problem // reconciling the Machine and will contain a more verbose string suitable diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machine_types_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machine_types_test.go index 76e5ec769d..f2e971445f 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machine_types_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machine_types_test.go @@ -38,7 +38,7 @@ func TestStorageMachine(t *testing.T) { }, Spec: MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureRef", Name: "machine-infrastructure", }, diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machinedeployment_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machinedeployment_types.go index 36b7375677..97fe8c6330 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machinedeployment_types.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machinedeployment_types.go @@ -19,7 +19,14 @@ package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" +) + +type MachineDeploymentStrategyType string + +const ( + // Replace the old MachineSet by new one using rolling update + // i.e. gradually scale down the old MachineSet and scale up the new one. + RollingUpdateMachineDeploymentStrategyType MachineDeploymentStrategyType = "RollingUpdate" ) /// [MachineDeploymentSpec] @@ -77,7 +84,7 @@ type MachineDeploymentStrategy struct { // "RollingUpdate". // Default is RollingUpdate. // +optional - Type common.MachineDeploymentStrategyType `json:"type,omitempty"` + Type MachineDeploymentStrategyType `json:"type,omitempty"` // Rolling update config params. Present only if // MachineDeploymentStrategyType = RollingUpdate. diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machinedeployment_types_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machinedeployment_types_test.go index 0ebbeafd81..441e53a1f6 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machinedeployment_types_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machinedeployment_types_test.go @@ -40,7 +40,7 @@ func TestStorageMachineDeployment(t *testing.T) { Template: MachineTemplateSpec{ Spec: MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureRef", Name: "machine-infrastructure", }, diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machineset_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machineset_types.go index a05cf1607a..6470519f95 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machineset_types.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machineset_types.go @@ -23,7 +23,7 @@ import ( metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/validation/field" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" ) // +genclient @@ -161,7 +161,7 @@ type MachineSetStatus struct { // can be added as events to the MachineSet object and/or logged in the // controller's output. // +optional - ErrorReason *common.MachineSetStatusError `json:"errorReason,omitempty"` + ErrorReason *capierrors.MachineSetStatusError `json:"errorReason,omitempty"` // +optional ErrorMessage *string `json:"errorMessage,omitempty"` } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machineset_types_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machineset_types_test.go index 0d4c9818da..9a9db7ec37 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machineset_types_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/machineset_types_test.go @@ -40,7 +40,7 @@ func TestStorageMachineSet(t *testing.T) { Template: MachineTemplateSpec{ Spec: MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureRef", Name: "machine-infrastructure", }, diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/zz_generated.deepcopy.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/zz_generated.deepcopy.go index 7d61eadced..dc7c37782a 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/zz_generated.deepcopy.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2/zz_generated.deepcopy.go @@ -25,7 +25,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" intstr "k8s.io/apimachinery/pkg/util/intstr" - common "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + errors "sigs.k8s.io/cluster-api/pkg/errors" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -157,7 +157,11 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) { *out = new(ClusterNetworkingConfig) (*in).DeepCopyInto(*out) } - in.ProviderSpec.DeepCopyInto(&out.ProviderSpec) + if in.InfrastructureRef != nil { + in, out := &in.InfrastructureRef, &out.InfrastructureRef + *out = new(v1.ObjectReference) + **out = **in + } return } @@ -179,10 +183,20 @@ func (in *ClusterStatus) DeepCopyInto(out *ClusterStatus) { *out = make([]APIEndpoint, len(*in)) copy(*out, *in) } - if in.ProviderStatus != nil { - in, out := &in.ProviderStatus, &out.ProviderStatus - *out = new(runtime.RawExtension) - (*in).DeepCopyInto(*out) + if in.ErrorReason != nil { + in, out := &in.ErrorReason, &out.ErrorReason + *out = new(errors.ClusterStatusError) + **out = **in + } + if in.ErrorMessage != nil { + in, out := &in.ErrorMessage, &out.ErrorMessage + *out = new(string) + **out = **in + } + if in.Phase != nil { + in, out := &in.Phase, &out.Phase + *out = new(string) + **out = **in } return } @@ -550,7 +564,7 @@ func (in *MachineSetStatus) DeepCopyInto(out *MachineSetStatus) { *out = *in if in.ErrorReason != nil { in, out := &in.ErrorReason, &out.ErrorReason - *out = new(common.MachineSetStatusError) + *out = new(errors.MachineSetStatusError) **out = **in } if in.ErrorMessage != nil { @@ -619,7 +633,7 @@ func (in *MachineStatus) DeepCopyInto(out *MachineStatus) { } if in.ErrorReason != nil { in, out := &in.ErrorReason, &out.ErrorReason - *out = new(common.MachineStatusError) + *out = new(errors.MachineStatusError) **out = **in } if in.ErrorMessage != nil { @@ -725,24 +739,3 @@ func (in *ObjectMeta) DeepCopy() *ObjectMeta { in.DeepCopyInto(out) return out } - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ProviderSpec) DeepCopyInto(out *ProviderSpec) { - *out = *in - if in.Value != nil { - in, out := &in.Value, &out.Value - *out = new(runtime.RawExtension) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderSpec. -func (in *ProviderSpec) DeepCopy() *ProviderSpec { - if in == nil { - return nil - } - out := new(ProviderSpec) - in.DeepCopyInto(out) - return out -} diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/BUILD.bazel index 2487901b50..4e00e88f82 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/BUILD.bazel @@ -26,7 +26,7 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/scheme:go_default_library", ], ) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/cluster_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/cluster_types.go index 4402ddaa85..c8bdae0217 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/cluster_types.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/cluster_types.go @@ -20,7 +20,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" ) const ClusterFinalizer = "cluster.cluster.k8s.io" @@ -98,7 +98,7 @@ type ClusterStatus struct { // state, and will be set to a token value suitable for // programmatic interpretation. // +optional - ErrorReason common.ClusterStatusError `json:"errorReason,omitempty"` + ErrorReason capierrors.ClusterStatusError `json:"errorReason,omitempty"` // If set, indicates that there is a problem reconciling the // state, and will be set to a descriptive error message. diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/defaults.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/defaults.go index f9aeb4b438..cdb6ca58b6 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/defaults.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/defaults.go @@ -19,7 +19,6 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" ) // PopulateDefaultsMachineDeployment fills in default field values @@ -50,11 +49,11 @@ func PopulateDefaultsMachineDeployment(d *MachineDeployment) { } if d.Spec.Strategy.Type == "" { - d.Spec.Strategy.Type = common.RollingUpdateMachineDeploymentStrategyType + d.Spec.Strategy.Type = RollingUpdateMachineDeploymentStrategyType } // Default RollingUpdate strategy only if strategy type is RollingUpdate. - if d.Spec.Strategy.Type == common.RollingUpdateMachineDeploymentStrategyType { + if d.Spec.Strategy.Type == RollingUpdateMachineDeploymentStrategyType { if d.Spec.Strategy.RollingUpdate == nil { d.Spec.Strategy.RollingUpdate = &MachineRollingUpdateDeployment{} } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machine_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machine_types.go index f166c1cada..356150032e 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machine_types.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machine_types.go @@ -20,7 +20,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" ) const ( @@ -147,7 +147,7 @@ type MachineStatus struct { // can be added as events to the Machine object and/or logged in the // controller's output. // +optional - ErrorReason *common.MachineStatusError `json:"errorReason,omitempty"` + ErrorReason *capierrors.MachineStatusError `json:"errorReason,omitempty"` // ErrorMessage will be set in the event that there is a terminal problem // reconciling the Machine and will contain a more verbose string suitable diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machinedeployment_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machinedeployment_types.go index 4e2c1e9dec..bfc74fd390 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machinedeployment_types.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machinedeployment_types.go @@ -19,7 +19,14 @@ package v1alpha1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" +) + +type MachineDeploymentStrategyType string + +const ( + // Replace the old MachineSet by new one using rolling update + // i.e. gradually scale down the old MachineSet and scale up the new one. + RollingUpdateMachineDeploymentStrategyType MachineDeploymentStrategyType = "RollingUpdate" ) /// [MachineDeploymentSpec] @@ -77,7 +84,7 @@ type MachineDeploymentStrategy struct { // "RollingUpdate". // Default is RollingUpdate. // +optional - Type common.MachineDeploymentStrategyType `json:"type,omitempty"` + Type MachineDeploymentStrategyType `json:"type,omitempty"` // Rolling update config params. Present only if // MachineDeploymentStrategyType = RollingUpdate. diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machineset_types.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machineset_types.go index ec37c43a6b..9d71a11a03 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machineset_types.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/machineset_types.go @@ -23,7 +23,7 @@ import ( metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/validation/field" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" ) // +genclient @@ -158,7 +158,7 @@ type MachineSetStatus struct { // can be added as events to the MachineSet object and/or logged in the // controller's output. // +optional - ErrorReason *common.MachineSetStatusError `json:"errorReason,omitempty"` + ErrorReason *capierrors.MachineSetStatusError `json:"errorReason,omitempty"` // +optional ErrorMessage *string `json:"errorMessage,omitempty"` } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/zz_generated.deepcopy.go b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/zz_generated.deepcopy.go index a7826d989a..33352b17d6 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/zz_generated.deepcopy.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/apis/deprecated/v1alpha1/zz_generated.deepcopy.go @@ -25,7 +25,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" intstr "k8s.io/apimachinery/pkg/util/intstr" - common "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" + errors "sigs.k8s.io/cluster-api/pkg/errors" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -600,7 +600,7 @@ func (in *MachineSetStatus) DeepCopyInto(out *MachineSetStatus) { *out = *in if in.ErrorReason != nil { in, out := &in.ErrorReason, &out.ErrorReason - *out = new(common.MachineSetStatusError) + *out = new(errors.MachineSetStatusError) **out = **in } if in.ErrorMessage != nil { @@ -676,7 +676,7 @@ func (in *MachineStatus) DeepCopyInto(out *MachineStatus) { } if in.ErrorReason != nil { in, out := &in.ErrorReason, &out.ErrorReason - *out = new(common.MachineStatusError) + *out = new(errors.MachineStatusError) **out = **in } if in.ErrorMessage != nil { diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/controller/BUILD.bazel index 5109a71d7d..d67af4f03e 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/BUILD.bazel @@ -3,6 +3,7 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = [ + "add_cluster.go", "add_machine.go", "add_machinedeployment.go", "add_machineset.go", @@ -12,6 +13,7 @@ go_library( importpath = "sigs.k8s.io/cluster-api/pkg/controller", visibility = ["//visibility:public"], deps = [ + "//vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/machine:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset:go_default_library", diff --git a/pkg/cloud/actuators/cluster/actuator_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/add_cluster.go similarity index 72% rename from pkg/cloud/actuators/cluster/actuator_test.go rename to vendor/sigs.k8s.io/cluster-api/pkg/controller/add_cluster.go index 1914b3c37d..85d58531ea 100644 --- a/pkg/cloud/actuators/cluster/actuator_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/add_cluster.go @@ -1,5 +1,5 @@ /* -Copyright 2018 The Kubernetes Authors. +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. @@ -14,12 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cluster +package controller import ( "sigs.k8s.io/cluster-api/pkg/controller/cluster" ) -var ( - _ cluster.Actuator = (*Actuator)(nil) -) +func init() { + // AddToManagerFuncs is a list of functions to create controllers and add them to a manager. + AddToManagerFuncs = append(AddToManagerFuncs, cluster.Add) +} diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/BUILD.bazel index fe224d990f..b77143cb05 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/BUILD.bazel @@ -3,20 +3,24 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test") go_library( name = "go_default_library", srcs = [ - "actuator.go", "cluster_controller.go", - "testactuator.go", + "cluster_controller_phases.go", ], importmap = "sigs.k8s.io/cluster-api-provider-aws/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster", importpath = "sigs.k8s.io/cluster-api/pkg/controller/cluster", visibility = ["//visibility:public"], deps = [ "//vendor/github.com/pkg/errors:go_default_library", + "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", + "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", + "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/klog:go_default_library", + "//vendor/k8s.io/utils/pointer:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/controller/external:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/util:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", @@ -36,9 +40,9 @@ go_test( ], embed = [":go_default_library"], deps = [ + "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/golang.org/x/net/context:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/apimachinery/pkg/types:go_default_library", "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis:go_default_library", @@ -46,6 +50,5 @@ go_test( "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/envtest:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/manager:go_default_library", - "//vendor/sigs.k8s.io/controller-runtime/pkg/reconcile:go_default_library", ], ) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_controller.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_controller.go index 4a07eed7b9..945986880f 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_controller.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_controller.go @@ -18,13 +18,18 @@ package cluster import ( "context" + "path" + "sync" + "time" "github.com/pkg/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/tools/record" "k8s.io/klog" + "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" + "sigs.k8s.io/cluster-api/pkg/controller/external" capierrors "sigs.k8s.io/cluster-api/pkg/errors" "sigs.k8s.io/cluster-api/pkg/util" "sigs.k8s.io/controller-runtime/pkg/client" @@ -35,32 +40,41 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" ) -var DefaultActuator Actuator +const controllerName = "cluster-controller" -func AddWithActuator(mgr manager.Manager, actuator Actuator) error { - return add(mgr, newReconciler(mgr, actuator)) +// Add creates a new Cluster Controller and adds it to the Manager with default RBAC. +// The Manager will set fields on the Controller and Start it when the Manager is Started. +func Add(mgr manager.Manager) error { + r := newReconciler(mgr) + c, err := addController(mgr, r) + r.controller = c + return err } // newReconciler returns a new reconcile.Reconciler -func newReconciler(mgr manager.Manager, actuator Actuator) reconcile.Reconciler { - return &ReconcileCluster{Client: mgr.GetClient(), scheme: mgr.GetScheme(), actuator: actuator} +func newReconciler(mgr manager.Manager) *ReconcileCluster { + return &ReconcileCluster{ + Client: mgr.GetClient(), + scheme: mgr.GetScheme(), + recorder: mgr.GetEventRecorderFor(controllerName), + } } // add adds a new Controller to mgr with r as the reconcile.Reconciler -func add(mgr manager.Manager, r reconcile.Reconciler) error { +func addController(mgr manager.Manager, r reconcile.Reconciler) (controller.Controller, error) { // Create a new controller - c, err := controller.New("cluster-controller", mgr, controller.Options{Reconciler: r}) + c, err := controller.New(controllerName, mgr, controller.Options{Reconciler: r}) if err != nil { - return err + return nil, err } // Watch for changes to Cluster err = c.Watch(&source.Kind{Type: &clusterv1.Cluster{}}, &handler.EnqueueRequestForObject{}) if err != nil { - return err + return nil, err } - return nil + return c, nil } var _ reconcile.Reconciler = &ReconcileCluster{} @@ -68,81 +82,99 @@ var _ reconcile.Reconciler = &ReconcileCluster{} // ReconcileCluster reconciles a Cluster object type ReconcileCluster struct { client.Client - scheme *runtime.Scheme - actuator Actuator + scheme *runtime.Scheme + controller controller.Controller + recorder record.EventRecorder + externalWatchers sync.Map } -func (r *ReconcileCluster) Reconcile(request reconcile.Request) (reconcile.Result, error) { +func (r *ReconcileCluster) Reconcile(request reconcile.Request) (_ reconcile.Result, reterr error) { + ctx := context.TODO() + + // Fetch the Cluster instance. cluster := &clusterv1.Cluster{} - err := r.Get(context.Background(), request.NamespacedName, cluster) + err := r.Get(ctx, request.NamespacedName, cluster) if err != nil { if apierrors.IsNotFound(err) { // Object not found, return. Created objects are automatically garbage collected. // For additional cleanup logic use finalizers. return reconcile.Result{}, nil } + // Error reading the object - requeue the request. return reconcile.Result{}, err } - name := cluster.Name - klog.Infof("Running reconcile Cluster for %q", name) + // Store Cluster early state to allow patching. + patchCluster := client.MergeFrom(cluster.DeepCopy()) - // If object hasn't been deleted and doesn't have a finalizer, add one - // Add a finalizer to newly created objects. - if cluster.ObjectMeta.DeletionTimestamp.IsZero() { - finalizerCount := len(cluster.Finalizers) - - if !util.Contains(cluster.Finalizers, metav1.FinalizerDeleteDependents) { - cluster.Finalizers = append(cluster.ObjectMeta.Finalizers, metav1.FinalizerDeleteDependents) + // Always issue a Patch for the Cluster object and its status after each reconciliation. + defer func() { + gvk := cluster.GroupVersionKind() + if err := r.Client.Patch(ctx, cluster, patchCluster); err != nil { + klog.Errorf("Error Patching Cluster %q in namespace %q: %v", cluster.Name, cluster.Namespace, err) + if reterr == nil { + reterr = err + } + return + } + // TODO(vincepri): This is a hack because after a Patch, the object loses TypeMeta information. + // Remove when https://github.com/kubernetes-sigs/controller-runtime/issues/526 is fixed. + cluster.SetGroupVersionKind(gvk) + if err := r.Client.Status().Patch(ctx, cluster, patchCluster); err != nil { + klog.Errorf("Error Patching Cluster status %q in namespace %q: %v", cluster.Name, cluster.Namespace, err) + if reterr == nil { + reterr = err + } } + }() + // If object hasn't been deleted and doesn't have a finalizer, add one. + if cluster.ObjectMeta.DeletionTimestamp.IsZero() { if !util.Contains(cluster.Finalizers, clusterv1.ClusterFinalizer) { cluster.Finalizers = append(cluster.ObjectMeta.Finalizers, clusterv1.ClusterFinalizer) } + } - if len(cluster.Finalizers) > finalizerCount { - if err := r.Update(context.Background(), cluster); err != nil { - klog.Infof("Failed to add finalizer to cluster %q: %v", name, err) - return reconcile.Result{}, err - } - - // Since adding the finalizer updates the object return to avoid later update issues. - return reconcile.Result{Requeue: true}, nil + if err := r.reconcile(ctx, cluster); err != nil { + if requeueErr, ok := errors.Cause(err).(capierrors.HasRequeueAfterError); ok { + klog.Infof("Reconciliation for Cluster %q in namespace %q asked to requeue: %v", cluster.Name, cluster.Namespace, err) + return reconcile.Result{Requeue: true, RequeueAfter: requeueErr.GetRequeueAfter()}, nil } - + return reconcile.Result{}, err } if !cluster.ObjectMeta.DeletionTimestamp.IsZero() { - // no-op if finalizer has been removed. - if !util.Contains(cluster.ObjectMeta.Finalizers, clusterv1.ClusterFinalizer) { - klog.Infof("reconciling cluster object %v causes a no-op as there is no finalizer.", name) - return reconcile.Result{}, nil - } - - klog.Infof("reconciling cluster object %v triggers delete.", name) - if err := r.actuator.Delete(cluster); err != nil { - klog.Errorf("Error deleting cluster object %v; %v", name, err) + if err := r.isDeleteReady(ctx, cluster); err != nil { + if requeueErr, ok := errors.Cause(err).(capierrors.HasRequeueAfterError); ok { + klog.Infof("Reconciliation for Cluster %q in namespace %q asked to requeue: %v", cluster.Name, cluster.Namespace, err) + return reconcile.Result{Requeue: true, RequeueAfter: requeueErr.GetRequeueAfter()}, nil + } return reconcile.Result{}, err } - // Remove finalizer on successful deletion. - klog.Infof("cluster object %v deletion successful, removing finalizer.", name) + cluster.ObjectMeta.Finalizers = util.Filter(cluster.ObjectMeta.Finalizers, clusterv1.ClusterFinalizer) - if err := r.Client.Update(context.Background(), cluster); err != nil { - klog.Errorf("Error removing finalizer from cluster object %v; %v", name, err) - return reconcile.Result{}, err - } - return reconcile.Result{}, nil } - klog.Infof("reconciling cluster object %v triggers idempotent reconcile.", name) - if err := r.actuator.Reconcile(cluster); err != nil { - if requeueErr, ok := errors.Cause(err).(capierrors.HasRequeueAfterError); ok { - klog.Infof("Actuator returned requeue-after error: %v", requeueErr) - return reconcile.Result{Requeue: true, RequeueAfter: requeueErr.GetRequeueAfter()}, nil + return reconcile.Result{}, nil +} + +// isDeleteReady returns an error if InfrastructureRef referenced object still exist +// or if any resources linked to this cluster aren't yet deleted. +func (r *ReconcileCluster) isDeleteReady(ctx context.Context, cluster *v1alpha2.Cluster) error { + // TODO(vincepri): List and delete MachineDeployments, MachineSets, Machines, and + // block deletion until they're all deleted. + + if cluster.Spec.InfrastructureRef != nil { + _, err := external.Get(r.Client, cluster.Spec.InfrastructureRef, cluster.Namespace) + if err != nil && !apierrors.IsNotFound(err) { + return errors.Wrapf(err, "failed to get %s %q for Cluster %q in namespace %q", + path.Join(cluster.Spec.InfrastructureRef.APIVersion, cluster.Spec.InfrastructureRef.Kind), + cluster.Spec.InfrastructureRef.Name, cluster.Name, cluster.Namespace) + } else if err == nil { + return &capierrors.RequeueAfterError{RequeueAfter: 10 * time.Second} } - klog.Errorf("Error reconciling cluster object %v; %v", name, err) - return reconcile.Result{}, err } - return reconcile.Result{}, nil + + return nil } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_controller_phases.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_controller_phases.go new file mode 100644 index 0000000000..e2dd1d7b19 --- /dev/null +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_controller_phases.go @@ -0,0 +1,198 @@ +/* +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 cluster + +import ( + "context" + "time" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/klog" + "k8s.io/utils/pointer" + "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" + clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" + "sigs.k8s.io/cluster-api/pkg/controller/external" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" + "sigs.k8s.io/cluster-api/pkg/util" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +func (r *ReconcileCluster) reconcile(ctx context.Context, cluster *v1alpha2.Cluster) (err error) { + // TODO(vincepri): These can be generalized with an interface and possibly a for loop. + errors := []error{} + errors = append(errors, r.reconcileInfrastructure(ctx, cluster)) + errors = append(errors, r.reconcilePhase(ctx, cluster)) + + // Determine the return error, giving precedence to the first non-nil and non-requeueAfter errors. + for _, e := range errors { + if e == nil { + continue + } + if err == nil || capierrors.IsRequeueAfter(err) { + err = e + } + } + return err +} + +func (r *ReconcileCluster) reconcilePhase(ctx context.Context, cluster *v1alpha2.Cluster) error { + // Set the phase to "pending" if nil. + if cluster.Status.Phase == nil { + cluster.Status.SetTypedPhase(v1alpha2.ClusterPhasePending) + } + + // Set the phase to "provisioning" if the Cluster has an InfrastructureRef object associated. + if cluster.Spec.InfrastructureRef != nil { + cluster.Status.SetTypedPhase(v1alpha2.ClusterPhaseProvisioning) + } + + // Set the phase to "provisioned" if the infrastructure is ready. + if cluster.Status.InfrastructureReady { + cluster.Status.SetTypedPhase(v1alpha2.ClusterPhaseProvisioned) + } + + // Set the phase to "failed" if any of Status.ErrorReason or Status.ErrorMessage is not-nil. + if cluster.Status.ErrorReason != nil || cluster.Status.ErrorMessage != nil { + cluster.Status.SetTypedPhase(v1alpha2.ClusterPhaseFailed) + } + + // Set the phase to "deleting" if the deletion timestamp is set. + if !cluster.DeletionTimestamp.IsZero() { + cluster.Status.SetTypedPhase(v1alpha2.ClusterPhaseDeleting) + } + + return nil +} + +// reconcileExternal handles generic unstructured objects referenced by a Cluster. +func (r *ReconcileCluster) reconcileExternal(ctx context.Context, cluster *v1alpha2.Cluster, ref *corev1.ObjectReference) (*unstructured.Unstructured, error) { + obj, err := external.Get(r.Client, ref, cluster.Namespace) + if err != nil { + if apierrors.IsNotFound(err) && !cluster.DeletionTimestamp.IsZero() { + return nil, nil + } else if apierrors.IsNotFound(err) { + return nil, errors.Wrapf(&capierrors.RequeueAfterError{RequeueAfter: 30 * time.Second}, + "could not find %v %q for Cluster %q in namespace %q, requeuing", + ref.GroupVersionKind(), ref.Name, cluster.Name, cluster.Namespace) + } + return nil, err + } + + objPatch := client.MergeFrom(obj.DeepCopy()) + + // Delete the external object if the Cluster is being deleted. + if !cluster.DeletionTimestamp.IsZero() { + if err := r.Delete(ctx, obj); err != nil { + return nil, errors.Wrapf(err, + "failed to delete %v %q for Cluster %q in namespace %q", + obj.GroupVersionKind(), ref.Name, cluster.Name, cluster.Namespace) + } + return obj, nil + } + + // Set external object OwnerReference to the Cluster. + ownerRef := metav1.OwnerReference{ + APIVersion: cluster.APIVersion, + Kind: cluster.Kind, + Name: cluster.Name, + UID: cluster.UID, + } + + if !util.HasOwnerRef(obj.GetOwnerReferences(), ownerRef) { + obj.SetOwnerReferences(util.EnsureOwnerRef(obj.GetOwnerReferences(), ownerRef)) + if err := r.Patch(ctx, obj, objPatch); err != nil { + return nil, errors.Wrapf(err, + "failed to set OwnerReference on %v %q for Cluster %q in namespace %q", + obj.GroupVersionKind(), ref.Name, cluster.Name, cluster.Namespace) + } + } + + // Add watcher for external object, if there isn't one already. + _, loaded := r.externalWatchers.LoadOrStore(obj.GroupVersionKind().String(), struct{}{}) + if !loaded && r.controller != nil { + klog.Infof("Adding watcher on external object %q", obj.GroupVersionKind()) + err := r.controller.Watch( + &source.Kind{Type: obj}, + &handler.EnqueueRequestForOwner{OwnerType: &clusterv1.Cluster{}}, + ) + if err != nil { + r.externalWatchers.Delete(obj.GroupVersionKind().String()) + return nil, errors.Wrapf(err, "failed to add watcher on external object %q", obj.GroupVersionKind()) + } + } + + // Set error reason and message, if any. + errorReason, errorMessage, err := external.ErrorsFrom(obj) + if err != nil { + return nil, err + } + if errorReason != "" { + clusterStatusError := capierrors.ClusterStatusError(errorReason) + cluster.Status.ErrorReason = &clusterStatusError + } + if errorMessage != "" { + cluster.Status.ErrorMessage = pointer.StringPtr(errorMessage) + } + + return obj, nil +} + +// reconcileInfrastructure reconciles the Spec.InfrastructureRef object on a Cluster. +func (r *ReconcileCluster) reconcileInfrastructure(ctx context.Context, cluster *v1alpha2.Cluster) error { + if cluster.Spec.InfrastructureRef == nil { + return nil + } + + // Call generic external reconciler. + infraConfig, err := r.reconcileExternal(ctx, cluster, cluster.Spec.InfrastructureRef) + if infraConfig == nil && err == nil { + return nil + } else if err != nil { + return err + } + + if cluster.Status.InfrastructureReady || !infraConfig.GetDeletionTimestamp().IsZero() { + return nil + } + + // Determine if the infrastructure provider is ready. + ready, err := external.IsReady(infraConfig) + if err != nil { + return err + } else if !ready { + klog.V(3).Infof("Infrastructure provider for Cluster %q in namespace %q is not ready, requeuing", cluster.Name, cluster.Namespace) + return &capierrors.RequeueAfterError{RequeueAfter: 30 * time.Second} + } + + // Get and parse Status.APIEndpoint field from the infrastructure provider. + if err := util.UnstructuredUnmarshalField(infraConfig, &cluster.Status.APIEndpoints, "status", "apiEndpoints"); err != nil { + return errors.Wrapf(err, "failed to retrieve Status.APIEndpoints from infrastructure provider for Cluster %q in namespace %q", + cluster.Name, cluster.Namespace) + } else if len(cluster.Status.APIEndpoints) == 0 { + return errors.Wrapf(err, "retrieved empty Status.APIEndpoints from infrastructure provider for Cluster %q in namespace %q", + cluster.Name, cluster.Namespace) + } + + cluster.Status.InfrastructureReady = true + return nil +} diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_reconciler_suite_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_reconciler_suite_test.go index f7c248ae91..ee11905f17 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_reconciler_suite_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_reconciler_suite_test.go @@ -27,7 +27,6 @@ import ( "sigs.k8s.io/cluster-api/pkg/apis" "sigs.k8s.io/controller-runtime/pkg/envtest" "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/reconcile" ) var cfg *rest.Config @@ -48,18 +47,6 @@ func TestMain(m *testing.M) { os.Exit(code) } -// SetupTestReconcile returns a reconcile.Reconcile implementation that delegates to inner and -// writes the request to requests after Reconcile is finished. -func SetupTestReconcile(inner reconcile.Reconciler) (reconcile.Reconciler, chan reconcile.Request) { - requests := make(chan reconcile.Request) - fn := reconcile.Func(func(req reconcile.Request) (reconcile.Result, error) { - result, err := inner.Reconcile(req) - requests <- req - return result, err - }) - return fn, requests -} - // StartTestManager adds recFn func StartTestManager(mgr manager.Manager, t *testing.T) chan struct{} { t.Helper() diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_reconciler_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_reconciler_test.go index 7f9e7bc6f9..a670ae8c90 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_reconciler_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/cluster_reconciler_test.go @@ -20,22 +20,20 @@ import ( "testing" "time" + . "github.com/onsi/gomega" "golang.org/x/net/context" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" clusterv1alpha2 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" - "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -var c client.Client - -var expectedRequest = reconcile.Request{NamespacedName: types.NamespacedName{Name: "foo", Namespace: "default"}} - const timeout = time.Second * 5 func TestReconcile(t *testing.T) { + RegisterTestingT(t) + ctx := context.TODO() + instance := &clusterv1alpha2.Cluster{ ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}, Spec: clusterv1alpha2.ClusterSpec{}, @@ -47,26 +45,24 @@ func TestReconcile(t *testing.T) { if err != nil { t.Fatalf("error creating new manager: %v", err) } - c = mgr.GetClient() + c := mgr.GetClient() - a := newTestActuator() - recFn, requests := SetupTestReconcile(newReconciler(mgr, a)) - if err := add(mgr, recFn); err != nil { - t.Fatalf("error adding controller to manager: %v", err) - } + reconciler := newReconciler(mgr) + controller, err := addController(mgr, reconciler) + Expect(err).To(BeNil()) + reconciler.controller = controller defer close(StartTestManager(mgr, t)) // Create the Cluster object and expect the Reconcile and Deployment to be created - if err := c.Create(context.TODO(), instance); err != nil { - t.Fatalf("error creating instance: %v", err) - } - defer c.Delete(context.TODO(), instance) - select { - case recv := <-requests: - if recv != expectedRequest { - t.Error("received request does not match expected request") + Expect(c.Create(ctx, instance)).To(BeNil()) + defer c.Delete(ctx, instance) + + // Make sure the Cluster exists. + Eventually(func() bool { + key := client.ObjectKey{Namespace: instance.Namespace, Name: instance.Name} + if err := c.Get(ctx, key, instance); err != nil { + return false } - case <-time.After(timeout): - t.Error("timed out waiting for request") - } + return true + }, timeout).Should(BeTrue()) } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/testactuator.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/testactuator.go deleted file mode 100644 index 319d6ffd84..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/testactuator.go +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright 2018 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 cluster - -import ( - "sync" - - "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" -) - -type TestActuator struct { - unblock chan string - BlockOnReconcile bool - BlockOnDelete bool - ReconcileCallCount int64 - DeleteCallCount int64 - Lock sync.Mutex -} - -func (a *TestActuator) Reconcile(*v1alpha2.Cluster) error { - defer func() { - if a.BlockOnReconcile { - <-a.unblock - } - }() - - a.Lock.Lock() - defer a.Lock.Unlock() - a.ReconcileCallCount++ - return nil -} - -func (a *TestActuator) Delete(*v1alpha2.Cluster) error { - defer func() { - if a.BlockOnDelete { - <-a.unblock - } - }() - - a.Lock.Lock() - defer a.Lock.Unlock() - a.DeleteCallCount++ - return nil -} - -func newTestActuator() *TestActuator { - ta := new(TestActuator) - ta.unblock = make(chan string) - return ta -} - -func (a *TestActuator) Unblock() { - close(a.unblock) -} diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/external/testing.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/external/testing.go index ca01ebd810..113d3b603e 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/external/testing.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/external/testing.go @@ -39,7 +39,7 @@ var ( Validation: &apiextensionsv1beta1.CustomResourceValidation{}, Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ { - Name: "v1alpha1", + Name: "v1alpha2", Served: true, Storage: true, }, @@ -64,7 +64,7 @@ var ( Validation: &apiextensionsv1beta1.CustomResourceValidation{}, Versions: []apiextensionsv1beta1.CustomResourceDefinitionVersion{ { - Name: "v1alpha1", + Name: "v1alpha2", Served: true, Storage: true, }, diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/BUILD.bazel index 42348e1c5c..de2e6b8ff5 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/BUILD.bazel @@ -21,7 +21,6 @@ go_library( "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/external:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/noderefutil:go_default_library", diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller.go index 0dc8b826c6..b65dc78761 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller.go @@ -29,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" "k8s.io/klog" - "k8s.io/utils/pointer" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/controller/external" @@ -95,7 +94,7 @@ type ReconcileMachine struct { // Reconcile reads that state of the cluster for a Machine object and makes changes based on the state read // and what is in the Machine.Spec -func (r *ReconcileMachine) Reconcile(request reconcile.Request) (reconcile.Result, error) { +func (r *ReconcileMachine) Reconcile(request reconcile.Request) (_ reconcile.Result, reterr error) { ctx := context.TODO() // Fetch the Machine instance @@ -117,11 +116,22 @@ func (r *ReconcileMachine) Reconcile(request reconcile.Request) (reconcile.Resul // Always issue a Patch for the Machine object and its status after each reconciliation. // TODO(vincepri): Figure out if we should bubble up the errors from Patch to the controller. defer func() { + gvk := m.GroupVersionKind() if err := r.Client.Patch(ctx, m, patchMachine); err != nil { klog.Errorf("Error Patching Machine %q in namespace %q: %v", m.Name, m.Namespace, err) + if reterr == nil { + reterr = err + } + return } + // TODO(vincepri): This is a hack because after a Patch, the object loses TypeMeta information. + // Remove when https://github.com/kubernetes-sigs/controller-runtime/issues/526 is fixed. + m.SetGroupVersionKind(gvk) if err := r.Client.Status().Patch(ctx, m, patchMachine); err != nil { klog.Errorf("Error Patching Machine status %q in namespace %q: %v", m.Name, m.Namespace, err) + if reterr == nil { + reterr = err + } } }() @@ -129,19 +139,19 @@ func (r *ReconcileMachine) Reconcile(request reconcile.Request) (reconcile.Resul // for machine management. cluster, err := util.GetClusterFromMetadata(ctx, r.Client, m.ObjectMeta) if errors.Cause(err) == util.ErrNoCluster { - klog.Infof("Machine %q in namespace %q doesn't specify %q label, assuming nil cluster", m.Name, m.Namespace, clusterv1.MachineClusterLabelName) + klog.Infof("Machine %q in namespace %q doesn't specify %q label, assuming nil cluster", + m.Name, m.Namespace, clusterv1.MachineClusterLabelName) } else if err != nil { - return reconcile.Result{}, errors.Wrapf(err, "failed to get cluster %q for machine %q in namespace %q", m.Labels[clusterv1.MachineClusterLabelName], m.Name, m.Namespace) + return reconcile.Result{}, errors.Wrapf(err, "failed to get cluster %q for machine %q in namespace %q", + m.Labels[clusterv1.MachineClusterLabelName], m.Name, m.Namespace) } - // Set the ownerRef with foreground deletion if there is a linked cluster. if cluster != nil { m.OwnerReferences = util.EnsureOwnerRef(m.OwnerReferences, metav1.OwnerReference{ - APIVersion: cluster.APIVersion, - Kind: cluster.Kind, - Name: cluster.Name, - UID: cluster.UID, - BlockOwnerDeletion: pointer.BoolPtr(true), + APIVersion: cluster.APIVersion, + Kind: cluster.Kind, + Name: cluster.Name, + UID: cluster.UID, }) } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_phases.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_phases.go index 3fbe4aa39d..8f523fe5e1 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_phases.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_phases.go @@ -27,7 +27,6 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/klog" "k8s.io/utils/pointer" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/controller/external" @@ -156,7 +155,7 @@ func (r *ReconcileMachine) reconcileExternal(ctx context.Context, m *v1alpha2.Ma return nil, err } if errorReason != "" { - machineStatusError := common.MachineStatusError(errorReason) + machineStatusError := capierrors.MachineStatusError(errorReason) m.Status.ErrorReason = &machineStatusError } if errorMessage != "" { diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_phases_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_phases_test.go index dfe8c02915..b3c9e7800d 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_phases_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_phases_test.go @@ -43,13 +43,13 @@ func TestReconcilePhase(t *testing.T) { Spec: v1alpha2.MachineSpec{ Bootstrap: v1alpha2.Bootstrap{ ConfigRef: &corev1.ObjectReference{ - APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha1", + APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha2", Kind: "BootstrapConfig", Name: "bootstrap-config1", }, }, InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infra.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureConfig", Name: "infra-config1", }, @@ -69,7 +69,7 @@ func TestReconcilePhase(t *testing.T) { name: "new machine, expect pending", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -79,7 +79,7 @@ func TestReconcilePhase(t *testing.T) { }, infraConfig: map[string]interface{}{ "kind": "InfrastructureConfig", - "apiVersion": "infra.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "infra-config1", "namespace": "default", @@ -97,7 +97,7 @@ func TestReconcilePhase(t *testing.T) { name: "ready bootstrap, expect provisioning", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -110,7 +110,7 @@ func TestReconcilePhase(t *testing.T) { }, infraConfig: map[string]interface{}{ "kind": "InfrastructureConfig", - "apiVersion": "infra.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "infra-config1", "namespace": "default", @@ -128,7 +128,7 @@ func TestReconcilePhase(t *testing.T) { name: "ready bootstrap and infra, expect provisioned", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -141,7 +141,7 @@ func TestReconcilePhase(t *testing.T) { }, infraConfig: map[string]interface{}{ "kind": "InfrastructureConfig", - "apiVersion": "infra.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "infra-config1", "namespace": "default", @@ -174,7 +174,7 @@ func TestReconcilePhase(t *testing.T) { name: "ready bootstrap and infra, expect error with nil addresses", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -187,7 +187,7 @@ func TestReconcilePhase(t *testing.T) { }, infraConfig: map[string]interface{}{ "kind": "InfrastructureConfig", - "apiVersion": "infra.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "infra-config1", "namespace": "default", @@ -216,13 +216,13 @@ func TestReconcilePhase(t *testing.T) { Spec: v1alpha2.MachineSpec{ Bootstrap: v1alpha2.Bootstrap{ ConfigRef: &corev1.ObjectReference{ - APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha1", + APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha2", Kind: "BootstrapConfig", Name: "bootstrap-config1", }, }, InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infra.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureConfig", Name: "infra-config1", }, @@ -235,7 +235,7 @@ func TestReconcilePhase(t *testing.T) { }, bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -248,7 +248,7 @@ func TestReconcilePhase(t *testing.T) { }, infraConfig: map[string]interface{}{ "kind": "InfrastructureConfig", - "apiVersion": "infra.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "infra-config1", "namespace": "default", @@ -283,13 +283,13 @@ func TestReconcilePhase(t *testing.T) { Spec: v1alpha2.MachineSpec{ Bootstrap: v1alpha2.Bootstrap{ ConfigRef: &corev1.ObjectReference{ - APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha1", + APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha2", Kind: "BootstrapConfig", Name: "bootstrap-config1", }, }, InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infra.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureConfig", Name: "infra-config1", }, @@ -302,7 +302,7 @@ func TestReconcilePhase(t *testing.T) { }, bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -315,7 +315,7 @@ func TestReconcilePhase(t *testing.T) { }, infraConfig: map[string]interface{}{ "kind": "InfrastructureConfig", - "apiVersion": "infra.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "infra-config1", "namespace": "default", @@ -394,7 +394,7 @@ func TestReconcileBootstrap(t *testing.T) { Spec: v1alpha2.MachineSpec{ Bootstrap: v1alpha2.Bootstrap{ ConfigRef: &corev1.ObjectReference{ - APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha1", + APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha2", Kind: "BootstrapConfig", Name: "bootstrap-config1", }, @@ -413,7 +413,7 @@ func TestReconcileBootstrap(t *testing.T) { name: "new machine, bootstrap config ready with data", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -435,7 +435,7 @@ func TestReconcileBootstrap(t *testing.T) { name: "new machine, bootstrap config ready with no data", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -455,7 +455,7 @@ func TestReconcileBootstrap(t *testing.T) { name: "new machine, bootstrap config not ready", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -472,7 +472,7 @@ func TestReconcileBootstrap(t *testing.T) { name: "new machine, bootstrap config is not found", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "wrong-namespace", @@ -489,7 +489,7 @@ func TestReconcileBootstrap(t *testing.T) { name: "new machine, no bootstrap config or data", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "wrong-namespace", @@ -503,7 +503,7 @@ func TestReconcileBootstrap(t *testing.T) { name: "existing machine, bootstrap data should not change", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -522,7 +522,7 @@ func TestReconcileBootstrap(t *testing.T) { Spec: v1alpha2.MachineSpec{ Bootstrap: v1alpha2.Bootstrap{ ConfigRef: &corev1.ObjectReference{ - APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha1", + APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha2", Kind: "BootstrapConfig", Name: "bootstrap-config1", }, @@ -543,7 +543,7 @@ func TestReconcileBootstrap(t *testing.T) { name: "existing machine, bootstrap provider is to not ready", bootstrapConfig: map[string]interface{}{ "kind": "BootstrapConfig", - "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha1", + "apiVersion": "bootstrap.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "bootstrap-config1", "namespace": "default", @@ -562,7 +562,7 @@ func TestReconcileBootstrap(t *testing.T) { Spec: v1alpha2.MachineSpec{ Bootstrap: v1alpha2.Bootstrap{ ConfigRef: &corev1.ObjectReference{ - APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha1", + APIVersion: "bootstrap.cluster.x-k8s.io/v1alpha2", Kind: "BootstrapConfig", Name: "bootstrap-config1", }, @@ -621,7 +621,7 @@ func TestReconcileInfrastructure(t *testing.T) { }, Spec: v1alpha2.MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infra.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureConfig", Name: "infra-config1", }, @@ -640,7 +640,7 @@ func TestReconcileInfrastructure(t *testing.T) { name: "new machine, infrastructure config ready", infraConfig: map[string]interface{}{ "kind": "InfrastructureConfig", - "apiVersion": "infra.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "infra-config1", "namespace": "default", diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_test.go index c86ae13466..7131934740 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_controller_test.go @@ -42,7 +42,7 @@ func TestReconcileRequest(t *testing.T) { infraConfig := unstructured.Unstructured{ Object: map[string]interface{}{ "kind": "InfrastructureConfig", - "apiVersion": "infra.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{ "name": "infra-config1", "namespace": "default", @@ -72,7 +72,7 @@ func TestReconcileRequest(t *testing.T) { }, Spec: v1alpha2.MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infra.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureConfig", Name: "infra-config1", }, @@ -90,7 +90,7 @@ func TestReconcileRequest(t *testing.T) { }, Spec: v1alpha2.MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infra.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureConfig", Name: "infra-config1", }, @@ -110,7 +110,7 @@ func TestReconcileRequest(t *testing.T) { }, Spec: v1alpha2.MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infra.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureConfig", Name: "infra-config1", }, diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_reconciler_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_reconciler_test.go index 9a442dd209..cf56e9f076 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_reconciler_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machine/machine_reconciler_test.go @@ -38,7 +38,7 @@ func TestReconcile(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "foo", Namespace: "default"}, Spec: clusterv1.MachineSpec{ InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infrastructure.clusters.k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureRef", Name: "machine-infrastructure", }, diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/BUILD.bazel index c39d94c394..3c36a303f5 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/BUILD.bazel @@ -25,8 +25,6 @@ go_library( "//vendor/k8s.io/client-go/util/retry:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/integer:go_default_library", - "//vendor/k8s.io/utils/pointer:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/util:go_default_library", @@ -62,7 +60,6 @@ go_test( "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/utils/pointer:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/external:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/machinedeployment_controller.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/machinedeployment_controller.go index 4dda8db264..2821ad3cf8 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/machinedeployment_controller.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/machinedeployment_controller.go @@ -29,8 +29,6 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" "k8s.io/klog" - "k8s.io/utils/pointer" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/util" "sigs.k8s.io/controller-runtime/pkg/client" @@ -178,33 +176,15 @@ func (r *ReconcileMachineDeployment) reconcile(ctx context.Context, d *v1alpha2. return reconcile.Result{}, err } - // Set the ownerRef with foreground deletion if there is a linked cluster. if cluster != nil { d.OwnerReferences = util.EnsureOwnerRef(d.OwnerReferences, metav1.OwnerReference{ - APIVersion: cluster.APIVersion, - Kind: cluster.Kind, - Name: cluster.Name, - UID: cluster.UID, - BlockOwnerDeletion: pointer.BoolPtr(true), + APIVersion: cluster.APIVersion, + Kind: cluster.Kind, + Name: cluster.Name, + UID: cluster.UID, }) } - // Add foregroundDeletion finalizer if MachineDeployment isn't deleted and linked to a cluster. - if cluster != nil && - d.ObjectMeta.DeletionTimestamp.IsZero() && - !util.Contains(d.Finalizers, metav1.FinalizerDeleteDependents) { - - patch := client.MergeFrom(d.DeepCopy()) - d.Finalizers = append(d.ObjectMeta.Finalizers, metav1.FinalizerDeleteDependents) - if err := r.Client.Patch(ctx, d, patch); err != nil { - klog.Infof("Failed to add finalizers to MachineSet %q: %v", d.Name, err) - return reconcile.Result{}, err - } - - // Since adding the finalizer updates the object return to avoid later update issues - return reconcile.Result{Requeue: true}, nil - } - msList, err := r.getMachineSetsForDeployment(d) if err != nil { return reconcile.Result{}, err @@ -220,7 +200,7 @@ func (r *ReconcileMachineDeployment) reconcile(ctx context.Context, d *v1alpha2. } switch d.Spec.Strategy.Type { - case common.RollingUpdateMachineDeploymentStrategyType: + case v1alpha2.RollingUpdateMachineDeploymentStrategyType: return reconcile.Result{}, r.rolloutRolling(d, msList, machineMap) } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/machinedeployment_reconciler_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/machinedeployment_reconciler_test.go index e5af17c3ef..edeaf83287 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/machinedeployment_reconciler_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/machinedeployment_reconciler_test.go @@ -29,7 +29,6 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/pointer" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -51,7 +50,7 @@ func TestReconcile(t *testing.T) { RevisionHistoryLimit: pointer.Int32Ptr(0), Selector: metav1.LabelSelector{MatchLabels: labels}, Strategy: &clusterv1.MachineDeploymentStrategy{ - Type: common.RollingUpdateMachineDeploymentStrategyType, + Type: clusterv1.RollingUpdateMachineDeploymentStrategyType, RollingUpdate: &clusterv1.MachineRollingUpdateDeployment{ MaxUnavailable: intOrStrPtr(0), MaxSurge: intOrStrPtr(1), @@ -64,7 +63,7 @@ func TestReconcile(t *testing.T) { Spec: clusterv1.MachineSpec{ Version: &version, InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureMachineTemplate", Name: "foo-template", }, @@ -90,7 +89,7 @@ func TestReconcile(t *testing.T) { // Create infrastructure template resource. infraResource := map[string]interface{}{ "kind": "InfrastructureMachine", - "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{}, "spec": map[string]interface{}{ "size": "3xlarge", @@ -104,7 +103,7 @@ func TestReconcile(t *testing.T) { }, } infraTmpl.SetKind("InfrastructureMachineTemplate") - infraTmpl.SetAPIVersion("infrastructure.cluster.x-k8s.io/v1alpha1") + infraTmpl.SetAPIVersion("infrastructure.cluster.x-k8s.io/v1alpha2") infraTmpl.SetName("foo-template") infraTmpl.SetNamespace("default") Expect(c.Create(ctx, infraTmpl)).To(BeNil()) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/BUILD.bazel index a1f3d6f6a5..0e0ec02aac 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/BUILD.bazel @@ -16,7 +16,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/klog:go_default_library", "//vendor/k8s.io/utils/integer:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", ], ) @@ -33,7 +32,6 @@ go_test( "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library", "//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library", "//vendor/k8s.io/client-go/testing:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/fake:go_default_library", ], diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/util.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/util.go index e22573ee0e..333a7cdb86 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/util.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/util.go @@ -33,7 +33,6 @@ import ( intstrutil "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/klog" "k8s.io/utils/integer" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" ) @@ -489,7 +488,7 @@ func GetAvailableReplicaCountForMachineSets(machineSets []*v1alpha2.MachineSet) // IsRollingUpdate returns true if the strategy type is a rolling update. func IsRollingUpdate(deployment *v1alpha2.MachineDeployment) bool { - return deployment.Spec.Strategy.Type == common.RollingUpdateMachineDeploymentStrategyType + return deployment.Spec.Strategy.Type == v1alpha2.RollingUpdateMachineDeploymentStrategyType } // DeploymentComplete considers a deployment to be complete once all of its desired replicas @@ -507,7 +506,7 @@ func DeploymentComplete(deployment *v1alpha2.MachineDeployment, newStatus *v1alp // 2) Max number of machines allowed is reached: deployment's replicas + maxSurge == all MSs' replicas func NewMSNewReplicas(deployment *v1alpha2.MachineDeployment, allMSs []*v1alpha2.MachineSet, newMS *v1alpha2.MachineSet) (int32, error) { switch deployment.Spec.Strategy.Type { - case common.RollingUpdateMachineDeploymentStrategyType: + case v1alpha2.RollingUpdateMachineDeploymentStrategyType: // Check if we can scale up. maxSurge, err := intstrutil.GetValueFromIntOrPercent(deployment.Spec.Strategy.RollingUpdate.MaxSurge, int(*(deployment.Spec.Replicas)), true) if err != nil { diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/util_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/util_test.go index e9420dde78..5e4823a92e 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/util_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machinedeployment/util/util_test.go @@ -32,7 +32,6 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apiserver/pkg/storage/names" core "k8s.io/client-go/testing" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/fake" ) @@ -515,7 +514,7 @@ func TestResolveFenceposts(t *testing.T) { func TestNewMSNewReplicas(t *testing.T) { tests := []struct { Name string - strategyType common.MachineDeploymentStrategyType + strategyType v1alpha2.MachineDeploymentStrategyType depReplicas int32 newMSReplicas int32 maxSurge int @@ -523,12 +522,12 @@ func TestNewMSNewReplicas(t *testing.T) { }{ { "can not scale up - to newMSReplicas", - common.RollingUpdateMachineDeploymentStrategyType, + v1alpha2.RollingUpdateMachineDeploymentStrategyType, 1, 5, 1, 5, }, { "scale up - to depReplicas", - common.RollingUpdateMachineDeploymentStrategyType, + v1alpha2.RollingUpdateMachineDeploymentStrategyType, 6, 2, 10, 6, }, } @@ -573,7 +572,7 @@ func TestDeploymentComplete(t *testing.T) { MaxUnavailable: func(i int) *intstr.IntOrString { x := intstr.FromInt(i); return &x }(int(maxUnavailable)), MaxSurge: func(i int) *intstr.IntOrString { x := intstr.FromInt(i); return &x }(int(maxSurge)), }, - Type: common.RollingUpdateMachineDeploymentStrategyType, + Type: v1alpha2.RollingUpdateMachineDeploymentStrategyType, }, }, Status: v1alpha2.MachineDeploymentStatus{ @@ -650,7 +649,7 @@ func TestMaxUnavailable(t *testing.T) { MaxSurge: func(i int) *intstr.IntOrString { x := intstr.FromInt(i); return &x }(int(1)), MaxUnavailable: &maxUnavailable, }, - Type: common.RollingUpdateMachineDeploymentStrategyType, + Type: v1alpha2.RollingUpdateMachineDeploymentStrategyType, }, }, } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/BUILD.bazel index b204b427bc..cdb0a44c1b 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/BUILD.bazel @@ -21,7 +21,6 @@ go_library( "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/client-go/tools/record:go_default_library", "//vendor/k8s.io/klog:go_default_library", - "//vendor/k8s.io/utils/pointer:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/external:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/noderefutil:go_default_library", @@ -56,9 +55,9 @@ go_test( "//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library", "//vendor/k8s.io/client-go/rest:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/controller/external:go_default_library", + "//vendor/sigs.k8s.io/cluster-api/pkg/errors:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/client:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/client/fake:go_default_library", "//vendor/sigs.k8s.io/controller-runtime/pkg/envtest:go_default_library", diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/delete_policy_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/delete_policy_test.go index e91025445a..6bc55265a2 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/delete_policy_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/delete_policy_test.go @@ -21,8 +21,8 @@ import ( "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" + capierrors "sigs.k8s.io/cluster-api/pkg/errors" ) func TestMachineToDelete(t *testing.T) { @@ -161,7 +161,7 @@ func TestMachineToDelete(t *testing.T) { func TestMachineNewestDelete(t *testing.T) { currentTime := metav1.Now() - statusError := common.MachineStatusError("I'm unhealthy!") + statusError := capierrors.MachineStatusError("I'm unhealthy!") mustDeleteMachine := &v1alpha2.Machine{ObjectMeta: metav1.ObjectMeta{DeletionTimestamp: ¤tTime}} newest := &v1alpha2.Machine{ObjectMeta: metav1.ObjectMeta{CreationTimestamp: metav1.NewTime(currentTime.Time.AddDate(0, 0, -1))}} new := &v1alpha2.Machine{ObjectMeta: metav1.ObjectMeta{CreationTimestamp: metav1.NewTime(currentTime.Time.AddDate(0, 0, -5))}} @@ -229,7 +229,7 @@ func TestMachineNewestDelete(t *testing.T) { func TestMachineOldestDelete(t *testing.T) { currentTime := metav1.Now() - statusError := common.MachineStatusError("I'm unhealthy!") + statusError := capierrors.MachineStatusError("I'm unhealthy!") empty := &v1alpha2.Machine{} newest := &v1alpha2.Machine{ObjectMeta: metav1.ObjectMeta{CreationTimestamp: metav1.NewTime(currentTime.Time.AddDate(0, 0, -1))}} new := &v1alpha2.Machine{ObjectMeta: metav1.ObjectMeta{CreationTimestamp: metav1.NewTime(currentTime.Time.AddDate(0, 0, -5))}} diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/machineset_controller.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/machineset_controller.go index 766c8b2b67..99bce69702 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/machineset_controller.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/machineset_controller.go @@ -33,7 +33,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/tools/record" "k8s.io/klog" - "k8s.io/utils/pointer" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" "sigs.k8s.io/cluster-api/pkg/controller/external" "sigs.k8s.io/cluster-api/pkg/util" @@ -187,33 +186,15 @@ func (r *ReconcileMachineSet) reconcile(ctx context.Context, machineSet *cluster return reconcile.Result{}, err } - // Set the ownerRef with foreground deletion if there is a linked cluster. if cluster != nil { machineSet.OwnerReferences = util.EnsureOwnerRef(machineSet.OwnerReferences, metav1.OwnerReference{ - APIVersion: cluster.APIVersion, - Kind: cluster.Kind, - Name: cluster.Name, - UID: cluster.UID, - BlockOwnerDeletion: pointer.BoolPtr(true), + APIVersion: cluster.APIVersion, + Kind: cluster.Kind, + Name: cluster.Name, + UID: cluster.UID, }) } - // Add foregroundDeletion finalizer if MachineSet isn't deleted and linked to a cluster. - if cluster != nil && - machineSet.ObjectMeta.DeletionTimestamp.IsZero() && - !util.Contains(machineSet.Finalizers, metav1.FinalizerDeleteDependents) { - - machineSet.Finalizers = append(machineSet.ObjectMeta.Finalizers, metav1.FinalizerDeleteDependents) - - if err := r.Client.Update(context.Background(), machineSet); err != nil { - klog.Infof("Failed to add finalizers to MachineSet %q: %v", machineSet.Name, err) - return reconcile.Result{}, err - } - - // Since adding the finalizer updates the object return to avoid later update issues - return reconcile.Result{Requeue: true}, nil - } - // Filter out irrelevant machines (deleting/mismatch labels) and claim orphaned machines. filteredMachines := make([]*clusterv1.Machine, 0, len(allMachines.Items)) for idx := range allMachines.Items { diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/machineset_reconciler_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/machineset_reconciler_test.go index 4c057e6279..2fd9d8d7f3 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/machineset_reconciler_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/controller/machineset/machineset_reconciler_test.go @@ -57,7 +57,7 @@ func TestReconcile(t *testing.T) { Spec: clusterv1alpha2.MachineSpec{ Version: &version, InfrastructureRef: corev1.ObjectReference{ - APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha1", + APIVersion: "infrastructure.cluster.x-k8s.io/v1alpha2", Kind: "InfrastructureMachineTemplate", Name: "foo-template", }, @@ -75,7 +75,7 @@ func TestReconcile(t *testing.T) { // Create infrastructure template resource. infraResource := map[string]interface{}{ "kind": "InfrastructureMachine", - "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha1", + "apiVersion": "infrastructure.cluster.x-k8s.io/v1alpha2", "metadata": map[string]interface{}{}, "spec": map[string]interface{}{ "size": "3xlarge", @@ -89,7 +89,7 @@ func TestReconcile(t *testing.T) { }, } infraTmpl.SetKind("InfrastructureMachineTemplate") - infraTmpl.SetAPIVersion("infrastructure.cluster.x-k8s.io/v1alpha1") + infraTmpl.SetAPIVersion("infrastructure.cluster.x-k8s.io/v1alpha2") infraTmpl.SetName("foo-template") infraTmpl.SetNamespace("default") Expect(c.Create(ctx, infraTmpl)).To(BeNil()) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/errors/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/errors/BUILD.bazel index 3c0ca33e2e..d477813d82 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/errors/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/pkg/errors/BUILD.bazel @@ -4,15 +4,14 @@ go_library( name = "go_default_library", srcs = [ "clusters.go", + "consts.go", "controllers.go", "deployer.go", "machines.go", + "pointer.go", ], importmap = "sigs.k8s.io/cluster-api-provider-aws/vendor/sigs.k8s.io/cluster-api/pkg/errors", importpath = "sigs.k8s.io/cluster-api/pkg/errors", visibility = ["//visibility:public"], - deps = [ - "//vendor/github.com/pkg/errors:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common:go_default_library", - ], + deps = ["//vendor/github.com/pkg/errors:go_default_library"], ) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/errors/clusters.go b/vendor/sigs.k8s.io/cluster-api/pkg/errors/clusters.go index f6a0f7809c..5a9fd6b61e 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/errors/clusters.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/errors/clusters.go @@ -18,8 +18,6 @@ package errors import ( "fmt" - - commonerrors "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" ) // A more descriptive kind of error that represents an error condition that @@ -27,7 +25,7 @@ import ( // enum-style constants meant to be interpreted by clusters. The "Message" // field is meant to be read by humans. type ClusterError struct { - Reason commonerrors.ClusterStatusError + Reason ClusterStatusError Message string } @@ -41,21 +39,21 @@ func (e *ClusterError) Error() string { func InvalidClusterConfiguration(format string, args ...interface{}) *ClusterError { return &ClusterError{ - Reason: commonerrors.InvalidConfigurationClusterError, + Reason: InvalidConfigurationClusterError, Message: fmt.Sprintf(format, args...), } } func CreateCluster(format string, args ...interface{}) *ClusterError { return &ClusterError{ - Reason: commonerrors.CreateClusterError, + Reason: CreateClusterError, Message: fmt.Sprintf(format, args...), } } func DeleteCluster(format string, args ...interface{}) *ClusterError { return &ClusterError{ - Reason: commonerrors.DeleteClusterError, + Reason: DeleteClusterError, Message: fmt.Sprintf(format, args...), } } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common/consts.go b/vendor/sigs.k8s.io/cluster-api/pkg/errors/consts.go similarity index 93% rename from vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common/consts.go rename to vendor/sigs.k8s.io/cluster-api/pkg/errors/consts.go index dfa87062d9..de94f507a4 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/common/consts.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/errors/consts.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package common +package errors // Constants aren't automatically generated for unversioned packages. // Instead share the same constant for all versioned packages @@ -111,11 +111,3 @@ const ( // Example: the ProviderSpec specifies an instance type that doesn't exist. InvalidConfigurationMachineSetError MachineSetStatusError = "InvalidConfiguration" ) - -type MachineDeploymentStrategyType string - -const ( - // Replace the old MachineSet by new one using rolling update - // i.e. gradually scale down the old MachineSet and scale up the new one. - RollingUpdateMachineDeploymentStrategyType MachineDeploymentStrategyType = "RollingUpdate" -) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/errors/machines.go b/vendor/sigs.k8s.io/cluster-api/pkg/errors/machines.go index b78877b345..8a499050be 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/errors/machines.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/errors/machines.go @@ -18,8 +18,6 @@ package errors import ( "fmt" - - commonerrors "sigs.k8s.io/cluster-api/pkg/apis/cluster/common" ) // A more descriptive kind of error that represents an error condition that @@ -27,7 +25,7 @@ import ( // enum-style constants meant to be interpreted by machines. The "Message" // field is meant to be read by humans. type MachineError struct { - Reason commonerrors.MachineStatusError + Reason MachineStatusError Message string } @@ -41,28 +39,28 @@ func (e *MachineError) Error() string { func InvalidMachineConfiguration(msg string, args ...interface{}) *MachineError { return &MachineError{ - Reason: commonerrors.InvalidConfigurationMachineError, + Reason: InvalidConfigurationMachineError, Message: fmt.Sprintf(msg, args...), } } func CreateMachine(msg string, args ...interface{}) *MachineError { return &MachineError{ - Reason: commonerrors.CreateMachineError, + Reason: CreateMachineError, Message: fmt.Sprintf(msg, args...), } } func UpdateMachine(msg string, args ...interface{}) *MachineError { return &MachineError{ - Reason: commonerrors.UpdateMachineError, + Reason: UpdateMachineError, Message: fmt.Sprintf(msg, args...), } } func DeleteMachine(msg string, args ...interface{}) *MachineError { return &MachineError{ - Reason: commonerrors.DeleteMachineError, + Reason: DeleteMachineError, Message: fmt.Sprintf(msg, args...), } } diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/actuator.go b/vendor/sigs.k8s.io/cluster-api/pkg/errors/pointer.go similarity index 57% rename from vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/actuator.go rename to vendor/sigs.k8s.io/cluster-api/pkg/errors/pointer.go index 5863f989f7..2335cfaeff 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/controller/cluster/actuator.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/errors/pointer.go @@ -14,20 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cluster +package errors -import ( - clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" -) - -/// [Actuator] -// Actuator controls clusters on a specific infrastructure. All -// methods should be idempotent unless otherwise specified. -type Actuator interface { - // Reconcile creates or applies updates to the cluster. - Reconcile(*clusterv1.Cluster) error - // Delete the cluster. - Delete(*clusterv1.Cluster) error +// MachineStatusErrorPtr converts a MachineStatusError to a pointer. +func MachineStatusErrorPtr(v MachineStatusError) *MachineStatusError { + return &v } -/// [Actuator] +// ClusterStatusErrorPtr converts a MachineStatusError to a pointer. +func ClusterStatusErrorPtr(v ClusterStatusError) *ClusterStatusError { + return &v +} diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster/BUILD.bazel deleted file mode 100644 index 5406d9e401..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster/BUILD.bazel +++ /dev/null @@ -1,15 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = ["clusteractuator.go"], - importmap = "sigs.k8s.io/cluster-api-provider-aws/vendor/sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster", - importpath = "sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster", - visibility = ["//visibility:public"], - deps = [ - "//vendor/k8s.io/api/core/v1:go_default_library", - "//vendor/k8s.io/client-go/tools/record:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", - "//vendor/sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha2:go_default_library", - ], -) diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster/clusteractuator.go b/vendor/sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster/clusteractuator.go deleted file mode 100644 index 483c61a3ec..0000000000 --- a/vendor/sigs.k8s.io/cluster-api/pkg/provider/example/actuators/cluster/clusteractuator.go +++ /dev/null @@ -1,50 +0,0 @@ -/* -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 cluster - -import ( - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/tools/record" - clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" - clusterv1alpha2 "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset/typed/cluster/v1alpha2" -) - -// Actuator is responsible for performing cluster reconciliation -type Actuator struct { - clusterV1 clusterv1alpha2.ClusterV1alpha2Interface - recorder record.EventRecorder -} - -// NewClusterActuator creates a new cluster actuator -func NewClusterActuator(clusterV1 clusterv1alpha2.ClusterV1alpha2Interface, recorder record.EventRecorder) (*Actuator, error) { - return &Actuator{ - clusterV1: clusterV1, - recorder: recorder, - }, nil -} - -// Reconcile will create or update the cluster -func (a *Actuator) Reconcile(cluster *clusterv1.Cluster) error { - a.recorder.Event(cluster, corev1.EventTypeWarning, "cluster-api", "clusteractuator Reconcile invoked") - return nil -} - -// Delete deletes a cluster and is invoked by the Cluster Controller -func (a *Actuator) Delete(cluster *clusterv1.Cluster) error { - a.recorder.Event(cluster, corev1.EventTypeWarning, "cluster-api", "clusteractuator Delete invoked") - return nil -} diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/util/util.go b/vendor/sigs.k8s.io/cluster-api/pkg/util/util.go index aa973afea7..87a3916654 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/util/util.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/util/util.go @@ -166,6 +166,16 @@ func GetClusterFromMetadata(ctx context.Context, c client.Client, obj metav1.Obj return GetClusterByName(ctx, c, obj.Namespace, obj.Labels[clusterv1.MachineClusterLabelName]) } +// GetOwnerCluster returns the Cluster object owning the current resource. +func GetOwnerCluster(ctx context.Context, c client.Client, obj metav1.ObjectMeta) (*clusterv1.Cluster, error) { + for _, ref := range obj.OwnerReferences { + if ref.Kind == "Cluster" && ref.APIVersion == clusterv1.SchemeGroupVersion.String() { + return GetClusterByName(ctx, c, obj.Namespace, obj.Name) + } + } + return nil, nil +} + // GetClusterByName finds and return a Cluster object using the specified params. func GetClusterByName(ctx context.Context, c client.Client, namespace, name string) (*clusterv1.Cluster, error) { cluster := &clusterv1.Cluster{} @@ -181,6 +191,32 @@ func GetClusterByName(ctx context.Context, c client.Client, namespace, name stri return cluster, nil } +// ClusterToInfrastructureMapFunc returns a handler.ToRequestsFunc that watches for +// Cluster events and returns reconciliation requests for an infrastructure provider object. +func ClusterToInfrastructureMapFunc(gvk schema.GroupVersionKind) handler.ToRequestsFunc { + return func(o handler.MapObject) []reconcile.Request { + c, ok := o.Object.(*clusterv1.Cluster) + if !ok { + return nil + } + + // Return early if the GroupVersionKind doesn't match what we expect. + infraGVK := c.Spec.InfrastructureRef.GroupVersionKind() + if gvk != infraGVK { + return nil + } + + return []reconcile.Request{ + { + NamespacedName: client.ObjectKey{ + Namespace: c.Namespace, + Name: c.Spec.InfrastructureRef.Name, + }, + }, + } + } +} + // GetOwnerMachine returns the Machine object owning the current resource. func GetOwnerMachine(ctx context.Context, c client.Client, obj metav1.ObjectMeta) (*clusterv1.Machine, error) { for _, ref := range obj.OwnerReferences { diff --git a/vendor/sigs.k8s.io/cluster-api/pkg/util/util_test.go b/vendor/sigs.k8s.io/cluster-api/pkg/util/util_test.go index 7cf8328138..edb3f24acc 100644 --- a/vendor/sigs.k8s.io/cluster-api/pkg/util/util_test.go +++ b/vendor/sigs.k8s.io/cluster-api/pkg/util/util_test.go @@ -408,3 +408,78 @@ func TestMachineToInfrastructureMapFunc(t *testing.T) { }) } } + +func TestClusterToInfrastructureMapFunc(t *testing.T) { + var testcases = []struct { + name string + input schema.GroupVersionKind + request handler.MapObject + output []reconcile.Request + }{ + { + name: "should reconcile infra-1", + input: schema.GroupVersionKind{ + Group: "foo.cluster.x-k8s.io", + Version: "v1alpha2", + Kind: "TestCluster", + }, + request: handler.MapObject{ + Object: &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test-1", + }, + Spec: clusterv1.ClusterSpec{ + InfrastructureRef: &corev1.ObjectReference{ + APIVersion: "foo.cluster.x-k8s.io/v1alpha2", + Kind: "TestCluster", + Name: "infra-1", + }, + }, + }, + }, + output: []reconcile.Request{ + { + NamespacedName: client.ObjectKey{ + Namespace: "default", + Name: "infra-1", + }, + }, + }, + }, + { + name: "should return no matching reconcile requests", + input: schema.GroupVersionKind{ + Group: "foo.cluster.x-k8s.io", + Version: "v1alpha2", + Kind: "TestCluster", + }, + request: handler.MapObject{ + Object: &clusterv1.Cluster{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test-1", + }, + Spec: clusterv1.ClusterSpec{ + InfrastructureRef: &corev1.ObjectReference{ + APIVersion: "bar.cluster.x-k8s.io/v1alpha2", + Kind: "TestCluster", + Name: "bar-1", + }, + }, + }, + }, + output: nil, + }, + } + + for _, tc := range testcases { + t.Run(tc.name, func(t *testing.T) { + fn := ClusterToInfrastructureMapFunc(tc.input) + out := fn(tc.request) + if !reflect.DeepEqual(out, tc.output) { + t.Fatalf("Unexpected output. Got: %v, Want: %v", out, tc.output) + } + }) + } +} diff --git a/vendor/sigs.k8s.io/cluster-api/scripts/ci-integration.sh b/vendor/sigs.k8s.io/cluster-api/scripts/ci-integration.sh index 5cff424853..c317e54250 100644 --- a/vendor/sigs.k8s.io/cluster-api/scripts/ci-integration.sh +++ b/vendor/sigs.k8s.io/cluster-api/scripts/ci-integration.sh @@ -20,7 +20,6 @@ set -o pipefail MAKE="make" KIND_VERSION="v0.4.0" -KUSTOMIZE_VERSION="2.0.3" KUBECTL_VERSION="v1.15.0" CRD_YAML="crd.yaml" BOOTSTRAP_CLUSTER_NAME="clusterapi-bootstrap" @@ -31,12 +30,6 @@ INTEGRATION_TEST_DIR="./test/integration" GOOS=$(go env GOOS) GOARCH=$(go env GOARCH) -install_kustomize() { - wget "https://github.com/kubernetes-sigs/kustomize/releases/download/v${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_${GOOS}_${GOARCH}" \ - --no-verbose -O /usr/local/bin/kustomize - chmod +x /usr/local/bin/kustomize -} - install_kind() { wget "https://github.com/kubernetes-sigs/kind/releases/download/${KIND_VERSION}/kind-${GOOS}-${GOARCH}" \ --no-verbose -O /usr/local/bin/kind @@ -60,9 +53,9 @@ build_containers() { prepare_crd_yaml() { CLUSTER_API_CONFIG_PATH="./config" - kustomize build "${CLUSTER_API_CONFIG_PATH}/default/" > "${CRD_YAML}" + kubectl kustomize "${CLUSTER_API_CONFIG_PATH}/default/" > "${CRD_YAML}" echo "---" >> "${CRD_YAML}" - kustomize build "${CLUSTER_API_CONFIG_PATH}/ci/" >> "${CRD_YAML}" + kubectl kustomize "${CLUSTER_API_CONFIG_PATH}/ci/" >> "${CRD_YAML}" } create_bootstrap() { @@ -107,11 +100,9 @@ main() { ensure_docker_in_docker build_containers - install_kustomize - prepare_crd_yaml - install_kubectl install_kind + prepare_crd_yaml create_bootstrap kubectl create -f "${CRD_YAML}" diff --git a/vendor/sigs.k8s.io/cluster-api/test/integration/cluster/BUILD.bazel b/vendor/sigs.k8s.io/cluster-api/test/integration/cluster/BUILD.bazel index 4291fb5df5..321195a1f3 100644 --- a/vendor/sigs.k8s.io/cluster-api/test/integration/cluster/BUILD.bazel +++ b/vendor/sigs.k8s.io/cluster-api/test/integration/cluster/BUILD.bazel @@ -8,9 +8,7 @@ go_test( "//vendor/github.com/onsi/gomega:go_default_library", "//vendor/k8s.io/api/core/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", - "//vendor/k8s.io/client-go/informers:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library", - "//vendor/k8s.io/client-go/tools/cache:go_default_library", "//vendor/k8s.io/client-go/tools/clientcmd:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2:go_default_library", "//vendor/sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset:go_default_library", diff --git a/vendor/sigs.k8s.io/cluster-api/test/integration/cluster/cluster_test.go b/vendor/sigs.k8s.io/cluster-api/test/integration/cluster/cluster_test.go index 3934004fa2..68691be056 100644 --- a/vendor/sigs.k8s.io/cluster-api/test/integration/cluster/cluster_test.go +++ b/vendor/sigs.k8s.io/cluster-api/test/integration/cluster/cluster_test.go @@ -24,9 +24,7 @@ import ( . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - informers "k8s.io/client-go/informers" "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/cache" "k8s.io/client-go/tools/clientcmd" clusterv1 "sigs.k8s.io/cluster-api/pkg/apis/cluster/v1alpha2" clientset "sigs.k8s.io/cluster-api/pkg/client/clientset_generated/clientset" @@ -56,8 +54,6 @@ func TestCluster(t *testing.T) { var _ = Describe("Cluster-Controller", func() { var clusterapi client.ClusterInterface var client *kubernetes.Clientset - var stopper chan struct{} - var informer cache.SharedIndexInformer var testNamespace string BeforeEach(func() { @@ -76,11 +72,6 @@ var _ = Describe("Cluster-Controller", func() { Expect(err).ShouldNot(HaveOccurred()) testNamespace = ns.ObjectMeta.Name - // Create informer for events in the namespace - factory := informers.NewSharedInformerFactoryWithOptions(client, 0, informers.WithNamespace(testNamespace)) - informer = factory.Core().V1().Events().Informer() - stopper = make(chan struct{}) - // Create clusterapi client cs, err := clientset.NewForConfig(config) Expect(err).ShouldNot(HaveOccurred()) @@ -88,28 +79,11 @@ var _ = Describe("Cluster-Controller", func() { }) AfterEach(func() { - close(stopper) client.CoreV1().Namespaces().Delete(testNamespace, &metav1.DeleteOptions{}) }) Describe("Create Cluster", func() { - It("Should trigger an event", func(done Done) { - // Register handler for cluster events - events := make(chan *corev1.Event, 0) - informer.AddEventHandler(cache.ResourceEventHandlerFuncs{ - AddFunc: func(obj interface{}) { - // Guard against miscofigured informer not listening to Events - Expect(obj).Should(BeAssignableToTypeOf(&corev1.Event{})) - - e := obj.(*corev1.Event) - if e.InvolvedObject.Kind == "Cluster" { - events <- e - } - }, - }) - go informer.Run(stopper) - Expect(cache.WaitForCacheSync(stopper, informer.HasSynced)).To(BeTrue()) - + It("Should reach to pending phase after creation", func(done Done) { // Create Cluster cluster := &clusterv1.Cluster{ ObjectMeta: metav1.ObjectMeta{ @@ -118,10 +92,17 @@ var _ = Describe("Cluster-Controller", func() { }, Spec: *clusterSpec.DeepCopy(), } - _, err := clusterapi.Create(cluster) - Expect(err).ShouldNot(HaveOccurred()) - Expect(<-events).ShouldNot(BeNil()) + var err error + cluster, err = clusterapi.Create(cluster) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(func() bool { + cluster, err = clusterapi.Get(cluster.Name, metav1.GetOptions{}) + if err != nil { + return false + } + return cluster.Status.Phase != nil && *cluster.Status.Phase == "pending" + }).Should(BeTrue()) close(done) }, TIMEOUT) diff --git a/vendor/sigs.k8s.io/cluster-api/vendor/modules.txt b/vendor/sigs.k8s.io/cluster-api/vendor/modules.txt index ddc52b5fdc..4e6cd0b145 100644 --- a/vendor/sigs.k8s.io/cluster-api/vendor/modules.txt +++ b/vendor/sigs.k8s.io/cluster-api/vendor/modules.txt @@ -364,7 +364,6 @@ k8s.io/apimachinery/pkg/runtime/serializer k8s.io/apimachinery/pkg/util/runtime k8s.io/apimachinery/pkg/watch k8s.io/apimachinery/pkg/apis/meta/v1/unstructured -k8s.io/apimachinery/pkg/util/json k8s.io/apimachinery/pkg/api/equality k8s.io/apimachinery/pkg/util/rand k8s.io/apimachinery/pkg/util/sets @@ -411,8 +410,8 @@ k8s.io/client-go/util/flowcontrol k8s.io/client-go/discovery/fake k8s.io/client-go/testing k8s.io/client-go/tools/cache -k8s.io/client-go/tools/leaderelection/resourcelock k8s.io/client-go/tools/record +k8s.io/client-go/tools/leaderelection/resourcelock k8s.io/client-go/util/retry k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1 k8s.io/client-go/kubernetes/typed/apps/v1 @@ -467,10 +466,9 @@ k8s.io/client-go/tools/leaderelection k8s.io/client-go/tools/reference k8s.io/client-go/util/jsonpath k8s.io/client-go/tools/pager -k8s.io/client-go/util/workqueue k8s.io/client-go/tools/record/util +k8s.io/client-go/util/workqueue k8s.io/client-go/kubernetes/fake -k8s.io/client-go/informers k8s.io/client-go/pkg/apis/clientauthentication k8s.io/client-go/pkg/apis/clientauthentication/v1alpha1 k8s.io/client-go/pkg/apis/clientauthentication/v1beta1 @@ -515,88 +513,6 @@ k8s.io/client-go/kubernetes/typed/settings/v1alpha1/fake k8s.io/client-go/kubernetes/typed/storage/v1/fake k8s.io/client-go/kubernetes/typed/storage/v1alpha1/fake k8s.io/client-go/kubernetes/typed/storage/v1beta1/fake -k8s.io/client-go/informers/admissionregistration -k8s.io/client-go/informers/apps -k8s.io/client-go/informers/auditregistration -k8s.io/client-go/informers/autoscaling -k8s.io/client-go/informers/batch -k8s.io/client-go/informers/certificates -k8s.io/client-go/informers/coordination -k8s.io/client-go/informers/core -k8s.io/client-go/informers/events -k8s.io/client-go/informers/extensions -k8s.io/client-go/informers/internalinterfaces -k8s.io/client-go/informers/networking -k8s.io/client-go/informers/node -k8s.io/client-go/informers/policy -k8s.io/client-go/informers/rbac -k8s.io/client-go/informers/scheduling -k8s.io/client-go/informers/settings -k8s.io/client-go/informers/storage -k8s.io/client-go/informers/admissionregistration/v1beta1 -k8s.io/client-go/informers/apps/v1 -k8s.io/client-go/informers/apps/v1beta1 -k8s.io/client-go/informers/apps/v1beta2 -k8s.io/client-go/informers/auditregistration/v1alpha1 -k8s.io/client-go/informers/autoscaling/v1 -k8s.io/client-go/informers/autoscaling/v2beta1 -k8s.io/client-go/informers/autoscaling/v2beta2 -k8s.io/client-go/informers/batch/v1 -k8s.io/client-go/informers/batch/v1beta1 -k8s.io/client-go/informers/batch/v2alpha1 -k8s.io/client-go/informers/certificates/v1beta1 -k8s.io/client-go/informers/coordination/v1 -k8s.io/client-go/informers/coordination/v1beta1 -k8s.io/client-go/informers/core/v1 -k8s.io/client-go/informers/events/v1beta1 -k8s.io/client-go/informers/extensions/v1beta1 -k8s.io/client-go/informers/networking/v1 -k8s.io/client-go/informers/networking/v1beta1 -k8s.io/client-go/informers/node/v1alpha1 -k8s.io/client-go/informers/node/v1beta1 -k8s.io/client-go/informers/policy/v1beta1 -k8s.io/client-go/informers/rbac/v1 -k8s.io/client-go/informers/rbac/v1alpha1 -k8s.io/client-go/informers/rbac/v1beta1 -k8s.io/client-go/informers/scheduling/v1 -k8s.io/client-go/informers/scheduling/v1alpha1 -k8s.io/client-go/informers/scheduling/v1beta1 -k8s.io/client-go/informers/settings/v1alpha1 -k8s.io/client-go/informers/storage/v1 -k8s.io/client-go/informers/storage/v1alpha1 -k8s.io/client-go/informers/storage/v1beta1 -k8s.io/client-go/listers/admissionregistration/v1beta1 -k8s.io/client-go/listers/apps/v1 -k8s.io/client-go/listers/apps/v1beta1 -k8s.io/client-go/listers/apps/v1beta2 -k8s.io/client-go/listers/auditregistration/v1alpha1 -k8s.io/client-go/listers/autoscaling/v1 -k8s.io/client-go/listers/autoscaling/v2beta1 -k8s.io/client-go/listers/autoscaling/v2beta2 -k8s.io/client-go/listers/batch/v1 -k8s.io/client-go/listers/batch/v1beta1 -k8s.io/client-go/listers/batch/v2alpha1 -k8s.io/client-go/listers/certificates/v1beta1 -k8s.io/client-go/listers/coordination/v1 -k8s.io/client-go/listers/coordination/v1beta1 -k8s.io/client-go/listers/core/v1 -k8s.io/client-go/listers/events/v1beta1 -k8s.io/client-go/listers/extensions/v1beta1 -k8s.io/client-go/listers/networking/v1 -k8s.io/client-go/listers/networking/v1beta1 -k8s.io/client-go/listers/node/v1alpha1 -k8s.io/client-go/listers/node/v1beta1 -k8s.io/client-go/listers/policy/v1beta1 -k8s.io/client-go/listers/rbac/v1 -k8s.io/client-go/listers/rbac/v1alpha1 -k8s.io/client-go/listers/rbac/v1beta1 -k8s.io/client-go/listers/scheduling/v1 -k8s.io/client-go/listers/scheduling/v1alpha1 -k8s.io/client-go/listers/scheduling/v1beta1 -k8s.io/client-go/listers/settings/v1alpha1 -k8s.io/client-go/listers/storage/v1 -k8s.io/client-go/listers/storage/v1alpha1 -k8s.io/client-go/listers/storage/v1beta1 # k8s.io/code-generator v0.0.0-20190311093542-50b561225d70 k8s.io/code-generator/cmd/client-gen k8s.io/code-generator/cmd/conversion-gen