diff --git a/data/data/cluster-api/vsphere-infrastructure-components.yaml b/data/data/cluster-api/vsphere-infrastructure-components.yaml index 7fd175e6368..b24a12da266 100644 --- a/data/data/cluster-api/vsphere-infrastructure-components.yaml +++ b/data/data/cluster-api/vsphere-infrastructure-components.yaml @@ -2,53 +2,35 @@ apiVersion: v1 kind: Namespace metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-system + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-system --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert controller-gen.kubebuilder.io/version: v0.12.1 labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - clusterctl.cluster.x-k8s.io/move-hierarchy: "" - name: awsclustercontrolleridentities.infrastructure.cluster.x-k8s.io + cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 + name: vsphereclusteridentities.infrastructure.cluster.x-k8s.io spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - caBundle: Cg== - service: - name: capa-webhook-service - namespace: capa-system - path: /convert - conversionReviewVersions: - - v1 - - v1beta1 group: infrastructure.cluster.x-k8s.io names: categories: - cluster-api - kind: AWSClusterControllerIdentity - listKind: AWSClusterControllerIdentityList - plural: awsclustercontrolleridentities - shortNames: - - awsci - singular: awsclustercontrolleridentity + kind: VSphereClusterIdentity + listKind: VSphereClusterIdentityList + plural: vsphereclusteridentities + singular: vsphereclusteridentity scope: Cluster versions: - - name: v1beta1 + - deprecated: true + name: v1alpha3 schema: openAPIV3Schema: - description: AWSClusterControllerIdentity is the Schema for the awsclustercontrolleridentities - API It is used to grant access to use Cluster API Provider AWS Controller - credentials. + description: "VSphereClusterIdentity defines the account to be used for reconciling + clusters \n Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -63,29 +45,15 @@ spec: metadata: type: object spec: - description: Spec for this AWSClusterControllerIdentity. properties: allowedNamespaces: description: AllowedNamespaces is used to identify which namespaces - are allowed to use the identity from. Namespaces can be selected - either using an array of namespaces or with label selector. An empty - allowedNamespaces object indicates that AWSClusters can use this - identity from any namespace. If this object is nil, no namespaces - will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with - Selector to use the identity. - nullable: true + are allowed to use this account. Namespaces can be selected with + a label selector. If this object is nil, no namespaces will be allowed properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array selector: - description: An empty selector indicates that AWSClusters cannot - use this AWSClusterIdentity from any namespace. + description: Selector is a standard Kubernetes LabelSelector. + A label query over a set of resources. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -130,16 +98,72 @@ spec: type: object x-kubernetes-map-type: atomic type: object + secretName: + description: SecretName references a Secret inside the controller + namespace with the credentials to use + minLength: 1 + type: string + type: object + status: + properties: + conditions: + description: Conditions defines current service state of the VSphereCluster. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - status + - type + type: object + type: array + ready: + type: boolean type: object type: object served: true storage: false - - name: v1beta2 + subresources: + status: {} + - deprecated: true + name: v1alpha4 schema: openAPIV3Schema: - description: AWSClusterControllerIdentity is the Schema for the awsclustercontrolleridentities - API It is used to grant access to use Cluster API Provider AWS Controller - credentials. + description: "VSphereClusterIdentity defines the account to be used for reconciling + clusters \n Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -154,29 +178,15 @@ spec: metadata: type: object spec: - description: Spec for this AWSClusterControllerIdentity. properties: allowedNamespaces: description: AllowedNamespaces is used to identify which namespaces - are allowed to use the identity from. Namespaces can be selected - either using an array of namespaces or with label selector. An empty - allowedNamespaces object indicates that AWSClusters can use this - identity from any namespace. If this object is nil, no namespaces - will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with - Selector to use the identity. - nullable: true + are allowed to use this account. Namespaces can be selected with + a label selector. If this object is nil, no namespaces will be allowed properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array selector: - description: An empty selector indicates that AWSClusters cannot - use this AWSClusterIdentity from any namespace. + description: Selector is a standard Kubernetes LabelSelector. + A label query over a set of resources. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -221,54 +231,71 @@ spec: type: object x-kubernetes-map-type: atomic type: object + secretName: + description: SecretName references a Secret inside the controller + namespace with the credentials to use + minLength: 1 + type: string + type: object + status: + properties: + conditions: + description: Conditions defines current service state of the VSphereCluster. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - status + - type + type: object + type: array + ready: + type: boolean type: object type: object served: true - storage: true ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - clusterctl.cluster.x-k8s.io/move-hierarchy: "" - name: awsclusterroleidentities.infrastructure.cluster.x-k8s.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - caBundle: Cg== - service: - name: capa-webhook-service - namespace: capa-system - path: /convert - conversionReviewVersions: - - v1 - - v1beta1 - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSClusterRoleIdentity - listKind: AWSClusterRoleIdentityList - plural: awsclusterroleidentities - shortNames: - - awsri - singular: awsclusterroleidentity - scope: Cluster - versions: + storage: false + subresources: + status: {} - name: v1beta1 schema: openAPIV3Schema: - description: AWSClusterRoleIdentity is the Schema for the awsclusterroleidentities - API It is used to assume a role using the provided sourceRef. + description: VSphereClusterIdentity defines the account to be used for reconciling + clusters properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -283,29 +310,15 @@ spec: metadata: type: object spec: - description: Spec for this AWSClusterRoleIdentity. properties: allowedNamespaces: description: AllowedNamespaces is used to identify which namespaces - are allowed to use the identity from. Namespaces can be selected - either using an array of namespaces or with label selector. An empty - allowedNamespaces object indicates that AWSClusters can use this - identity from any namespace. If this object is nil, no namespaces - will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with - Selector to use the identity. - nullable: true + are allowed to use this account. Namespaces can be selected with + a label selector. If this object is nil, no namespaces will be allowed properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array selector: - description: An empty selector indicates that AWSClusters cannot - use this AWSClusterIdentity from any namespace. + description: Selector is a standard Kubernetes LabelSelector. + A label query over a set of resources. properties: matchExpressions: description: matchExpressions is a list of label selector @@ -350,74 +363,125 @@ spec: type: object x-kubernetes-map-type: atomic type: object - durationSeconds: - description: The duration, in seconds, of the role session before - it is renewed. - format: int32 - maximum: 43200 - minimum: 900 - type: integer - externalID: - description: A unique identifier that might be required when you assume - a role in another account. If the administrator of the account to - which the role belongs provided you with an external ID, then provide - that value in the ExternalId parameter. This value can be any string, - such as a passphrase or account number. A cross-account role is - usually set up to trust everyone in an account. Therefore, the administrator - of the trusting account might send an external ID to the administrator - of the trusted account. That way, only someone with the ID can assume - the role, rather than everyone in the account. For more information - about the external ID, see How to Use an External ID When Granting - Access to Your AWS Resources to a Third Party in the IAM User Guide. - type: string - inlinePolicy: - description: An IAM policy as a JSON-encoded string that you want - to use as an inline session policy. + secretName: + description: SecretName references a Secret inside the controller + namespace with the credentials to use + minLength: 1 type: string - policyARNs: - description: The Amazon Resource Names (ARNs) of the IAM managed policies - that you want to use as managed session policies. The policies must - exist in the same account as the role. + type: object + status: + properties: + conditions: + description: Conditions defines current service state of the VSphereCluster. items: - type: string + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - lastTransitionTime + - status + - type + type: object type: array - roleARN: - description: The Amazon Resource Name (ARN) of the role to assume. - type: string - sessionName: - description: An identifier for the assumed role session - type: string - sourceIdentityRef: - description: SourceIdentityRef is a reference to another identity - which will be chained to do role assumption. All identity types - are accepted. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - required: - - roleARN + ready: + type: boolean type: object type: object served: true - storage: false - - name: v1beta2 + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 + name: vsphereclusters.infrastructure.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capv-webhook-service + namespace: capv-system + path: /convert + conversionReviewVersions: + - v1 + - v1beta1 + group: infrastructure.cluster.x-k8s.io + names: + categories: + - cluster-api + kind: VSphereCluster + listKind: VSphereClusterList + plural: vsphereclusters + singular: vspherecluster + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Cluster infrastructure is ready for VSphereMachine + jsonPath: .status.ready + name: Ready + type: string + - description: Server is the address of the vSphere endpoint + jsonPath: .spec.server + name: Server + type: string + - description: API Endpoint + jsonPath: .spec.controlPlaneEndpoint[0] + name: ControlPlaneEndpoint + priority: 1 + type: string + - description: Time duration since creation of Machine + jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + name: v1alpha3 schema: openAPIV3Schema: - description: AWSClusterRoleIdentity is the Schema for the awsclusterroleidentities - API It is used to assume a role using the provided sourceRef. + description: "VSphereCluster is the Schema for the vsphereclusters API \n + Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -432,121 +496,221 @@ spec: metadata: type: object spec: - description: Spec for this AWSClusterRoleIdentity. + description: VSphereClusterSpec defines the desired state of VSphereCluster properties: - allowedNamespaces: - description: AllowedNamespaces is used to identify which namespaces - are allowed to use the identity from. Namespaces can be selected - either using an array of namespaces or with label selector. An empty - allowedNamespaces object indicates that AWSClusters can use this - identity from any namespace. If this object is nil, no namespaces - will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with - Selector to use the identity. - nullable: true + cloudProviderConfiguration: + description: 'CloudProviderConfiguration holds the cluster-wide configuration + for the DEPRECATED: will be removed in v1alpha4 vSphere cloud provider.' properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: An empty selector indicates that AWSClusters cannot - use this AWSClusterIdentity from any namespace. + disk: + description: Disk is the vSphere cloud provider's disk configuration. properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, - Exists and DoesNotExist. + scsiControllerType: + description: SCSIControllerType defines SCSI controller to + be used. + type: string + type: object + global: + description: Global is the vSphere cloud provider's global configuration. + properties: + apiBindPort: + description: APIBindPort configures the vSphere cloud controller + manager API port. Defaults to 43001. + type: string + apiDisable: + description: APIDisable disables the vSphere cloud controller + manager API. Defaults to true. + type: boolean + caFile: + description: CAFile Specifies the path to a CA certificate + in PEM format. If not configured, the system's CA certificates + will be used. + type: string + datacenters: + description: Datacenters is a CSV string of the datacenters + in which VMs are located. + type: string + insecure: + description: Insecure is a flag that disables TLS peer verification. + type: boolean + password: + description: Password is the password used to access a vSphere + endpoint. + type: string + port: + description: Port is the port on which the vSphere endpoint + is listening. Defaults to 443. + type: string + roundTripperCount: + description: RoundTripperCount specifies the SOAP round tripper + count (retries = RoundTripper - 1) + format: int32 + type: integer + secretName: + description: SecretName is the name of the Kubernetes secret + in which the vSphere credentials are located. + type: string + secretNamespace: + description: SecretNamespace is the namespace for SecretName. + type: string + secretsDirectory: + description: 'SecretsDirectory is a directory in which secrets + may be found. This may used in the event that: 1. It is + not desirable to use the K8s API to watch changes to secrets + 2. The cloud controller manager is not running in a K8s + environment, such as DC/OS. For example, the container storage + interface (CSI) is container orcehstrator (CO) agnostic, + and should support non-K8s COs. Defaults to /etc/cloud/credentials.' + type: string + serviceAccount: + description: ServiceAccount is the Kubernetes service account + used to launch the cloud controller manager. Defaults to + cloud-controller-manager. + type: string + thumbprint: + description: Thumbprint is the cryptographic thumbprint of + the vSphere endpoint's certificate. + type: string + username: + description: Username is the username used to access a vSphere + endpoint. + type: string + type: object + labels: + description: Labels is the vSphere cloud provider's zone and region + configuration. + properties: + region: + description: Region is the region in which VMs are created/located. + type: string + zone: + description: Zone is the zone in which VMs are created/located. + type: string + type: object + network: + description: Network is the vSphere cloud provider's network configuration. + properties: + name: + description: Name is the name of the network to which VMs + are connected. + type: string + type: object + providerConfig: + description: CPIProviderConfig contains extra information used + to configure the vSphere cloud provider. + properties: + cloud: + properties: + controllerImage: + type: string + extraArgs: + additionalProperties: type: string - values: - description: values is an array of string values. If - the operator is In or NotIn, the values array must - be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced - during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. A - single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field is "key", - the operator is "In", and the values array contains only - "value". The requirements are ANDed. + description: ExtraArgs passes through extra arguments + to the cloud provider. The arguments here are passed + to the cloud provider daemonset specification + type: object + type: object + storage: + properties: + attacherImage: + type: string + controllerImage: + type: string + livenessProbeImage: + type: string + metadataSyncerImage: + type: string + nodeDriverImage: + type: string + provisionerImage: + type: string + registrarImage: + type: string type: object type: object - x-kubernetes-map-type: atomic + virtualCenter: + additionalProperties: + description: CPIVCenterConfig is a vSphere cloud provider's + vCenter configuration. + properties: + datacenters: + description: Datacenters is a CSV string of the datacenters + in which VMs are located. + type: string + password: + description: Password is the password used to access a vSphere + endpoint. + type: string + port: + description: Port is the port on which the vSphere endpoint + is listening. Defaults to 443. + type: string + roundTripperCount: + description: RoundTripperCount specifies the SOAP round + tripper count (retries = RoundTripper - 1) + format: int32 + type: integer + thumbprint: + description: Thumbprint is the cryptographic thumbprint + of the vSphere endpoint's certificate. + type: string + username: + description: Username is the username used to access a vSphere + endpoint. + type: string + type: object + description: VCenter is a list of vCenter configurations. + type: object + workspace: + description: Workspace is the vSphere cloud provider's workspace + configuration. + properties: + datacenter: + description: Datacenter is the datacenter in which VMs are + created/located. + type: string + datastore: + description: Datastore is the datastore in which VMs are created/located. + type: string + folder: + description: Folder is the folder in which VMs are created/located. + type: string + resourcePool: + description: ResourcePool is the resource pool in which VMs + are created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere + endpoint. + type: string + type: object type: object - durationSeconds: - description: The duration, in seconds, of the role session before - it is renewed. - format: int32 - maximum: 43200 - minimum: 900 - type: integer - externalID: - description: A unique identifier that might be required when you assume - a role in another account. If the administrator of the account to - which the role belongs provided you with an external ID, then provide - that value in the ExternalId parameter. This value can be any string, - such as a passphrase or account number. A cross-account role is - usually set up to trust everyone in an account. Therefore, the administrator - of the trusting account might send an external ID to the administrator - of the trusted account. That way, only someone with the ID can assume - the role, rather than everyone in the account. For more information - about the external ID, see How to Use an External ID When Granting - Access to Your AWS Resources to a Third Party in the IAM User Guide. - type: string - inlinePolicy: - description: An IAM policy as a JSON-encoded string that you want - to use as an inline session policy. - type: string - policyARNs: - description: The Amazon Resource Names (ARNs) of the IAM managed policies - that you want to use as managed session policies. The policies must - exist in the same account as the role. - items: - type: string - type: array - roleARN: - description: The Amazon Resource Name (ARN) of the role to assume. - type: string - sessionName: - description: An identifier for the assumed role session - type: string - sourceIdentityRef: - description: SourceIdentityRef is a reference to another identity - which will be chained to do role assumption. All identity types - are accepted. + controlPlaneEndpoint: + description: ControlPlaneEndpoint represents the endpoint used to + communicate with the control plane. + 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. + format: int32 + type: integer + required: + - host + - port + type: object + identityRef: + description: IdentityRef is a reference to either a Secret or VSphereClusterIdentity + that contains the identity to use when reconciling the cluster. properties: kind: - description: Kind of the identity. + description: Kind of the identity. Can either be VSphereClusterIdentity + or Secret enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity + - VSphereClusterIdentity + - Secret type: string name: description: Name of the identity. @@ -556,77 +720,160 @@ spec: - kind - name type: object - required: - - roleARN + insecure: + description: 'Insecure is a flag that controls whether or not to validate + the vSphere server''s certificate. DEPRECATED: will be removed in + v1alpha4' + type: boolean + loadBalancerRef: + description: 'LoadBalancerRef may be used to enable a control plane + load balancer for this cluster. When a LoadBalancerRef is provided, + the VSphereCluster.Status.Ready field will not be true until the + referenced resource is Status.Ready and has a non-empty Status.Address + value. DEPRECATED: will be removed in v1alpha4' + properties: + 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/sig-architecture/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/sig-architecture/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 + x-kubernetes-map-type: atomic + server: + description: Server is the address of the vSphere endpoint. + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When provided, Insecure + should not be set to true + type: string + type: object + status: + description: VSphereClusterStatus defines the observed state of VSphereClusterSpec + properties: + conditions: + description: Conditions defines current service state of the VSphereCluster. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. + type: string + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. + type: string + required: + - status + - type + type: object + type: array + failureDomains: + additionalProperties: + description: FailureDomainSpec is the Schema for Cluster API failure + domains. It allows controllers to understand how many failure + domains a cluster can optionally span across. + properties: + attributes: + additionalProperties: + type: string + description: Attributes is a free form map of attributes an + infrastructure provider might use or require. + type: object + controlPlane: + description: ControlPlane determines if this failure domain + is suitable for use by control plane machines. + type: boolean + type: object + description: FailureDomains is a list of failure domain objects synced + from the infrastructure provider. + type: object + ready: + type: boolean type: object type: object served: true - storage: true ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsclusters.infrastructure.cluster.x-k8s.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - caBundle: Cg== - service: - name: capa-webhook-service - namespace: capa-system - path: /convert - conversionReviewVersions: - - v1 - - v1beta1 - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSCluster - listKind: AWSClusterList - plural: awsclusters - shortNames: - - awsc - singular: awscluster - scope: Namespaced - versions: + storage: false + subresources: + status: {} - additionalPrinterColumns: - - description: Cluster to which this AWSCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Cluster infrastructure is ready for EC2 instances + - description: Cluster infrastructure is ready for VSphereMachine jsonPath: .status.ready name: Ready type: string - - description: AWS VPC the cluster is using - jsonPath: .spec.network.vpc.id - name: VPC + - description: Server is the address of the vSphere endpoint + jsonPath: .spec.server + name: Server type: string - description: API Endpoint - jsonPath: .spec.controlPlaneEndpoint - name: Endpoint + jsonPath: .spec.controlPlaneEndpoint[0] + name: ControlPlaneEndpoint priority: 1 type: string - - description: Bastion IP address for breakglass access - jsonPath: .status.bastion.publicIp - name: Bastion IP - type: string - name: v1beta1 + - description: Time duration since creation of Machine + jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + name: v1alpha4 schema: openAPIV3Schema: - description: AWSCluster is the schema for Amazon EC2 based Kubernetes Cluster - API. + description: "VSphereCluster is the Schema for the vsphereclusters API \n + Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -641,47 +888,8 @@ spec: metadata: type: object spec: - description: AWSClusterSpec defines the desired state of an EC2-based - Kubernetes cluster. + description: VSphereClusterSpec defines the desired state of VSphereCluster properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to AWS - resources managed by the AWS provider, in addition to the ones added - by default. - type: object - bastion: - description: Bastion contains options to configure the bastion host. - properties: - allowedCIDRBlocks: - description: AllowedCIDRBlocks is a list of CIDR blocks allowed - to access the bastion host. They are set as ingress rules for - the Bastion host's Security Group (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: AMI will use the specified AMI to boot the bastion. - If not specified, the AMI will default to one picked out in - public space. - type: string - disableIngressRules: - description: DisableIngressRules will ensure there are no Ingress - rules in the bastion host's security group. Requires AllowedCIDRBlocks - to be empty. - type: boolean - enabled: - description: Enabled allows this provider to create a bastion - host instance with a public ip to access the VPC private network. - type: boolean - instanceType: - description: InstanceType will use the specified instance type - for the bastion. If not specified, Cluster API Provider AWS - will use t3.micro for all regions except us-east-1, where t2.micro - will be the default. - type: string - type: object controlPlaneEndpoint: description: ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. @@ -697,67 +905,16 @@ spec: - host - port type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration for - customizing control plane behavior. - properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups sets the security groups - used by the load balancer. Expected to be security group IDs - This is optional - if not provided new security groups will - be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: "CrossZoneLoadBalancing enables the classic ELB cross - availability zone balancing. \n With cross-zone load balancing, - each load balancer node for your Classic Load Balancer distributes - requests evenly across the registered instances in all enabled - Availability Zones. If cross-zone load balancing is disabled, - each load balancer node distributes requests evenly across the - registered instances in its Availability Zone only. \n Defaults - to false." - type: boolean - healthCheckProtocol: - description: HealthCheckProtocol sets the protocol type for classic - ELB health check target default value is ClassicELBProtocolSSL - type: string - name: - description: Name sets the name of the classic ELB load balancer. - As per AWS, the name must be unique within your set of load - balancers for the region, must have a maximum of 32 characters, - must contain only alphanumeric characters or hyphens, and cannot - begin or end with a hyphen. Once set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer (defaults - to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied to - the control plane load balancer (defaults to discovered subnets - for managed VPCs or an empty set for unmanaged VPCs) - items: - type: string - type: array - type: object - identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling this cluster + identityRef: + description: IdentityRef is a reference to either a Secret or VSphereClusterIdentity + that contains the identity to use when reconciling the cluster. properties: kind: - description: Kind of the identity. + description: Kind of the identity. Can either be VSphereClusterIdentity + or Secret enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity + - VSphereClusterIdentity + - Secret type: string name: description: Name of the identity. @@ -767,423 +924,19 @@ spec: - kind - name type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating system - used to look up machine images when a machine does not specify an - AMI. When set, this will be used for all cluster machines unless - a machine specifies a different ImageLookupBaseOS. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look up - machine images when a machine does not specify an AMI. When set, - this will be used for all cluster machines unless a machine specifies - a different ImageLookupOrg. Supports substitutions for {{.BaseOS}} - and {{.K8sVersion}} with the base OS and kubernetes version, respectively. - The BaseOS will be the value in ImageLookupBaseOS or ubuntu (the - default), and the kubernetes version as defined by the packages - produced by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to look up - machine images when a machine does not specify an AMI. When set, - this will be used for all cluster machines unless a machine specifies - a different ImageLookupOrg. - type: string - network: - description: NetworkSpec encapsulates all things related to AWS network. - properties: - cni: - description: CNI configuration - properties: - cniIngressRules: - description: CNIIngressRules specify rules to apply to control - plane and worker node security groups. The source for the - rule will be set to control plane and worker security group - IDs. - items: - description: CNIIngressRule defines an AWS ingress rule - for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the protocol - type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: SecurityGroupOverrides is an optional set of security - groups to use for cluster instances This is optional - if not - provided new security groups will be created for the cluster - type: object - 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 - ipv6CidrBlock: - description: IPv6CidrBlock is the IPv6 CIDR block to be - used when the provider creates a managed VPC. A subnet - can have an IPv4 and an IPv6 address. IPv6 is only supported - in managed clusters, this field cannot be set on AWSCluster - object. - type: string - isIpv6: - description: IsIPv6 defines the subnet as an IPv6 subnet. - A subnet is IPv6 when it is associated with a VPC that - has IPv6 enabled. IPv6 is only supported in managed clusters, - this field cannot be set on AWSCluster object. - type: boolean - 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: - availabilityZoneSelection: - default: Ordered - description: 'AvailabilityZoneSelection specifies how AZs - should be selected if there are more AZs in a region than - specified by AvailabilityZoneUsageLimit. There are 2 selection - schemes: Ordered - selects based on alphabetical order Random - - selects AZs randomly in a region Defaults to Ordered' - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: AvailabilityZoneUsageLimit specifies the maximum - number of availability zones (AZ) that should be used in - a region when automatically creating subnets. If a region - has more than this number of AZs then this number of AZs - will be picked randomly when creating default subnets. Defaults - to 3 - minimum: 1 - type: integer - 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 - ipv6: - description: IPv6 contains ipv6 specific settings for the - network. Supported only in managed clusters. This field - cannot be set on AWSCluster object. - properties: - cidrBlock: - description: CidrBlock is the CIDR block provided by Amazon - when VPC has enabled IPv6. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the id of - the egress only internet gateway associated with an - IPv6 enabled VPC. - type: string - poolId: - description: PoolID is the IP pool which must be defined - in case of BYO IP is defined. - type: string - type: object - 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. + server: + description: Server is the address of the vSphere endpoint. type: string - s3Bucket: - description: S3Bucket contains options to configure a supporting S3 - bucket for this cluster - currently used for nodes requiring Ignition - (https://coreos.github.io/ignition/) for bootstrapping (requires - BootstrapFormatIgnition feature flag to be enabled). - properties: - controlPlaneIAMInstanceProfile: - description: ControlPlaneIAMInstanceProfile is a name of the IAMInstanceProfile, - which will be allowed to read control-plane node bootstrap data - from S3 Bucket. - type: string - name: - description: Name defines name of S3 Bucket to be created. - maxLength: 63 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ - type: string - nodesIAMInstanceProfiles: - description: NodesIAMInstanceProfiles is a list of IAM instance - profiles, which will be allowed to read worker nodes bootstrap - data from S3 Bucket. - items: - type: string - type: array - required: - - controlPlaneIAMInstanceProfile - - name - - nodesIAMInstanceProfiles - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - bastion host. Valid values are empty string (do not use SSH keys), - a valid SSH key name, or omitted (use the default SSH key name) + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate type: string type: object status: - description: AWSClusterStatus defines the observed state of AWSCluster. + description: VSphereClusterStatus defines the observed state of VSphereClusterSpec properties: - bastion: - description: Instance describes an AWS instance. - properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - availabilityZone: - description: Availability zone of instance - type: string - 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 - networkInterfaces: - description: Specifies ENIs attached to instance - items: - type: string - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for - the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by - the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size or - 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - 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 - rootVolume: - description: Configuration options for the root storage volume. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by the - controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - securityGroupIds: - description: SecurityGroupIDs are one or more security group IDs - this instance belongs to. - items: - type: string - type: array - spotMarketOptions: - description: SpotMarketOptions option for configuring instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: The name of the SSH key pair. - type: string - 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 - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - type: string - 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 - volumeIDs: - description: IDs of the instance's volumes - items: - type: string - type: array - required: - - id - type: object conditions: - description: Conditions provide observations of the operational state - of a Cluster API resource. + description: Conditions defines current service state of the VSphereCluster. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -1222,7 +975,6 @@ spec: important. type: string required: - - lastTransitionTime - status - type type: object @@ -1244,202 +996,11 @@ spec: is suitable for use by control plane machines. type: boolean type: object - description: FailureDomains is a slice of FailureDomains. - type: object - networkStatus: - description: NetworkStatus 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: - crossZoneLoadBalancing: - description: CrossZoneLoadBalancing enables the classic - load balancer load balancing. - type: boolean - 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 - availabilityZones: - description: AvailabilityZones is an array of availability - zones in the VPC attached to the load balancer. - items: - type: string - type: array - 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 - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - 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: - - description - - fromPort - - protocol - - 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 - - name - type: object - description: SecurityGroups is a map from the role/kind of the - security group to its unique name, if any. - type: object + description: FailureDomains is a list of failure domain objects synced + from the infrastructure provider. type: object ready: - default: false type: boolean - required: - - ready type: object type: object served: true @@ -1447,32 +1008,27 @@ spec: subresources: status: {} - additionalPrinterColumns: - - description: Cluster to which this AWSCluster belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Cluster infrastructure is ready for EC2 instances + - description: Cluster infrastructure is ready for VSphereMachine jsonPath: .status.ready name: Ready type: string - - description: AWS VPC the cluster is using - jsonPath: .spec.network.vpc.id - name: VPC + - description: Server is the address of the vSphere endpoint. + jsonPath: .spec.server + name: Server type: string - description: API Endpoint - jsonPath: .spec.controlPlaneEndpoint - name: Endpoint + jsonPath: .spec.controlPlaneEndpoint[0] + name: ControlPlaneEndpoint priority: 1 type: string - - description: Bastion IP address for breakglass access - jsonPath: .status.bastion.publicIp - name: Bastion IP - type: string - name: v1beta2 + - description: Time duration since creation of Machine + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 schema: openAPIV3Schema: - description: AWSCluster is the schema for Amazon EC2 based Kubernetes Cluster - API. + description: VSphereCluster is the Schema for the vsphereclusters API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -1487,47 +1043,38 @@ spec: metadata: type: object spec: - description: AWSClusterSpec defines the desired state of an EC2-based - Kubernetes cluster. + description: VSphereClusterSpec defines the desired state of VSphereCluster properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to AWS - resources managed by the AWS provider, in addition to the ones added - by default. - type: object - bastion: - description: Bastion contains options to configure the bastion host. - properties: - allowedCIDRBlocks: - description: AllowedCIDRBlocks is a list of CIDR blocks allowed - to access the bastion host. They are set as ingress rules for - the Bastion host's Security Group (defaults to 0.0.0.0/0). - items: + clusterModules: + description: ClusterModules hosts information regarding the anti-affinity + vSphere constructs for each of the objects responsible for creation + of VM objects belonging to the cluster. + items: + description: ClusterModule holds the anti affinity construct `ClusterModule` + identifier in use by the VMs owned by the object referred by the + TargetObjectName field. + properties: + controlPlane: + description: ControlPlane indicates whether the referred object + is responsible for control plane nodes. Currently, only the + KubeadmControlPlane objects have this flag set to true. Only + a single object in the slice can have this value set to true. + type: boolean + moduleUUID: + description: ModuleUUID is the unique identifier of the `ClusterModule` + used by the object. type: string - type: array - ami: - description: AMI will use the specified AMI to boot the bastion. - If not specified, the AMI will default to one picked out in - public space. - type: string - disableIngressRules: - description: DisableIngressRules will ensure there are no Ingress - rules in the bastion host's security group. Requires AllowedCIDRBlocks - to be empty. - type: boolean - enabled: - description: Enabled allows this provider to create a bastion - host instance with a public ip to access the VPC private network. - type: boolean - instanceType: - description: InstanceType will use the specified instance type - for the bastion. If not specified, Cluster API Provider AWS - will use t3.micro for all regions except us-east-1, where t2.micro - will be the default. - type: string - type: object + targetObjectName: + description: TargetObjectName points to the object that uses + the Cluster Module information to enforce anti-affinity amongst + its descendant VM objects. + type: string + required: + - controlPlane + - moduleUUID + - targetObjectName + type: object + type: array controlPlaneEndpoint: description: ControlPlaneEndpoint represents the endpoint used to communicate with the control plane. @@ -1543,190 +1090,65 @@ spec: - host - port type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration for - customizing control plane behavior. + failureDomainSelector: + description: FailureDomainSelector is the label selector to use for + failure domain selection for the control plane nodes of the cluster. + If not set (`nil`), selecting failure domains will be disabled. + An empty value (`{}`) selects all existing failure domains. A valid + selector will select all failure domains which match the selector. properties: - additionalListeners: - description: AdditionalListeners sets the additional listeners - for the control plane load balancer. This is only applicable - to Network Load Balancer (NLB) types for the time being. + matchExpressions: + description: matchExpressions is a list of label selector requirements. + The requirements are ANDed. items: - description: AdditionalListenerSpec defines the desired state - of an additional listener on an AWS load balancer. + description: A label selector requirement is a selector that + contains values, a key, and an operator that relates the key + and values. properties: - port: - description: Port sets the port for the additional listener. - format: int64 - type: integer - protocol: - description: Protocol sets the protocol for the additional - listener. Currently only TCP is supported. - enum: - - TCP + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: operator represents a key's relationship to + a set of values. Valid operators are In, NotIn, Exists + and DoesNotExist. type: string + values: + description: values is an array of string values. If the + operator is In or NotIn, the values array must be non-empty. + If the operator is Exists or DoesNotExist, the values + array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array required: - - port - - protocol + - key + - operator type: object type: array - additionalSecurityGroups: - description: AdditionalSecurityGroups sets the security groups - used by the load balancer. Expected to be security group IDs - This is optional - if not provided new security groups will - be created for the load balancer - items: + matchLabels: + additionalProperties: type: string - type: array - crossZoneLoadBalancing: - description: "CrossZoneLoadBalancing enables the classic ELB cross - availability zone balancing. \n With cross-zone load balancing, - each load balancer node for your Classic Load Balancer distributes - requests evenly across the registered instances in all enabled - Availability Zones. If cross-zone load balancing is disabled, - each load balancer node distributes requests evenly across the - registered instances in its Availability Zone only. \n Defaults - to false." - type: boolean - disableHostsRewrite: - description: DisableHostsRewrite disabled the hair pinning issue - solution that adds the NLB's address as 127.0.0.1 to the hosts - file of each instance. This is by default, false. - type: boolean - healthCheckProtocol: - description: HealthCheckProtocol sets the protocol type for ELB - health check target default value is ELBProtocolSSL + description: matchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + identityRef: + description: IdentityRef is a reference to either a Secret or VSphereClusterIdentity + that contains the identity to use when reconciling the cluster. + properties: + kind: + description: Kind of the identity. Can either be VSphereClusterIdentity + or Secret enum: - - TCP - - SSL - - HTTP - - HTTPS - - TLS - - UDP - type: string - ingressRules: - description: IngressRules sets the ingress rules for the control - plane load balancer. - 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: - description: Description provides extended information about - the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress rule. - Accepted values are "-1" (all), "4" (IP in IP),"tcp", - "udp", "icmp", and "58" (ICMPv6), "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access from. - Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: The security group role to allow access from. - Cannot be specified with CidrBlocks. The field will be - combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique role - of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - loadBalancerType: - default: classic - description: LoadBalancerType sets the type for a load balancer. - The default type is classic. - enum: - - classic - - elb - - alb - - nlb - type: string - name: - description: Name sets the name of the classic ELB load balancer. - As per AWS, the name must be unique within your set of load - balancers for the region, must have a maximum of 32 characters, - must contain only alphanumeric characters or hyphens, and cannot - begin or end with a hyphen. Once set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - preserveClientIP: - description: PreserveClientIP lets the user control if preservation - of client ips must be retained or not. If this is enabled 6443 - will be opened to 0.0.0.0/0. - type: boolean - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer (defaults - to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied to - the control plane load balancer (defaults to discovered subnets - for managed VPCs or an empty set for unmanaged VPCs) - items: - type: string - type: array - type: object - identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling this cluster - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity + - VSphereClusterIdentity + - Secret type: string name: description: Name of the identity. @@ -1736,620 +1158,19 @@ spec: - kind - name type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating system - used to look up machine images when a machine does not specify an - AMI. When set, this will be used for all cluster machines unless - a machine specifies a different ImageLookupBaseOS. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look up - machine images when a machine does not specify an AMI. When set, - this will be used for all cluster machines unless a machine specifies - a different ImageLookupOrg. Supports substitutions for {{.BaseOS}} - and {{.K8sVersion}} with the base OS and kubernetes version, respectively. - The BaseOS will be the value in ImageLookupBaseOS or ubuntu (the - default), and the kubernetes version as defined by the packages - produced by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to look up - machine images when a machine does not specify an AMI. When set, - this will be used for all cluster machines unless a machine specifies - a different ImageLookupOrg. - type: string - network: - description: NetworkSpec encapsulates all things related to AWS network. - properties: - additionalControlPlaneIngressRules: - description: AdditionalControlPlaneIngressRules is an optional - set of ingress rules to add to the control plane - 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: - description: Description provides extended information about - the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress rule. - Accepted values are "-1" (all), "4" (IP in IP),"tcp", - "udp", "icmp", and "58" (ICMPv6), "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access from. - Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: The security group role to allow access from. - Cannot be specified with CidrBlocks. The field will be - combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique role - of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - cni: - description: CNI configuration - properties: - cniIngressRules: - description: CNIIngressRules specify rules to apply to control - plane and worker node security groups. The source for the - rule will be set to control plane and worker security group - IDs. - items: - description: CNIIngressRule defines an AWS ingress rule - for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the protocol - type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: SecurityGroupOverrides is an optional set of security - groups to use for cluster instances This is optional - if not - provided new security groups will be created for the cluster - type: object - 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. If you're bringing your subnet, set the - AWS subnet-id here, it must start with `subnet-`. \n When - the VPC is managed by CAPA, and you'd like the provider - to create a subnet for you, the id can be set to any placeholder - value that does not start with `subnet-`; upon creation, - the subnet AWS identifier will be populated in the `ResourceID` - field and the `id` field is going to be used as the subnet - name. If you specify a tag called `Name`, it takes precedence." - type: string - ipv6CidrBlock: - description: IPv6CidrBlock is the IPv6 CIDR block to be - used when the provider creates a managed VPC. A subnet - can have an IPv4 and an IPv6 address. IPv6 is only supported - in managed clusters, this field cannot be set on AWSCluster - object. - type: string - isIpv6: - description: IsIPv6 defines the subnet as an IPv6 subnet. - A subnet is IPv6 when it is associated with a VPC that - has IPv6 enabled. IPv6 is only supported in managed clusters, - this field cannot be set on AWSCluster object. - type: boolean - 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 - resourceID: - description: ResourceID is the subnet identifier from AWS, - READ ONLY. This field is populated when the provider manages - the 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 - required: - - id - type: object - type: array - x-kubernetes-list-map-keys: - - id - x-kubernetes-list-type: map - vpc: - description: VPC configuration. - properties: - availabilityZoneSelection: - default: Ordered - description: 'AvailabilityZoneSelection specifies how AZs - should be selected if there are more AZs in a region than - specified by AvailabilityZoneUsageLimit. There are 2 selection - schemes: Ordered - selects based on alphabetical order Random - - selects AZs randomly in a region Defaults to Ordered' - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: AvailabilityZoneUsageLimit specifies the maximum - number of availability zones (AZ) that should be used in - a region when automatically creating subnets. If a region - has more than this number of AZs then this number of AZs - will be picked randomly when creating default subnets. Defaults - to 3 - minimum: 1 - type: integer - cidrBlock: - description: CidrBlock is the CIDR block to be used when the - provider creates a managed VPC. Defaults to 10.0.0.0/16. - Mutually exclusive with IPAMPool. - 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 - ipamPool: - description: IPAMPool defines the IPAMv4 pool to be used for - VPC. Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this provider - should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool this provider - should use to create VPC. - type: string - netmaskLength: - description: The netmask length of the IPv4 CIDR you want - to allocate to VPC from an Amazon VPC IP Address Manager - (IPAM) pool. Defaults to /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - ipv6: - description: IPv6 contains ipv6 specific settings for the - network. Supported only in managed clusters. This field - cannot be set on AWSCluster object. - properties: - cidrBlock: - description: CidrBlock is the CIDR block provided by Amazon - when VPC has enabled IPv6. Mutually exclusive with IPAMPool. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the id of - the egress only internet gateway associated with an - IPv6 enabled VPC. - type: string - ipamPool: - description: IPAMPool defines the IPAMv6 pool to be used - for VPC. Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this provider - should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool this - provider should use to create VPC. - type: string - netmaskLength: - description: The netmask length of the IPv4 CIDR you - want to allocate to VPC from an Amazon VPC IP Address - Manager (IPAM) pool. Defaults to /16 for IPv4 if - not specified. - format: int64 - type: integer - type: object - poolId: - description: PoolID is the IP pool which must be defined - in case of BYO IP is defined. Must be specified if CidrBlock - is set. Mutually exclusive with IPAMPool. - type: string - type: object - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the resource. - type: object - type: object - type: object - partition: - description: Partition is the AWS security partition being used. Defaults - to "aws" - type: string - region: - description: The AWS Region the cluster lives in. + server: + description: Server is the address of the vSphere endpoint. type: string - s3Bucket: - description: S3Bucket contains options to configure a supporting S3 - bucket for this cluster - currently used for nodes requiring Ignition - (https://coreos.github.io/ignition/) for bootstrapping (requires - BootstrapFormatIgnition feature flag to be enabled). - properties: - controlPlaneIAMInstanceProfile: - description: ControlPlaneIAMInstanceProfile is a name of the IAMInstanceProfile, - which will be allowed to read control-plane node bootstrap data - from S3 Bucket. - type: string - name: - description: Name defines name of S3 Bucket to be created. - maxLength: 63 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ - type: string - nodesIAMInstanceProfiles: - description: NodesIAMInstanceProfiles is a list of IAM instance - profiles, which will be allowed to read worker nodes bootstrap - data from S3 Bucket. - items: - type: string - type: array - presignedURLDuration: - description: "PresignedURLDuration defines the duration for which - presigned URLs are valid. \n This is used to generate presigned - URLs for S3 Bucket objects, which are used by control-plane - and worker nodes to fetch bootstrap data. \n When enabled, the - IAM instance profiles specified are not used." - type: string - required: - - name - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - bastion host. Valid values are empty string (do not use SSH keys), - a valid SSH key name, or omitted (use the default SSH key name) + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate type: string type: object status: - description: AWSClusterStatus defines the observed state of AWSCluster. + description: VSphereClusterStatus defines the observed state of VSphereClusterSpec properties: - bastion: - description: Instance describes an AWS instance. - properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - availabilityZone: - description: Availability zone of instance - type: string - 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 - instanceMetadataOptions: - description: InstanceMetadataOptions is the metadata options for - the EC2 instance. - properties: - httpEndpoint: - default: enabled - description: "Enables or disables the HTTP metadata endpoint - on your instances. \n If you specify a value of disabled, - you cannot access your instance metadata. \n Default: enabled" - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: "The desired HTTP PUT response hop limit for - instance metadata requests. The larger the number, the further - instance metadata requests can travel. \n Default: 1" - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: "The state of token usage for your instance metadata - requests. \n If the state is optional, you can choose to - retrieve instance metadata with or without a session token - on your request. If you retrieve the IAM role credentials - without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session - token, the version 2.0 role credentials are returned. \n - If the state is required, you must send a session token - with any instance metadata retrieval requests. In this state, - retrieving the IAM role credentials always returns the version - 2.0 credentials; the version 1.0 credentials are not available. - \n Default: optional" - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: "Set to enabled to allow access to instance tags - from the instance metadata. Set to disabled to turn off - access to instance tags from the instance metadata. For - more information, see Work with instance tags using the - instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - \n Default: disabled" - enum: - - enabled - - disabled - type: string - type: object - instanceState: - description: The current state of the instance. - type: string - networkInterfaces: - description: Specifies ENIs attached to instance - items: - type: string - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for - the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by - the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size or - 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - placementGroupName: - description: PlacementGroupName specifies the name of the placement - group in which to launch the instance. - 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 - rootVolume: - description: Configuration options for the root storage volume. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by the - controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - securityGroupIds: - description: SecurityGroupIDs are one or more security group IDs - this instance belongs to. - items: - type: string - type: array - spotMarketOptions: - description: SpotMarketOptions option for configuring instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: The name of the SSH key pair. - type: string - 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 - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - type: string - 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 - volumeIDs: - description: IDs of the instance's volumes - items: - type: string - type: array - required: - - id - type: object conditions: - description: Conditions provide observations of the operational state - of a Cluster API resource. + description: Conditions defines current service state of the VSphereCluster. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -2410,329 +1231,15 @@ spec: is suitable for use by control plane machines. type: boolean type: object - description: FailureDomains is a slice of FailureDomains. - type: object - networkStatus: - description: NetworkStatus encapsulates AWS networking resources. - properties: - apiServerElb: - description: APIServerELB is the Kubernetes api server load balancer. - properties: - arn: - description: ARN of the load balancer. Unlike the ClassicLB, - ARN is used mostly to define and get it. - type: string - attributes: - description: ClassicElbAttributes defines extra attributes - associated with the load balancer. - properties: - crossZoneLoadBalancing: - description: CrossZoneLoadBalancing enables the classic - load balancer load balancing. - type: boolean - 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 - availabilityZones: - description: AvailabilityZones is an array of availability - zones in the VPC attached to the load balancer. - items: - type: string - type: array - dnsName: - description: DNSName is the dns name of the load balancer. - type: string - elbAttributes: - additionalProperties: - type: string - description: ELBAttributes defines extra attributes associated - with v2 load balancers. - type: object - elbListeners: - description: ELBListeners is an array of listeners associated - with the load balancer. There must be at least one. - items: - description: Listener defines an AWS network load balancer - listener. - properties: - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - targetGroup: - description: TargetGroupSpec specifies target group - settings for a given listener. This is created first, - and the ARN is then passed to the listener. - properties: - name: - description: Name of the TargetGroup. Must be unique - over the same group of listeners. - type: string - port: - description: Port is the exposed port - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - enum: - - tcp - - tls - - udp - - TCP - - TLS - - UDP - type: string - targetGroupHealthCheck: - description: HealthCheck is the elb health check - associated with the load balancer. - properties: - intervalSeconds: - format: int64 - type: integer - path: - type: string - port: - type: string - protocol: - type: string - thresholdCount: - format: int64 - type: integer - timeoutSeconds: - format: int64 - type: integer - type: object - vpcId: - type: string - required: - - name - - port - - protocol - - vpcId - type: object - required: - - port - - protocol - - targetGroup - type: object - type: array - 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: ClassicELBListeners 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: ELBProtocol defines listener protocols - for a load balancer. - type: string - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - required: - - instancePort - - instanceProtocol - - port - - protocol - type: object - type: array - loadBalancerType: - description: LoadBalancerType sets the type for a load balancer. - The default type is classic. - enum: - - classic - - elb - - alb - - nlb - type: string - 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 - natGatewaysIPs: - description: NatGatewaysIPs contains the public IPs of the NAT - Gateways - items: - type: string - type: array - 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: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP in - IP),"tcp", "udp", "icmp", and "58" (ICMPv6), "50" - (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: The security group role to allow access - from. Cannot be specified with CidrBlocks. The field - will be combined with source security group IDs - if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - 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 - - name - type: object - description: SecurityGroups is a map from the role/kind of the - security group to its unique name, if any. - type: object + description: FailureDomains is a list of failure domain objects synced + from the infrastructure provider. type: object ready: - default: false type: boolean - required: - - ready + vCenterVersion: + description: VCenterVersion defines the version of the vCenter server + defined in the spec. + type: string type: object type: object served: true @@ -2744,33 +1251,41 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert controller-gen.kubebuilder.io/version: v0.12.1 labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - clusterctl.cluster.x-k8s.io/move-hierarchy: "" - name: awsclusterstaticidentities.infrastructure.cluster.x-k8s.io + cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 + name: vsphereclustertemplates.infrastructure.cluster.x-k8s.io spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capv-webhook-service + namespace: capv-system + path: /convert + conversionReviewVersions: + - v1 + - v1beta1 group: infrastructure.cluster.x-k8s.io names: categories: - cluster-api - kind: AWSClusterStaticIdentity - listKind: AWSClusterStaticIdentityList - plural: awsclusterstaticidentities - shortNames: - - awssi - singular: awsclusterstaticidentity - scope: Cluster + kind: VSphereClusterTemplate + listKind: VSphereClusterTemplateList + plural: vsphereclustertemplates + singular: vsphereclustertemplate + scope: Namespaced versions: - - name: v1beta1 + - deprecated: true + name: v1alpha4 schema: openAPIV3Schema: - description: AWSClusterStaticIdentity is the Schema for the awsclusterstaticidentities - API It represents a reference to an AWS access key ID and secret access - key, stored in a secret. + description: "VSphereClusterTemplate is the Schema for the vsphereclustertemplates + API \n Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -2785,91 +1300,70 @@ spec: metadata: type: object spec: - description: Spec for this AWSClusterStaticIdentity + description: VSphereClusterTemplateSpec defines the desired state of VSphereClusterTemplate properties: - allowedNamespaces: - description: AllowedNamespaces is used to identify which namespaces - are allowed to use the identity from. Namespaces can be selected - either using an array of namespaces or with label selector. An empty - allowedNamespaces object indicates that AWSClusters can use this - identity from any namespace. If this object is nil, no namespaces - will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with - Selector to use the identity. - nullable: true + template: properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: An empty selector indicates that AWSClusters cannot - use this AWSClusterIdentity from any namespace. + spec: + description: VSphereClusterSpec defines the desired state of VSphereCluster properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that relates - the key and values. - properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, - Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. If - the operator is In or NotIn, the values array must - be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced - during a strategic merge patch. - items: - type: string - type: array - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. A - single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field is "key", - the operator is "In", and the values array contains only - "value". The requirements are ANDed. + controlPlaneEndpoint: + description: ControlPlaneEndpoint represents the endpoint + used to communicate with the control plane. + 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. + format: int32 + type: integer + required: + - host + - port + type: object + identityRef: + description: IdentityRef is a reference to either a Secret + or VSphereClusterIdentity that contains the identity to + use when reconciling the cluster. + properties: + kind: + description: Kind of the identity. Can either be VSphereClusterIdentity + or Secret + enum: + - VSphereClusterIdentity + - Secret + type: string + name: + description: Name of the identity. + minLength: 1 + type: string + required: + - kind + - name type: object + server: + description: Server is the address of the vSphere endpoint. + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum + of the given vCenter server's host certificate + type: string type: object - x-kubernetes-map-type: atomic + required: + - spec type: object - secretRef: - description: 'Reference to a secret containing the credentials. The - secret should contain the following data keys: AccessKeyID: AKIAIOSFODNN7EXAMPLE - SecretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY SessionToken: - Optional' - type: string required: - - secretRef + - template type: object type: object served: true storage: false - - name: v1beta2 + - name: v1beta1 schema: openAPIV3Schema: - description: AWSClusterStaticIdentity is the Schema for the awsclusterstaticidentities - API It represents a reference to an AWS access key ID and secret access - key, stored in a secret. + description: VSphereClusterTemplate is the Schema for the vsphereclustertemplates + API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -2884,81 +1378,144 @@ spec: metadata: type: object spec: - description: Spec for this AWSClusterStaticIdentity + description: VSphereClusterTemplateSpec defines the desired state of VSphereClusterTemplate properties: - allowedNamespaces: - description: AllowedNamespaces is used to identify which namespaces - are allowed to use the identity from. Namespaces can be selected - either using an array of namespaces or with label selector. An empty - allowedNamespaces object indicates that AWSClusters can use this - identity from any namespace. If this object is nil, no namespaces - will be allowed (default behaviour, if this field is not provided) - A namespace should be either in the NamespaceList or match with - Selector to use the identity. - nullable: true + template: properties: - list: - description: An nil or empty list indicates that AWSClusters cannot - use the identity from any namespace. - items: - type: string - nullable: true - type: array - selector: - description: An empty selector indicates that AWSClusters cannot - use this AWSClusterIdentity from any namespace. + spec: + description: VSphereClusterSpec defines the desired state of VSphereCluster properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. + clusterModules: + description: ClusterModules hosts information regarding the + anti-affinity vSphere constructs for each of the objects + responsible for creation of VM objects belonging to the + cluster. items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that relates - the key and values. + description: ClusterModule holds the anti affinity construct + `ClusterModule` identifier in use by the VMs owned by + the object referred by the TargetObjectName field. properties: - key: - description: key is the label key that the selector - applies to. + controlPlane: + description: ControlPlane indicates whether the referred + object is responsible for control plane nodes. Currently, + only the KubeadmControlPlane objects have this flag + set to true. Only a single object in the slice can + have this value set to true. + type: boolean + moduleUUID: + description: ModuleUUID is the unique identifier of + the `ClusterModule` used by the object. type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, NotIn, - Exists and DoesNotExist. + targetObjectName: + description: TargetObjectName points to the object that + uses the Cluster Module information to enforce anti-affinity + amongst its descendant VM objects. type: string - values: - description: values is an array of string values. If - the operator is In or NotIn, the values array must - be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced - during a strategic merge patch. - items: - type: string - type: array required: - - key - - operator + - controlPlane + - moduleUUID + - targetObjectName type: object type: array - matchLabels: - additionalProperties: - type: string - description: matchLabels is a map of {key,value} pairs. A - single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field is "key", - the operator is "In", and the values array contains only - "value". The requirements are ANDed. + controlPlaneEndpoint: + description: ControlPlaneEndpoint represents the endpoint + used to communicate with the control plane. + 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. + format: int32 + type: integer + required: + - host + - port + type: object + failureDomainSelector: + description: FailureDomainSelector is the label selector to + use for failure domain selection for the control plane nodes + of the cluster. If not set (`nil`), selecting failure domains + will be disabled. An empty value (`{}`) selects all existing + failure domains. A valid selector will select all failure + domains which match the selector. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists or + DoesNotExist, the values array must be empty. + This array is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + identityRef: + description: IdentityRef is a reference to either a Secret + or VSphereClusterIdentity that contains the identity to + use when reconciling the cluster. + properties: + kind: + description: Kind of the identity. Can either be VSphereClusterIdentity + or Secret + enum: + - VSphereClusterIdentity + - Secret + type: string + name: + description: Name of the identity. + minLength: 1 + type: string + required: + - kind + - name type: object + server: + description: Server is the address of the vSphere endpoint. + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum + of the given vCenter server's host certificate + type: string type: object - x-kubernetes-map-type: atomic + required: + - spec type: object - secretRef: - description: 'Reference to a secret containing the credentials. The - secret should contain the following data keys: AccessKeyID: AKIAIOSFODNN7EXAMPLE - SecretAccessKey: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY SessionToken: - Optional' - type: string required: - - secretRef + - template type: object type: object served: true @@ -2968,14 +1525,12 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert controller-gen.kubebuilder.io/version: v0.12.1 labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsclustertemplates.infrastructure.cluster.x-k8s.io + cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 + name: vspheredeploymentzones.infrastructure.cluster.x-k8s.io spec: conversion: strategy: Webhook @@ -2983,8 +1538,8 @@ spec: clientConfig: caBundle: Cg== service: - name: capa-webhook-service - namespace: capa-system + name: capv-webhook-service + namespace: capv-system path: /convert conversionReviewVersions: - v1 @@ -2993,24 +1548,18 @@ spec: names: categories: - cluster-api - kind: AWSClusterTemplate - listKind: AWSClusterTemplateList - plural: awsclustertemplates - shortNames: - - awsct - singular: awsclustertemplate - scope: Namespaced + kind: VSphereDeploymentZone + listKind: VSphereDeploymentZoneList + plural: vspheredeploymentzones + singular: vspheredeploymentzone + scope: Cluster versions: - - additionalPrinterColumns: - - description: Time duration since creation of AWSClusterTemplate - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta1 + - deprecated: true + name: v1alpha3 schema: openAPIV3Schema: - description: AWSClusterTemplate is the schema for Amazon EC2 based Kubernetes - Cluster Templates. + description: "VSphereDeploymentZone is the Schema for the vspheredeploymentzones + API \n Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -3025,2958 +1574,39 @@ spec: metadata: type: object spec: - description: AWSClusterTemplateSpec defines the desired state of AWSClusterTemplate. + description: VSphereDeploymentZoneSpec defines the desired state of VSphereDeploymentZone properties: - template: + controlPlane: + description: ControlPlane determines if this failure domain is suitable + for use by control plane machines. + type: boolean + failureDomain: + description: failureDomain is the name of the VSphereFailureDomain + used for this VSphereDeploymentZone + type: string + placementConstraint: + description: PlacementConstraint encapsulates the placement constraints + used within this deployment zone. properties: - metadata: - description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not queryable - and should be preserved when modifying objects. More info: - http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used - to organize and categorize (scope and select) objects. May - match selectors of replication controllers and services. - More info: http://kubernetes.io/docs/user-guide/labels' - type: object - type: object - spec: - description: AWSClusterSpec defines the desired state of an EC2-based - Kubernetes cluster. - properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to - add to AWS resources managed by the AWS provider, in addition - to the ones added by default. - type: object - bastion: - description: Bastion contains options to configure the bastion - host. - properties: - allowedCIDRBlocks: - description: AllowedCIDRBlocks is a list of CIDR blocks - allowed to access the bastion host. They are set as - ingress rules for the Bastion host's Security Group - (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: AMI will use the specified AMI to boot the - bastion. If not specified, the AMI will default to one - picked out in public space. - type: string - disableIngressRules: - description: DisableIngressRules will ensure there are - no Ingress rules in the bastion host's security group. - Requires AllowedCIDRBlocks to be empty. - type: boolean - enabled: - description: Enabled allows this provider to create a - bastion host instance with a public ip to access the - VPC private network. - type: boolean - instanceType: - description: InstanceType will use the specified instance - type for the bastion. If not specified, Cluster API - Provider AWS will use t3.micro for all regions except - us-east-1, where t2.micro will be the default. - type: string - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint - used to communicate with the control plane. - 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. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration - for customizing control plane behavior. - properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups sets the security - groups used by the load balancer. Expected to be security - group IDs This is optional - if not provided new security - groups will be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: "CrossZoneLoadBalancing enables the classic - ELB cross availability zone balancing. \n With cross-zone - load balancing, each load balancer node for your Classic - Load Balancer distributes requests evenly across the - registered instances in all enabled Availability Zones. - If cross-zone load balancing is disabled, each load - balancer node distributes requests evenly across the - registered instances in its Availability Zone only. - \n Defaults to false." - type: boolean - healthCheckProtocol: - description: HealthCheckProtocol sets the protocol type - for classic ELB health check target default value is - ClassicELBProtocolSSL - type: string - name: - description: Name sets the name of the classic ELB load - balancer. As per AWS, the name must be unique within - your set of load balancers for the region, must have - a maximum of 32 characters, must contain only alphanumeric - characters or hyphens, and cannot begin or end with - a hyphen. Once set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer - (defaults to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied - to the control plane load balancer (defaults to discovered - subnets for managed VPCs or an empty set for unmanaged - VPCs) - items: - type: string - type: array - type: object - identityRef: - description: IdentityRef is a reference to a identity to be - used when reconciling this cluster - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating - system used to look up machine images when a machine does - not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different - ImageLookupBaseOS. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to - look up machine images when a machine does not specify an - AMI. When set, this will be used for all cluster machines - unless a machine specifies a different ImageLookupOrg. Supports - substitutions for {{.BaseOS}} and {{.K8sVersion}} with the - base OS and kubernetes version, respectively. The BaseOS - will be the value in ImageLookupBaseOS or ubuntu (the default), - and the kubernetes version as defined by the packages produced - by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the - ubuntu base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to - look up machine images when a machine does not specify an - AMI. When set, this will be used for all cluster machines - unless a machine specifies a different ImageLookupOrg. - type: string - network: - description: NetworkSpec encapsulates all things related to - AWS network. - properties: - cni: - description: CNI configuration - properties: - cniIngressRules: - description: CNIIngressRules specify rules to apply - to control plane and worker node security groups. - The source for the rule will be set to control plane - and worker security group IDs. - items: - description: CNIIngressRule defines an AWS ingress - rule for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the - protocol type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: SecurityGroupOverrides is an optional set - of security groups to use for cluster instances This - is optional - if not provided new security groups will - be created for the cluster - type: object - 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 - ipv6CidrBlock: - description: IPv6CidrBlock is the IPv6 CIDR block - to be used when the provider creates a managed - VPC. A subnet can have an IPv4 and an IPv6 address. - IPv6 is only supported in managed clusters, this - field cannot be set on AWSCluster object. - type: string - isIpv6: - description: IsIPv6 defines the subnet as an IPv6 - subnet. A subnet is IPv6 when it is associated - with a VPC that has IPv6 enabled. IPv6 is only - supported in managed clusters, this field cannot - be set on AWSCluster object. - type: boolean - 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: - availabilityZoneSelection: - default: Ordered - description: 'AvailabilityZoneSelection specifies - how AZs should be selected if there are more AZs - in a region than specified by AvailabilityZoneUsageLimit. - There are 2 selection schemes: Ordered - selects - based on alphabetical order Random - selects AZs - randomly in a region Defaults to Ordered' - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: AvailabilityZoneUsageLimit specifies - the maximum number of availability zones (AZ) that - should be used in a region when automatically creating - subnets. If a region has more than this number of - AZs then this number of AZs will be picked randomly - when creating default subnets. Defaults to 3 - minimum: 1 - type: integer - 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 - ipv6: - description: IPv6 contains ipv6 specific settings - for the network. Supported only in managed clusters. - This field cannot be set on AWSCluster object. - properties: - cidrBlock: - description: CidrBlock is the CIDR block provided - by Amazon when VPC has enabled IPv6. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the - id of the egress only internet gateway associated - with an IPv6 enabled VPC. - type: string - poolId: - description: PoolID is the IP pool which must - be defined in case of BYO IP is defined. - type: string - type: object - 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 - s3Bucket: - description: S3Bucket contains options to configure a supporting - S3 bucket for this cluster - currently used for nodes requiring - Ignition (https://coreos.github.io/ignition/) for bootstrapping - (requires BootstrapFormatIgnition feature flag to be enabled). - properties: - controlPlaneIAMInstanceProfile: - description: ControlPlaneIAMInstanceProfile is a name - of the IAMInstanceProfile, which will be allowed to - read control-plane node bootstrap data from S3 Bucket. - type: string - name: - description: Name defines name of S3 Bucket to be created. - maxLength: 63 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ - type: string - nodesIAMInstanceProfiles: - description: NodesIAMInstanceProfiles is a list of IAM - instance profiles, which will be allowed to read worker - nodes bootstrap data from S3 Bucket. - items: - type: string - type: array - required: - - controlPlaneIAMInstanceProfile - - name - - nodesIAMInstanceProfiles - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach - to the bastion host. Valid values are empty string (do not - use SSH keys), a valid SSH key name, or omitted (use the - default SSH key name) - type: string - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: false - subresources: {} - - additionalPrinterColumns: - - description: Time duration since creation of AWSClusterTemplate - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1beta2 - schema: - openAPIV3Schema: - description: AWSClusterTemplate is the schema for Amazon EC2 based Kubernetes - Cluster Templates. - 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: AWSClusterTemplateSpec defines the desired state of AWSClusterTemplate. - properties: - template: - properties: - metadata: - description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not queryable - and should be preserved when modifying objects. More info: - http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used - to organize and categorize (scope and select) objects. May - match selectors of replication controllers and services. - More info: http://kubernetes.io/docs/user-guide/labels' - type: object - type: object - spec: - description: AWSClusterSpec defines the desired state of an EC2-based - Kubernetes cluster. - properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to - add to AWS resources managed by the AWS provider, in addition - to the ones added by default. - type: object - bastion: - description: Bastion contains options to configure the bastion - host. - properties: - allowedCIDRBlocks: - description: AllowedCIDRBlocks is a list of CIDR blocks - allowed to access the bastion host. They are set as - ingress rules for the Bastion host's Security Group - (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: AMI will use the specified AMI to boot the - bastion. If not specified, the AMI will default to one - picked out in public space. - type: string - disableIngressRules: - description: DisableIngressRules will ensure there are - no Ingress rules in the bastion host's security group. - Requires AllowedCIDRBlocks to be empty. - type: boolean - enabled: - description: Enabled allows this provider to create a - bastion host instance with a public ip to access the - VPC private network. - type: boolean - instanceType: - description: InstanceType will use the specified instance - type for the bastion. If not specified, Cluster API - Provider AWS will use t3.micro for all regions except - us-east-1, where t2.micro will be the default. - type: string - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint - used to communicate with the control plane. - 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. - format: int32 - type: integer - required: - - host - - port - type: object - controlPlaneLoadBalancer: - description: ControlPlaneLoadBalancer is optional configuration - for customizing control plane behavior. - properties: - additionalListeners: - description: AdditionalListeners sets the additional listeners - for the control plane load balancer. This is only applicable - to Network Load Balancer (NLB) types for the time being. - items: - description: AdditionalListenerSpec defines the desired - state of an additional listener on an AWS load balancer. - properties: - port: - description: Port sets the port for the additional - listener. - format: int64 - type: integer - protocol: - description: Protocol sets the protocol for the - additional listener. Currently only TCP is supported. - enum: - - TCP - type: string - required: - - port - - protocol - type: object - type: array - additionalSecurityGroups: - description: AdditionalSecurityGroups sets the security - groups used by the load balancer. Expected to be security - group IDs This is optional - if not provided new security - groups will be created for the load balancer - items: - type: string - type: array - crossZoneLoadBalancing: - description: "CrossZoneLoadBalancing enables the classic - ELB cross availability zone balancing. \n With cross-zone - load balancing, each load balancer node for your Classic - Load Balancer distributes requests evenly across the - registered instances in all enabled Availability Zones. - If cross-zone load balancing is disabled, each load - balancer node distributes requests evenly across the - registered instances in its Availability Zone only. - \n Defaults to false." - type: boolean - disableHostsRewrite: - description: DisableHostsRewrite disabled the hair pinning - issue solution that adds the NLB's address as 127.0.0.1 - to the hosts file of each instance. This is by default, - false. - type: boolean - healthCheckProtocol: - description: HealthCheckProtocol sets the protocol type - for ELB health check target default value is ELBProtocolSSL - enum: - - TCP - - SSL - - HTTP - - HTTPS - - TLS - - UDP - type: string - ingressRules: - description: IngressRules sets the ingress rules for the - control plane load balancer. - 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: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP - in IP),"tcp", "udp", "icmp", and "58" (ICMPv6), - "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: The security group role to allow access - from. Cannot be specified with CidrBlocks. The - field will be combined with source security group - IDs if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - loadBalancerType: - default: classic - description: LoadBalancerType sets the type for a load - balancer. The default type is classic. - enum: - - classic - - elb - - alb - - nlb - type: string - name: - description: Name sets the name of the classic ELB load - balancer. As per AWS, the name must be unique within - your set of load balancers for the region, must have - a maximum of 32 characters, must contain only alphanumeric - characters or hyphens, and cannot begin or end with - a hyphen. Once set, the value cannot be changed. - maxLength: 32 - pattern: ^[A-Za-z0-9]([A-Za-z0-9]{0,31}|[-A-Za-z0-9]{0,30}[A-Za-z0-9])$ - type: string - preserveClientIP: - description: PreserveClientIP lets the user control if - preservation of client ips must be retained or not. - If this is enabled 6443 will be opened to 0.0.0.0/0. - type: boolean - scheme: - default: internet-facing - description: Scheme sets the scheme of the load balancer - (defaults to internet-facing) - enum: - - internet-facing - - internal - type: string - subnets: - description: Subnets sets the subnets that should be applied - to the control plane load balancer (defaults to discovered - subnets for managed VPCs or an empty set for unmanaged - VPCs) - items: - type: string - type: array - type: object - identityRef: - description: IdentityRef is a reference to a identity to be - used when reconciling this cluster - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating - system used to look up machine images when a machine does - not specify an AMI. When set, this will be used for all - cluster machines unless a machine specifies a different - ImageLookupBaseOS. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to - look up machine images when a machine does not specify an - AMI. When set, this will be used for all cluster machines - unless a machine specifies a different ImageLookupOrg. Supports - substitutions for {{.BaseOS}} and {{.K8sVersion}} with the - base OS and kubernetes version, respectively. The BaseOS - will be the value in ImageLookupBaseOS or ubuntu (the default), - and the kubernetes version as defined by the packages produced - by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the - ubuntu base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to - look up machine images when a machine does not specify an - AMI. When set, this will be used for all cluster machines - unless a machine specifies a different ImageLookupOrg. - type: string - network: - description: NetworkSpec encapsulates all things related to - AWS network. - properties: - additionalControlPlaneIngressRules: - description: AdditionalControlPlaneIngressRules is an - optional set of ingress rules to add to the control - plane - 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: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP - in IP),"tcp", "udp", "icmp", and "58" (ICMPv6), - "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: The security group role to allow access - from. Cannot be specified with CidrBlocks. The - field will be combined with source security group - IDs if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - cni: - description: CNI configuration - properties: - cniIngressRules: - description: CNIIngressRules specify rules to apply - to control plane and worker node security groups. - The source for the rule will be set to control plane - and worker security group IDs. - items: - description: CNIIngressRule defines an AWS ingress - rule for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the - protocol type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: SecurityGroupOverrides is an optional set - of security groups to use for cluster instances This - is optional - if not provided new security groups will - be created for the cluster - type: object - 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. If you're bringing your - subnet, set the AWS subnet-id here, it must start - with `subnet-`. \n When the VPC is managed by - CAPA, and you'd like the provider to create a - subnet for you, the id can be set to any placeholder - value that does not start with `subnet-`; upon - creation, the subnet AWS identifier will be populated - in the `ResourceID` field and the `id` field is - going to be used as the subnet name. If you specify - a tag called `Name`, it takes precedence." - type: string - ipv6CidrBlock: - description: IPv6CidrBlock is the IPv6 CIDR block - to be used when the provider creates a managed - VPC. A subnet can have an IPv4 and an IPv6 address. - IPv6 is only supported in managed clusters, this - field cannot be set on AWSCluster object. - type: string - isIpv6: - description: IsIPv6 defines the subnet as an IPv6 - subnet. A subnet is IPv6 when it is associated - with a VPC that has IPv6 enabled. IPv6 is only - supported in managed clusters, this field cannot - be set on AWSCluster object. - type: boolean - 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 - resourceID: - description: ResourceID is the subnet identifier - from AWS, READ ONLY. This field is populated when - the provider manages the 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 - required: - - id - type: object - type: array - x-kubernetes-list-map-keys: - - id - x-kubernetes-list-type: map - vpc: - description: VPC configuration. - properties: - availabilityZoneSelection: - default: Ordered - description: 'AvailabilityZoneSelection specifies - how AZs should be selected if there are more AZs - in a region than specified by AvailabilityZoneUsageLimit. - There are 2 selection schemes: Ordered - selects - based on alphabetical order Random - selects AZs - randomly in a region Defaults to Ordered' - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: AvailabilityZoneUsageLimit specifies - the maximum number of availability zones (AZ) that - should be used in a region when automatically creating - subnets. If a region has more than this number of - AZs then this number of AZs will be picked randomly - when creating default subnets. Defaults to 3 - minimum: 1 - type: integer - cidrBlock: - description: CidrBlock is the CIDR block to be used - when the provider creates a managed VPC. Defaults - to 10.0.0.0/16. Mutually exclusive with IPAMPool. - 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 - ipamPool: - description: IPAMPool defines the IPAMv4 pool to be - used for VPC. Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this - provider should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool - this provider should use to create VPC. - type: string - netmaskLength: - description: The netmask length of the IPv4 CIDR - you want to allocate to VPC from an Amazon VPC - IP Address Manager (IPAM) pool. Defaults to - /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - ipv6: - description: IPv6 contains ipv6 specific settings - for the network. Supported only in managed clusters. - This field cannot be set on AWSCluster object. - properties: - cidrBlock: - description: CidrBlock is the CIDR block provided - by Amazon when VPC has enabled IPv6. Mutually - exclusive with IPAMPool. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the - id of the egress only internet gateway associated - with an IPv6 enabled VPC. - type: string - ipamPool: - description: IPAMPool defines the IPAMv6 pool - to be used for VPC. Mutually exclusive with - CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool - this provider should use to create VPC. - type: string - name: - description: Name is the name of the IPAM - pool this provider should use to create - VPC. - type: string - netmaskLength: - description: The netmask length of the IPv4 - CIDR you want to allocate to VPC from an - Amazon VPC IP Address Manager (IPAM) pool. - Defaults to /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - poolId: - description: PoolID is the IP pool which must - be defined in case of BYO IP is defined. Must - be specified if CidrBlock is set. Mutually exclusive - with IPAMPool. - type: string - type: object - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing - the resource. - type: object - type: object - type: object - partition: - description: Partition is the AWS security partition being - used. Defaults to "aws" - type: string - region: - description: The AWS Region the cluster lives in. - type: string - s3Bucket: - description: S3Bucket contains options to configure a supporting - S3 bucket for this cluster - currently used for nodes requiring - Ignition (https://coreos.github.io/ignition/) for bootstrapping - (requires BootstrapFormatIgnition feature flag to be enabled). - properties: - controlPlaneIAMInstanceProfile: - description: ControlPlaneIAMInstanceProfile is a name - of the IAMInstanceProfile, which will be allowed to - read control-plane node bootstrap data from S3 Bucket. - type: string - name: - description: Name defines name of S3 Bucket to be created. - maxLength: 63 - minLength: 3 - pattern: ^[a-z0-9][a-z0-9.-]{1,61}[a-z0-9]$ - type: string - nodesIAMInstanceProfiles: - description: NodesIAMInstanceProfiles is a list of IAM - instance profiles, which will be allowed to read worker - nodes bootstrap data from S3 Bucket. - items: - type: string - type: array - presignedURLDuration: - description: "PresignedURLDuration defines the duration - for which presigned URLs are valid. \n This is used - to generate presigned URLs for S3 Bucket objects, which - are used by control-plane and worker nodes to fetch - bootstrap data. \n When enabled, the IAM instance profiles - specified are not used." - type: string - required: - - name - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach - to the bastion host. Valid values are empty string (do not - use SSH keys), a valid SSH key name, or omitted (use the - default SSH key name) - type: string - type: object - required: - - spec - type: object - required: - - template - type: object - type: object - served: true - storage: true - subresources: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsfargateprofiles.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSFargateProfile - listKind: AWSFargateProfileList - plural: awsfargateprofiles - shortNames: - - awsfp - singular: awsfargateprofile - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: AWSFargateProfile ready status - jsonPath: .status.ready - name: Ready - type: string - - description: EKS Fargate profile name - jsonPath: .spec.profileName - name: ProfileName - type: string - - description: Failure reason - jsonPath: .status.failureReason - name: FailureReason - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSFargateProfile is the Schema for the awsfargateprofiles 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: FargateProfileSpec defines the desired state of FargateProfile. - properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to AWS - resources managed by the AWS provider, in addition to the ones added - by default. - type: object - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - profileName: - description: ProfileName specifies the profile name. - type: string - roleName: - description: RoleName specifies the name of IAM role for this fargate - pool If the role is pre-existing we will treat it as unmanaged and - not delete it on deletion. If the EKSEnableIAM feature flag is true - and no name is supplied then a role is created. - type: string - selectors: - description: Selectors specify fargate pod selectors. - items: - description: FargateSelector specifies a selector for pods that - should run on this fargate pool. - properties: - labels: - additionalProperties: - type: string - description: Labels specifies which pod labels this selector - should match. - type: object - namespace: - description: Namespace specifies which namespace this selector - should match. - type: string - type: object - type: array - subnetIDs: - description: SubnetIDs specifies which subnets are used for the auto - scaling group of this nodegroup. - items: - type: string - type: array - required: - - clusterName - type: object - status: - description: FargateProfileStatus defines the observed state of FargateProfile. - properties: - conditions: - description: Conditions defines current state of the Fargate profile. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. This should be when the underlying condition changed. - If that is not known, then using the time when the API field - changed is acceptable. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. This field may be empty. - type: string - reason: - description: The reason for the condition's last transition - in CamelCase. The specific API may choose whether or not this - field is considered a guaranteed API. This field may not be - empty. - type: string - severity: - description: Severity provides an explicit classification of - Reason code, so the users or machines can immediately understand - the current situation and act accordingly. The Severity field - MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the FargateProfile and will contain - a more verbose string suitable for logging and human consumption. - \n This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the FargateProfile's spec or the configuration of the - controller, and that manual intervention is required. Examples of - terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the responsible - controller itself being critically misconfigured. \n Any transient - errors that occur during the reconciliation of FargateProfiles can - be added as events to the FargateProfile object and/or logged in - the controller's output." - type: string - failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the FargateProfile and will contain - a succinct value suitable for machine interpretation. \n This field - should not be set for transitive errors that a controller faces - that are expected to be fixed automatically over time (like service - outages), but instead indicate that something is fundamentally wrong - with the FargateProfile's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of FargateProfiles can be added - as events to the FargateProfile object and/or logged in the controller's - output." - type: string - ready: - default: false - description: Ready denotes that the FargateProfile is available. - type: boolean - required: - - ready - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: AWSFargateProfile ready status - jsonPath: .status.ready - name: Ready - type: string - - description: EKS Fargate profile name - jsonPath: .spec.profileName - name: ProfileName - type: string - - description: Failure reason - jsonPath: .status.failureReason - name: FailureReason - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: AWSFargateProfile is the Schema for the awsfargateprofiles 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: FargateProfileSpec defines the desired state of FargateProfile. - properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to AWS - resources managed by the AWS provider, in addition to the ones added - by default. - type: object - clusterName: - description: ClusterName is the name of the Cluster this object belongs - to. - minLength: 1 - type: string - profileName: - description: ProfileName specifies the profile name. - type: string - roleName: - description: RoleName specifies the name of IAM role for this fargate - pool If the role is pre-existing we will treat it as unmanaged and - not delete it on deletion. If the EKSEnableIAM feature flag is true - and no name is supplied then a role is created. - type: string - selectors: - description: Selectors specify fargate pod selectors. - items: - description: FargateSelector specifies a selector for pods that - should run on this fargate pool. - properties: - labels: - additionalProperties: - type: string - description: Labels specifies which pod labels this selector - should match. - type: object - namespace: - description: Namespace specifies which namespace this selector - should match. - type: string - type: object - type: array - subnetIDs: - description: SubnetIDs specifies which subnets are used for the auto - scaling group of this nodegroup. - items: - type: string - type: array - required: - - clusterName - type: object - status: - description: FargateProfileStatus defines the observed state of FargateProfile. - properties: - conditions: - description: Conditions defines current state of the Fargate profile. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. This should be when the underlying condition changed. - If that is not known, then using the time when the API field - changed is acceptable. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. This field may be empty. - type: string - reason: - description: The reason for the condition's last transition - in CamelCase. The specific API may choose whether or not this - field is considered a guaranteed API. This field may not be - empty. - type: string - severity: - description: Severity provides an explicit classification of - Reason code, so the users or machines can immediately understand - the current situation and act accordingly. The Severity field - MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the FargateProfile and will contain - a more verbose string suitable for logging and human consumption. - \n This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the FargateProfile's spec or the configuration of the - controller, and that manual intervention is required. Examples of - terminal errors would be invalid combinations of settings in the - spec, values that are unsupported by the controller, or the responsible - controller itself being critically misconfigured. \n Any transient - errors that occur during the reconciliation of FargateProfiles can - be added as events to the FargateProfile object and/or logged in - the controller's output." - type: string - failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the FargateProfile and will contain - a succinct value suitable for machine interpretation. \n This field - should not be set for transitive errors that a controller faces - that are expected to be fixed automatically over time (like service - outages), but instead indicate that something is fundamentally wrong - with the FargateProfile's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of FargateProfiles can be added - as events to the FargateProfile object and/or logged in the controller's - output." - type: string - ready: - default: false - description: Ready denotes that the FargateProfile is available. - type: boolean - required: - - ready - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsmachinepools.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSMachinePool - listKind: AWSMachinePoolList - plural: awsmachinepools - shortNames: - - awsmp - singular: awsmachinepool - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: Machine ready status - jsonPath: .status.replicas - name: Replicas - type: integer - - description: Minimum instanes in ASG - jsonPath: .spec.minSize - name: MinSize - type: integer - - description: Maximum instanes in ASG - jsonPath: .spec.maxSize - name: MaxSize - type: integer - - description: Launch Template ID - jsonPath: .status.launchTemplateID - name: LaunchTemplate ID - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSMachinePool is the Schema for the awsmachinepools 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: AWSMachinePoolSpec defines the desired state of AWSMachinePool. - properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to an - instance, in addition to the ones added by default by the AWS provider. - type: object - availabilityZones: - description: AvailabilityZones is an array of availability zones instances - can run in - items: - type: string - type: array - awsLaunchTemplate: - description: AWSLaunchTemplate specifies the launch template and version - to use when an instance is launched. - properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups is an array of references - to security groups that should be applied to the instances. - These security groups would be set in addition to any security - groups defined at the cluster level or in the actuator. - items: - description: AWSResourceReference is a reference to a specific - AWS resource by ID or filters. Only one of ID or Filters may - be specified. Specifying more than one will result in a validation - error. - properties: - filters: - description: 'Filters is a set of key/value pairs used to - identify a resource They are applied according to the - rules defined by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS - resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look - up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - iamInstanceProfile: - description: The name or the Amazon Resource Name (ARN) of the - instance profile associated with the IAM role for the instance. - The instance profile contains the IAM role. - type: string - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating - system to use for image lookup the AMI is not set. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look - up the image for this machine It will be ignored if an explicit - AMI is set. Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} - with the base OS and kubernetes version, respectively. The BaseOS - will be the value in ImageLookupBaseOS or ubuntu (the default), - and the kubernetes version as defined by the packages produced - by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use - for image lookup if AMI is not set. - type: string - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - type: string - name: - description: The name of the launch template. - type: string - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by the - controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions are options for configuring AWSMachinePool - instances to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to - the instance. Valid values are empty string (do not use SSH - keys), a valid SSH key name, or omitted (use the default SSH - key name) - type: string - versionNumber: - description: 'VersionNumber is the version of the launch template - that is applied. Typically a new version is created when at - least one of the following happens: 1) A new launch template - spec is applied. 2) One or more parameters in an existing template - is changed. 3) A new AMI is discovered.' - format: int64 - type: integer - type: object - capacityRebalance: - description: Enable or disable the capacity rebalance autoscaling - group feature - type: boolean - defaultCoolDown: - description: The amount of time, in seconds, after a scaling activity - completes before another scaling activity can start. If no value - is supplied by user a default value of 300 seconds is set - type: string - maxSize: - default: 1 - description: MaxSize defines the maximum size of the group. - format: int32 - minimum: 1 - type: integer - minSize: - default: 1 - description: MinSize defines the minimum size of the group. - format: int32 - minimum: 0 - type: integer - mixedInstancesPolicy: - description: MixedInstancesPolicy describes how multiple instance - types will be used by the ASG. - properties: - instancesDistribution: - description: InstancesDistribution to configure distribution of - On-Demand Instances and Spot Instances. - properties: - onDemandAllocationStrategy: - default: prioritized - description: OnDemandAllocationStrategy indicates how to allocate - instance types to fulfill On-Demand capacity. - enum: - - prioritized - type: string - onDemandBaseCapacity: - default: 0 - format: int64 - type: integer - onDemandPercentageAboveBaseCapacity: - default: 100 - format: int64 - type: integer - spotAllocationStrategy: - default: lowest-price - description: SpotAllocationStrategy indicates how to allocate - instances across Spot Instance pools. - enum: - - lowest-price - - capacity-optimized - type: string - type: object - overrides: - items: - description: Overrides are used to override the instance type - specified by the launch template with multiple instance types - that can be used to launch On-Demand Instances and Spot Instances. - properties: - instanceType: - type: string - required: - - instanceType - type: object - type: array - type: object - providerID: - description: ProviderID is the ARN of the associated ASG - type: string - providerIDList: - description: ProviderIDList are the identification IDs of machine - instances provided by the provider. This field must match the provider - IDs as seen on the node objects corresponding to a machine pool's - machine instances. - items: - type: string - type: array - refreshPreferences: - description: RefreshPreferences describes set of preferences associated - with the instance refresh request. - properties: - instanceWarmup: - description: The number of seconds until a newly launched instance - is configured and ready to use. During this time, the next replacement - will not be initiated. The default is to use the value for the - health check grace period defined for the group. - format: int64 - type: integer - minHealthyPercentage: - description: The amount of capacity as a percentage in ASG that - must remain healthy during an instance refresh. The default - is 90. - format: int64 - type: integer - strategy: - description: The strategy to use for the instance refresh. The - only valid value is Rolling. A rolling update is an update that - is applied to all instances in an Auto Scaling group until all - instances have been updated. - type: string - type: object - subnets: - description: Subnets is an array of subnet configurations - items: - description: AWSResourceReference is a reference to a specific AWS - resource by ID or filters. Only one of ID or Filters may be specified. - Specifying more than one will result in a validation error. - properties: - filters: - description: 'Filters is a set of key/value pairs used to identify - a resource They are applied according to the rules defined - by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - required: - - awsLaunchTemplate - - maxSize - - minSize - type: object - status: - description: AWSMachinePoolStatus defines the observed state of AWSMachinePool. - properties: - asgStatus: - description: ASGStatus is a status string returned by the autoscaling - API. - type: string - conditions: - description: Conditions defines current service state of the AWSMachinePool. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. This should be when the underlying condition changed. - If that is not known, then using the time when the API field - changed is acceptable. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. This field may be empty. - type: string - reason: - description: The reason for the condition's last transition - in CamelCase. The specific API may choose whether or not this - field is considered a guaranteed API. This field may not be - empty. - type: string - severity: - description: Severity provides an explicit classification of - Reason code, so the users or machines can immediately understand - the current situation and act accordingly. The Severity field - MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the Machine and will contain a more - verbose string suitable for logging and human consumption. \n This - field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of Machines can be added as events - to the Machine object and/or logged in the controller's output." - type: string - failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the Machine and will contain a succinct - value suitable for machine interpretation. \n This field should - not be set for transitive errors that a controller faces that are - expected to be fixed automatically over time (like service outages), - but instead indicate that something is fundamentally wrong with - the Machine's spec or the configuration of the controller, and that - manual intervention is required. Examples of terminal errors would - be invalid combinations of settings in the spec, values that are - unsupported by the controller, or the responsible controller itself - being critically misconfigured. \n Any transient errors that occur - during the reconciliation of Machines can be added as events to - the Machine object and/or logged in the controller's output." - type: string - instances: - description: Instances contains the status for each instance in the - pool - items: - description: AWSMachinePoolInstanceStatus defines the status of - the AWSMachinePoolInstance. - properties: - instanceID: - description: InstanceID is the identification of the Machine - Instance within ASG - type: string - version: - description: Version defines the Kubernetes version for the - Machine Instance - type: string - type: object - type: array - launchTemplateID: - description: The ID of the launch template - type: string - launchTemplateVersion: - description: The version of the launch template - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - replicas: - description: Replicas is the most recently observed number of replicas - format: int32 - type: integer - type: object - type: object - served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: Machine ready status - jsonPath: .status.replicas - name: Replicas - type: integer - - description: Minimum instanes in ASG - jsonPath: .spec.minSize - name: MinSize - type: integer - - description: Maximum instanes in ASG - jsonPath: .spec.maxSize - name: MaxSize - type: integer - - description: Launch Template ID - jsonPath: .status.launchTemplateID - name: LaunchTemplate ID - type: string - name: v1beta2 - schema: - openAPIV3Schema: - description: AWSMachinePool is the Schema for the awsmachinepools 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: AWSMachinePoolSpec defines the desired state of AWSMachinePool. - properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to an - instance, in addition to the ones added by default by the AWS provider. - type: object - availabilityZoneSubnetType: - description: AvailabilityZoneSubnetType specifies which type of subnets - to use when an availability zone is specified. - enum: - - public - - private - - all - type: string - availabilityZones: - description: AvailabilityZones is an array of availability zones instances - can run in - items: - type: string - type: array - awsLaunchTemplate: - description: AWSLaunchTemplate specifies the launch template and version - to use when an instance is launched. - properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups is an array of references - to security groups that should be applied to the instances. - These security groups would be set in addition to any security - groups defined at the cluster level or in the actuator. - items: - description: AWSResourceReference is a reference to a specific - AWS resource by ID or filters. Only one of ID or Filters may - be specified. Specifying more than one will result in a validation - error. - properties: - filters: - description: 'Filters is a set of key/value pairs used to - identify a resource They are applied according to the - rules defined by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS - resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look - up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - iamInstanceProfile: - description: The name or the Amazon Resource Name (ARN) of the - instance profile associated with the IAM role for the instance. - The instance profile contains the IAM role. - type: string - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating - system to use for image lookup the AMI is not set. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look - up the image for this machine It will be ignored if an explicit - AMI is set. Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} - with the base OS and kubernetes version, respectively. The BaseOS - will be the value in ImageLookupBaseOS or ubuntu (the default), - and the kubernetes version as defined by the packages produced - by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use - for image lookup if AMI is not set. - type: string - instanceMetadataOptions: - description: InstanceMetadataOptions defines the behavior for - applying metadata to instances. - properties: - httpEndpoint: - default: enabled - description: "Enables or disables the HTTP metadata endpoint - on your instances. \n If you specify a value of disabled, - you cannot access your instance metadata. \n Default: enabled" - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: "The desired HTTP PUT response hop limit for - instance metadata requests. The larger the number, the further - instance metadata requests can travel. \n Default: 1" - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: "The state of token usage for your instance metadata - requests. \n If the state is optional, you can choose to - retrieve instance metadata with or without a session token - on your request. If you retrieve the IAM role credentials - without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session - token, the version 2.0 role credentials are returned. \n - If the state is required, you must send a session token - with any instance metadata retrieval requests. In this state, - retrieving the IAM role credentials always returns the version - 2.0 credentials; the version 1.0 credentials are not available. - \n Default: optional" - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: "Set to enabled to allow access to instance tags - from the instance metadata. Set to disabled to turn off - access to instance tags from the instance metadata. For - more information, see Work with instance tags using the - instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - \n Default: disabled" - enum: - - enabled - - disabled - type: string - type: object - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - type: string - name: - description: The name of the launch template. - type: string - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by the - controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions are options for configuring AWSMachinePool - instances to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to - the instance. Valid values are empty string (do not use SSH - keys), a valid SSH key name, or omitted (use the default SSH - key name) - type: string - versionNumber: - description: 'VersionNumber is the version of the launch template - that is applied. Typically a new version is created when at - least one of the following happens: 1) A new launch template - spec is applied. 2) One or more parameters in an existing template - is changed. 3) A new AMI is discovered.' - format: int64 - type: integer - type: object - capacityRebalance: - description: Enable or disable the capacity rebalance autoscaling - group feature - type: boolean - defaultCoolDown: - description: The amount of time, in seconds, after a scaling activity - completes before another scaling activity can start. If no value - is supplied by user a default value of 300 seconds is set - type: string - maxSize: - default: 1 - description: MaxSize defines the maximum size of the group. - format: int32 - minimum: 1 - type: integer - minSize: - default: 1 - description: MinSize defines the minimum size of the group. - format: int32 - minimum: 0 - type: integer - mixedInstancesPolicy: - description: MixedInstancesPolicy describes how multiple instance - types will be used by the ASG. - properties: - instancesDistribution: - description: InstancesDistribution to configure distribution of - On-Demand Instances and Spot Instances. - properties: - onDemandAllocationStrategy: - default: prioritized - description: OnDemandAllocationStrategy indicates how to allocate - instance types to fulfill On-Demand capacity. - enum: - - prioritized - - lowest-price - type: string - onDemandBaseCapacity: - default: 0 - format: int64 - type: integer - onDemandPercentageAboveBaseCapacity: - default: 100 - format: int64 - type: integer - spotAllocationStrategy: - default: lowest-price - description: SpotAllocationStrategy indicates how to allocate - instances across Spot Instance pools. - enum: - - lowest-price - - capacity-optimized - - capacity-optimized-prioritized - - price-capacity-optimized - type: string - type: object - overrides: - items: - description: Overrides are used to override the instance type - specified by the launch template with multiple instance types - that can be used to launch On-Demand Instances and Spot Instances. - properties: - instanceType: - type: string - required: - - instanceType - type: object - type: array - type: object - providerID: - description: ProviderID is the ARN of the associated ASG - type: string - providerIDList: - description: ProviderIDList are the identification IDs of machine - instances provided by the provider. This field must match the provider - IDs as seen on the node objects corresponding to a machine pool's - machine instances. - items: - type: string - type: array - refreshPreferences: - description: RefreshPreferences describes set of preferences associated - with the instance refresh request. - properties: - disable: - description: Disable, if true, disables instance refresh from - triggering when new launch templates are detected. This is useful - in scenarios where ASG nodes are externally managed. - type: boolean - instanceWarmup: - description: The number of seconds until a newly launched instance - is configured and ready to use. During this time, the next replacement - will not be initiated. The default is to use the value for the - health check grace period defined for the group. - format: int64 - type: integer - minHealthyPercentage: - description: The amount of capacity as a percentage in ASG that - must remain healthy during an instance refresh. The default - is 90. - format: int64 - type: integer - strategy: - description: The strategy to use for the instance refresh. The - only valid value is Rolling. A rolling update is an update that - is applied to all instances in an Auto Scaling group until all - instances have been updated. - type: string - type: object - subnets: - description: Subnets is an array of subnet configurations - items: - description: AWSResourceReference is a reference to a specific AWS - resource by ID or filters. Only one of ID or Filters may be specified. - Specifying more than one will result in a validation error. - properties: - filters: - description: 'Filters is a set of key/value pairs used to identify - a resource They are applied according to the rules defined - by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - suspendProcesses: - description: SuspendProcesses defines a list of processes to suspend - for the given ASG. This is constantly reconciled. If a process is - removed from this list it will automatically be resumed. - properties: - all: - type: boolean - processes: - description: Processes defines the processes which can be enabled - or disabled individually. - properties: - addToLoadBalancer: - type: boolean - alarmNotification: - type: boolean - azRebalance: - type: boolean - healthCheck: - type: boolean - instanceRefresh: - type: boolean - launch: - type: boolean - replaceUnhealthy: - type: boolean - scheduledActions: - type: boolean - terminate: - type: boolean - type: object - type: object - required: - - awsLaunchTemplate - - maxSize - - minSize - type: object - status: - description: AWSMachinePoolStatus defines the observed state of AWSMachinePool. - properties: - asgStatus: - description: ASGStatus is a status string returned by the autoscaling - API. - type: string - conditions: - description: Conditions defines current service state of the AWSMachinePool. - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. This should be when the underlying condition changed. - If that is not known, then using the time when the API field - changed is acceptable. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. This field may be empty. - type: string - reason: - description: The reason for the condition's last transition - in CamelCase. The specific API may choose whether or not this - field is considered a guaranteed API. This field may not be - empty. - type: string - severity: - description: Severity provides an explicit classification of - Reason code, so the users or machines can immediately understand - the current situation and act accordingly. The Severity field - MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the Machine and will contain a more - verbose string suitable for logging and human consumption. \n This - field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of Machines can be added as events - to the Machine object and/or logged in the controller's output." - type: string - failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the Machine and will contain a succinct - value suitable for machine interpretation. \n This field should - not be set for transitive errors that a controller faces that are - expected to be fixed automatically over time (like service outages), - but instead indicate that something is fundamentally wrong with - the Machine's spec or the configuration of the controller, and that - manual intervention is required. Examples of terminal errors would - be invalid combinations of settings in the spec, values that are - unsupported by the controller, or the responsible controller itself - being critically misconfigured. \n Any transient errors that occur - during the reconciliation of Machines can be added as events to - the Machine object and/or logged in the controller's output." - type: string - instances: - description: Instances contains the status for each instance in the - pool - items: - description: AWSMachinePoolInstanceStatus defines the status of - the AWSMachinePoolInstance. - properties: - instanceID: - description: InstanceID is the identification of the Machine - Instance within ASG - type: string - version: - description: Version defines the Kubernetes version for the - Machine Instance - type: string - type: object - type: array - launchTemplateID: - description: The ID of the launch template - type: string - launchTemplateVersion: - description: The version of the launch template - type: string - ready: - description: Ready is true when the provider resource is ready. - type: boolean - replicas: - description: Replicas is the most recently observed number of replicas - format: int32 - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsmachines.infrastructure.cluster.x-k8s.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - caBundle: Cg== - service: - name: capa-webhook-service - namespace: capa-system - path: /convert - conversionReviewVersions: - - v1 - - v1beta1 - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSMachine - listKind: AWSMachineList - plural: awsmachines - shortNames: - - awsm - singular: awsmachine - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AWSMachine belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: EC2 instance state - jsonPath: .status.instanceState - name: State - type: string - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: EC2 instance ID - jsonPath: .spec.providerID - name: InstanceID - type: string - - description: Machine object which owns with this AWSMachine - jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name - name: Machine - type: string - name: v1beta1 - schema: - openAPIV3Schema: - description: AWSMachine is the schema for Amazon EC2 machines. - 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: AWSMachineSpec defines the desired state of an Amazon EC2 - instance. - properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups is an array of references to - security groups that should be applied to the instance. These security - groups would be set in addition to any security groups defined at - the cluster level or in the actuator. It is possible to specify - either IDs of Filters. Using Filters will cause additional requests - to AWS API and if tags change the attached security groups might - change too. - items: - description: AWSResourceReference is a reference to a specific AWS - resource by ID or filters. Only one of ID or Filters may be specified. - Specifying more than one will result in a validation error. - properties: - arn: - description: 'ARN of resource. Deprecated: This field has no - function and is going to be removed in the next release.' - type: string - filters: - description: 'Filters is a set of key/value pairs used to identify - a resource They are applied according to the rules defined - by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to an - instance, in addition to the ones added by default by the AWS provider. - If both the AWSCluster and the AWSMachine specify the same tag name - with different values, the AWSMachine's value takes precedence. - type: object - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look up - an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - cloudInit: - description: CloudInit defines options related to the bootstrapping - systems where CloudInit is used. - properties: - insecureSkipSecretsManager: - description: InsecureSkipSecretsManager, when set to true will - not use AWS Secrets Manager or AWS Systems Manager Parameter - Store to ensure privacy of userdata. By default, a cloud-init - boothook shell script is prepended to download the userdata - from Secrets Manager and additionally delete the secret. - type: boolean - secretCount: - description: SecretCount is the number of secrets used to form - the complete secret - format: int32 - type: integer - secretPrefix: - description: SecretPrefix is the prefix for the secret name. This - is stored temporarily, and deleted when the machine registers - as a node against the workload cluster. - type: string - secureSecretsBackend: - description: SecureSecretsBackend, when set to parameter-store - will utilize the AWS Systems Manager Parameter Storage to distribute - secrets. By default or with the value of secrets-manager, will - use AWS Secrets Manager instead. - enum: - - secrets-manager - - ssm-parameter-store - type: string - type: object - failureDomain: - description: FailureDomain is the failure domain unique identifier - this Machine should be attached to, as defined in Cluster API. For - this infrastructure provider, the ID is equivalent to an AWS Availability - Zone. If multiple subnets are matched for the availability zone, - the first one returned is picked. - type: string - iamInstanceProfile: - description: IAMInstanceProfile is a name of an IAM instance profile - to assign to the instance - type: string - ignition: - description: Ignition defined options related to the bootstrapping - systems where Ignition is used. - properties: - version: - default: "2.3" - description: Version defines which version of Ignition will be - used to generate bootstrap data. - enum: - - "2.3" + folder: + description: Folder is the name or inventory path of the folder + in which the virtual machine is created/located. type: string - type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating system - to use for image lookup the AMI is not set. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look up - the image for this machine It will be ignored if an explicit AMI - is set. Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} - with the base OS and kubernetes version, respectively. The BaseOS - will be the value in ImageLookupBaseOS or ubuntu (the default), - and the kubernetes version as defined by the packages produced by - kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use for - image lookup if AMI is not set. - type: string - instanceID: - description: InstanceID is the EC2 instance ID for this machine. - type: string - instanceType: - description: 'InstanceType is the type of instance to create. Example: - m4.xlarge' - minLength: 2 - type: string - networkInterfaces: - description: NetworkInterfaces is a list of ENIs to associate with - the instance. A maximum of 2 may be specified. - items: - type: string - maxItems: 2 - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for the - storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the disk. - Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - publicIP: - description: 'PublicIP specifies whether the instance should get a - public IP. Precedence for this setting is as follows: 1. This field - if set 2. Cluster/flavor setting 3. Subnet default' - type: boolean - rootVolume: - description: RootVolume encapsulates the configuration options for - the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt the - volume. Can be either a KMS key ID or ARN. If Encrypted is set - and this is omitted, the default AWS key will be used. The key - must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the disk. - Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for the - volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions allows users to configure instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is willing - to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - instance. Valid values are empty string (do not use SSH keys), a - valid SSH key name, or omitted (use the default SSH key name) - type: string - subnet: - description: Subnet is a reference to the subnet to use for this instance. - If not specified, the cluster subnet will be used. - properties: - arn: - description: 'ARN of resource. Deprecated: This field has no function - and is going to be removed in the next release.' - type: string - filters: - description: 'Filters is a set of key/value pairs used to identify - a resource They are applied according to the rules defined by - the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource + resourcePool: + description: ResourcePool is the name or inventory path of the + resource pool in which the virtual machine is created/located. type: string type: object - tenancy: - description: Tenancy indicates if instance should run on shared or - single-tenant hardware. - enum: - - default - - dedicated - - host + server: + description: Server is the address of the vSphere endpoint. type: string - uncompressedUserData: - description: UncompressedUserData specify whether the user data is - gzip-compressed before it is sent to ec2 instance. cloud-init has - built-in support for gzip-compressed user data user data stored - in aws secret manager is always gzip-compressed. - type: boolean required: - - instanceType + - placementConstraint type: object status: - description: AWSMachineStatus defines the observed state of AWSMachine. properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array conditions: - description: Conditions defines current service state of the AWSMachine. + description: Conditions defines current service state of the VSphereMachine. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -6015,54 +1645,13 @@ spec: important. type: string required: - - lastTransitionTime - status - type type: object type: array - failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the Machine and will contain a more - verbose string suitable for logging and human consumption. \n This - field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of Machines can be added as events - to the Machine object and/or logged in the controller's output." - type: string - failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the Machine and will contain a succinct - value suitable for machine interpretation. \n This field should - not be set for transitive errors that a controller faces that are - expected to be fixed automatically over time (like service outages), - but instead indicate that something is fundamentally wrong with - the Machine's spec or the configuration of the controller, and that - manual intervention is required. Examples of terminal errors would - be invalid combinations of settings in the spec, values that are - unsupported by the controller, or the responsible controller itself - being critically misconfigured. \n Any transient errors that occur - during the reconciliation of Machines can be added as events to - the Machine object and/or logged in the controller's output." - type: string - instanceState: - description: InstanceState is the state of the AWS instance for this - machine. - type: string - interruptible: - description: Interruptible reports that this machine is using spot - instances and can therefore be interrupted by CAPI when it receives - a notice that the spot instance is to be terminated by AWS. This - will be set to true when SpotMarketOptions is not nil (i.e. this - machine is using a spot instance). - type: boolean ready: - description: Ready is true when the provider resource is ready. + description: Ready is true when the VSphereDeploymentZone resource + is ready. If set to false, it will be ignored by VSphereClusters type: boolean type: object type: object @@ -6070,31 +1659,12 @@ spec: storage: false subresources: status: {} - - additionalPrinterColumns: - - description: Cluster to which this AWSMachine belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: EC2 instance state - jsonPath: .status.instanceState - name: State - type: string - - description: Machine ready status - jsonPath: .status.ready - name: Ready - type: string - - description: EC2 instance ID - jsonPath: .spec.providerID - name: InstanceID - type: string - - description: Machine object which owns with this AWSMachine - jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name - name: Machine - type: string - name: v1beta2 + - deprecated: true + name: v1alpha4 schema: openAPIV3Schema: - description: AWSMachine is the schema for Amazon EC2 machines. + description: "VSphereDeploymentZone is the Schema for the vspheredeploymentzones + API \n Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -6109,390 +1679,143 @@ spec: metadata: type: object spec: - description: AWSMachineSpec defines the desired state of an Amazon EC2 - instance. - properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups is an array of references to - security groups that should be applied to the instance. These security - groups would be set in addition to any security groups defined at - the cluster level or in the actuator. It is possible to specify - either IDs of Filters. Using Filters will cause additional requests - to AWS API and if tags change the attached security groups might - change too. - items: - description: AWSResourceReference is a reference to a specific AWS - resource by ID or filters. Only one of ID or Filters may be specified. - Specifying more than one will result in a validation error. - properties: - filters: - description: 'Filters is a set of key/value pairs used to identify - a resource They are applied according to the rules defined - by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to an - instance, in addition to the ones added by default by the AWS provider. - If both the AWSCluster and the AWSMachine specify the same tag name - with different values, the AWSMachine's value takes precedence. - type: object - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look up - an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - cloudInit: - description: CloudInit defines options related to the bootstrapping - systems where CloudInit is used. - properties: - insecureSkipSecretsManager: - description: InsecureSkipSecretsManager, when set to true will - not use AWS Secrets Manager or AWS Systems Manager Parameter - Store to ensure privacy of userdata. By default, a cloud-init - boothook shell script is prepended to download the userdata - from Secrets Manager and additionally delete the secret. - type: boolean - secretCount: - description: SecretCount is the number of secrets used to form - the complete secret - format: int32 - type: integer - secretPrefix: - description: SecretPrefix is the prefix for the secret name. This - is stored temporarily, and deleted when the machine registers - as a node against the workload cluster. - type: string - secureSecretsBackend: - description: SecureSecretsBackend, when set to parameter-store - will utilize the AWS Systems Manager Parameter Storage to distribute - secrets. By default or with the value of secrets-manager, will - use AWS Secrets Manager instead. - enum: - - secrets-manager - - ssm-parameter-store - type: string - type: object - iamInstanceProfile: - description: IAMInstanceProfile is a name of an IAM instance profile - to assign to the instance - type: string - ignition: - description: Ignition defined options related to the bootstrapping - systems where Ignition is used. - properties: - version: - default: "2.3" - description: Version defines which version of Ignition will be - used to generate bootstrap data. - enum: - - "2.3" - - "3.0" - - "3.1" - - "3.2" - - "3.3" - - "3.4" - type: string - type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating system - to use for image lookup the AMI is not set. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look up - the image for this machine It will be ignored if an explicit AMI - is set. Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} - with the base OS and kubernetes version, respectively. The BaseOS - will be the value in ImageLookupBaseOS or ubuntu (the default), - and the kubernetes version as defined by the packages produced by - kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use for - image lookup if AMI is not set. - type: string - instanceID: - description: InstanceID is the EC2 instance ID for this machine. - type: string - instanceMetadataOptions: - description: InstanceMetadataOptions is the metadata options for the - EC2 instance. - properties: - httpEndpoint: - default: enabled - description: "Enables or disables the HTTP metadata endpoint on - your instances. \n If you specify a value of disabled, you cannot - access your instance metadata. \n Default: enabled" - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: "The desired HTTP PUT response hop limit for instance - metadata requests. The larger the number, the further instance - metadata requests can travel. \n Default: 1" - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: "The state of token usage for your instance metadata - requests. \n If the state is optional, you can choose to retrieve - instance metadata with or without a session token on your request. - If you retrieve the IAM role credentials without a token, the - version 1.0 role credentials are returned. If you retrieve the - IAM role credentials using a valid session token, the version - 2.0 role credentials are returned. \n If the state is required, - you must send a session token with any instance metadata retrieval - requests. In this state, retrieving the IAM role credentials - always returns the version 2.0 credentials; the version 1.0 - credentials are not available. \n Default: optional" - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: "Set to enabled to allow access to instance tags - from the instance metadata. Set to disabled to turn off access - to instance tags from the instance metadata. For more information, - see Work with instance tags using the instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - \n Default: disabled" - enum: - - enabled - - disabled - type: string - type: object - instanceType: - description: 'InstanceType is the type of instance to create. Example: - m4.xlarge' - minLength: 2 - type: string - networkInterfaces: - description: NetworkInterfaces is a list of ENIs to associate with - the instance. A maximum of 2 may be specified. - items: - type: string - maxItems: 2 - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for the - storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be used. - The key must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the disk. - Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - placementGroupName: - description: PlacementGroupName specifies the name of the placement - group in which to launch the instance. - type: string - providerID: - description: ProviderID is the unique identifier as specified by the - cloud provider. - type: string - publicIP: - description: 'PublicIP specifies whether the instance should get a - public IP. Precedence for this setting is as follows: 1. This field - if set 2. Cluster/flavor setting 3. Subnet default' + description: VSphereDeploymentZoneSpec defines the desired state of VSphereDeploymentZone + properties: + controlPlane: + description: ControlPlane determines if this failure domain is suitable + for use by control plane machines. type: boolean - rootVolume: - description: RootVolume encapsulates the configuration options for - the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt the - volume. Can be either a KMS key ID or ARN. If Encrypted is set - and this is omitted, the default AWS key will be used. The key - must already exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the disk. - Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for the - volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions allows users to configure instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is willing - to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - instance. Valid values are empty string (do not use SSH keys), a - valid SSH key name, or omitted (use the default SSH key name) + failureDomain: + description: FailureDomain is the name of the VSphereFailureDomain + used for this VSphereDeploymentZone type: string - subnet: - description: Subnet is a reference to the subnet to use for this instance. - If not specified, the cluster subnet will be used. + placementConstraint: + description: PlacementConstraint encapsulates the placement constraints + used within this deployment zone. properties: - filters: - description: 'Filters is a set of key/value pairs used to identify - a resource They are applied according to the rules defined by - the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS resource. - properties: - name: - description: Name of the filter. Filter names are case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource + folder: + description: Folder is the name or inventory path of the folder + in which the virtual machine is created/located. + type: string + resourcePool: + description: ResourcePool is the name or inventory path of the + resource pool in which the virtual machine is created/located. type: string type: object - tenancy: - description: Tenancy indicates if instance should run on shared or - single-tenant hardware. - enum: - - default - - dedicated - - host + server: + description: Server is the address of the vSphere endpoint. type: string - uncompressedUserData: - description: UncompressedUserData specify whether the user data is - gzip-compressed before it is sent to ec2 instance. cloud-init has - built-in support for gzip-compressed user data user data stored - in aws secret manager is always gzip-compressed. - type: boolean required: - - instanceType + - placementConstraint type: object status: - description: AWSMachineStatus defines the observed state of AWSMachine. properties: - addresses: - description: Addresses contains the AWS instance associated addresses. + conditions: + description: Conditions defines current service state of the VSphereMachine. items: - description: MachineAddress contains information for the node's - address. + description: Condition defines an observation of a Cluster API resource + operational state. properties: - address: - description: The machine address. + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. + format: date-time + type: string + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. + type: string + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. + type: string + status: + description: Status of the condition, one of True, False, Unknown. type: string type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. type: string required: - - address + - status - type type: object type: array + ready: + description: Ready is true when the VSphereDeploymentZone resource + is ready. If set to false, it will be ignored by VSphereClusters + type: boolean + type: object + type: object + served: true + storage: false + subresources: + status: {} + - name: v1beta1 + schema: + openAPIV3Schema: + description: VSphereDeploymentZone is the Schema for the vspheredeploymentzones + 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: VSphereDeploymentZoneSpec defines the desired state of VSphereDeploymentZone + properties: + controlPlane: + description: ControlPlane determines if this failure domain is suitable + for use by control plane machines. + type: boolean + failureDomain: + description: FailureDomain is the name of the VSphereFailureDomain + used for this VSphereDeploymentZone + type: string + placementConstraint: + description: PlacementConstraint encapsulates the placement constraints + used within this deployment zone. + properties: + folder: + description: Folder is the name or inventory path of the folder + in which the virtual machine is created/located. + type: string + resourcePool: + description: ResourcePool is the name or inventory path of the + resource pool in which the virtual machine is created/located. + type: string + type: object + server: + description: Server is the address of the vSphere endpoint. + type: string + required: + - placementConstraint + type: object + status: + properties: conditions: - description: Conditions defines current service state of the AWSMachine. + description: Conditions defines current service state of the VSphereMachine. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -6536,49 +1859,9 @@ spec: - type type: object type: array - failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the Machine and will contain a more - verbose string suitable for logging and human consumption. \n This - field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of Machines can be added as events - to the Machine object and/or logged in the controller's output." - type: string - failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the Machine and will contain a succinct - value suitable for machine interpretation. \n This field should - not be set for transitive errors that a controller faces that are - expected to be fixed automatically over time (like service outages), - but instead indicate that something is fundamentally wrong with - the Machine's spec or the configuration of the controller, and that - manual intervention is required. Examples of terminal errors would - be invalid combinations of settings in the spec, values that are - unsupported by the controller, or the responsible controller itself - being critically misconfigured. \n Any transient errors that occur - during the reconciliation of Machines can be added as events to - the Machine object and/or logged in the controller's output." - type: string - instanceState: - description: InstanceState is the state of the AWS instance for this - machine. - type: string - interruptible: - description: Interruptible reports that this machine is using spot - instances and can therefore be interrupted by CAPI when it receives - a notice that the spot instance is to be terminated by AWS. This - will be set to true when SpotMarketOptions is not nil (i.e. this - machine is using a spot instance). - type: boolean ready: - description: Ready is true when the provider resource is ready. + description: Ready is true when the VSphereDeploymentZone resource + is ready. If set to false, it will be ignored by VSphereClusters type: boolean type: object type: object @@ -6591,14 +1874,12 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert controller-gen.kubebuilder.io/version: v0.12.1 labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsmachinetemplates.infrastructure.cluster.x-k8s.io + cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 + name: vspherefailuredomains.infrastructure.cluster.x-k8s.io spec: conversion: strategy: Webhook @@ -6606,8 +1887,8 @@ spec: clientConfig: caBundle: Cg== service: - name: capa-webhook-service - namespace: capa-system + name: capv-webhook-service + namespace: capv-system path: /convert conversionReviewVersions: - v1 @@ -6616,19 +1897,18 @@ spec: names: categories: - cluster-api - kind: AWSMachineTemplate - listKind: AWSMachineTemplateList - plural: awsmachinetemplates - shortNames: - - awsmt - singular: awsmachinetemplate - scope: Namespaced + kind: VSphereFailureDomain + listKind: VSphereFailureDomainList + plural: vspherefailuredomains + singular: vspherefailuredomain + scope: Cluster versions: - - name: v1beta1 + - deprecated: true + name: v1alpha3 schema: openAPIV3Schema: - description: AWSMachineTemplate is the schema for the Amazon EC2 Machine Templates - API. + description: "VSphereFailureDomain is the Schema for the vspherefailuredomains + API \n Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -6643,396 +1923,114 @@ spec: metadata: type: object spec: - description: AWSMachineTemplateSpec defines the desired state of AWSMachineTemplate. + description: VSphereFailureDomainSpec defines the desired state of VSphereFailureDomain properties: - template: - description: AWSMachineTemplateResource describes the data needed - to create am AWSMachine from a template. + region: + description: Region defines the name and type of a region properties: - metadata: - description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not queryable - and should be preserved when modifying objects. More info: - http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used - to organize and categorize (scope and select) objects. May - match selectors of replication controllers and services. - More info: http://kubernetes.io/docs/user-guide/labels' - type: object - type: object - spec: - description: Spec is the specification of the desired behavior - of the machine. - properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups is an array of references - to security groups that should be applied to the instance. - These security groups would be set in addition to any security - groups defined at the cluster level or in the actuator. - It is possible to specify either IDs of Filters. Using Filters - will cause additional requests to AWS API and if tags change - the attached security groups might change too. - items: - description: AWSResourceReference is a reference to a specific - AWS resource by ID or filters. Only one of ID or Filters - may be specified. Specifying more than one will result - in a validation error. - properties: - arn: - description: 'ARN of resource. Deprecated: This field - has no function and is going to be removed in the - next release.' - type: string - filters: - description: 'Filters is a set of key/value pairs used - to identify a resource They are applied according - to the rules defined by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an - AWS resource. - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to - add to an instance, in addition to the ones added by default - by the AWS provider. If both the AWSCluster and the AWSMachine - specify the same tag name with different values, the AWSMachine's - value takes precedence. - type: object - ami: - description: AMI is the reference to the AMI from which to - create the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will - look up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - cloudInit: - description: CloudInit defines options related to the bootstrapping - systems where CloudInit is used. - properties: - insecureSkipSecretsManager: - description: InsecureSkipSecretsManager, when set to true - will not use AWS Secrets Manager or AWS Systems Manager - Parameter Store to ensure privacy of userdata. By default, - a cloud-init boothook shell script is prepended to download - the userdata from Secrets Manager and additionally delete - the secret. - type: boolean - secretCount: - description: SecretCount is the number of secrets used - to form the complete secret - format: int32 - type: integer - secretPrefix: - description: SecretPrefix is the prefix for the secret - name. This is stored temporarily, and deleted when the - machine registers as a node against the workload cluster. - type: string - secureSecretsBackend: - description: SecureSecretsBackend, when set to parameter-store - will utilize the AWS Systems Manager Parameter Storage - to distribute secrets. By default or with the value - of secrets-manager, will use AWS Secrets Manager instead. - enum: - - secrets-manager - - ssm-parameter-store - type: string - type: object - failureDomain: - description: FailureDomain is the failure domain unique identifier - this Machine should be attached to, as defined in Cluster - API. For this infrastructure provider, the ID is equivalent - to an AWS Availability Zone. If multiple subnets are matched - for the availability zone, the first one returned is picked. - type: string - iamInstanceProfile: - description: IAMInstanceProfile is a name of an IAM instance - profile to assign to the instance - type: string - ignition: - description: Ignition defined options related to the bootstrapping - systems where Ignition is used. - properties: - version: - default: "2.3" - description: Version defines which version of Ignition - will be used to generate bootstrap data. - enum: - - "2.3" - type: string - type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating - system to use for image lookup the AMI is not set. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to - look up the image for this machine It will be ignored if - an explicit AMI is set. Supports substitutions for {{.BaseOS}} - and {{.K8sVersion}} with the base OS and kubernetes version, - respectively. The BaseOS will be the value in ImageLookupBaseOS - or ubuntu (the default), and the kubernetes version as defined - by the packages produced by kubernetes/release without v - as a prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, - the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the - ubuntu base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to - use for image lookup if AMI is not set. - type: string - instanceID: - description: InstanceID is the EC2 instance ID for this machine. - type: string - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - minLength: 2 - type: string - networkInterfaces: - description: NetworkInterfaces is a list of ENIs to associate - with the instance. A maximum of 2 may be specified. - items: - type: string - maxItems: 2 - type: array - nonRootVolumes: - description: Configuration options for the non root storage - volumes. - items: - description: Volume encapsulates the configuration options - for the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should - be encrypted or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to - encrypt the volume. Can be either a KMS key ID or - ARN. If Encrypted is set and this is omitted, the - default AWS key will be used. The key must already - exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for - the disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size - or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, - io1, etc...). - type: string - required: - - size - type: object - type: array - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - publicIP: - description: 'PublicIP specifies whether the instance should - get a public IP. Precedence for this setting is as follows: - 1. This field if set 2. Cluster/flavor setting 3. Subnet - default' - type: boolean - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be - encrypted or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will - be used. The key must already exist and be accessible - by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for - the disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size - or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, - io1, etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions allows users to configure instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user - is willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach - to the instance. Valid values are empty string (do not use - SSH keys), a valid SSH key name, or omitted (use the default - SSH key name) + autoConfigure: + description: AutoConfigure tags the Type which is specified in + the Topology + type: boolean + name: + description: Name is the name of the tag that represents this + failure domain + type: string + tagCategory: + description: TagCategory is the category used for the tag + type: string + type: + description: Type is the type of failure domain, the current values + are "Datacenter", "ComputeCluster" and "HostGroup" + enum: + - Datacenter + - ComputeCluster + - HostGroup + type: string + required: + - name + - tagCategory + - type + type: object + topology: + description: Topology is the what describes a given failure domain + using vSphere constructs + properties: + computeCluster: + description: ComputeCluster as the failure domain + type: string + datacenter: + description: The underlying infrastructure for this failure domain + Datacenter as the failure domain + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + hosts: + description: Hosts has information required for placement of machines + on VSphere hosts. + properties: + hostGroupName: + description: HostGroupName is the name of the Host group type: string - subnet: - description: Subnet is a reference to the subnet to use for - this instance. If not specified, the cluster subnet will - be used. - properties: - arn: - description: 'ARN of resource. Deprecated: This field - has no function and is going to be removed in the next - release.' - type: string - filters: - description: 'Filters is a set of key/value pairs used - to identify a resource They are applied according to - the rules defined by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an - AWS resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - enum: - - default - - dedicated - - host + vmGroupName: + description: VMGroupName is the name of the VM group type: string - uncompressedUserData: - description: UncompressedUserData specify whether the user - data is gzip-compressed before it is sent to ec2 instance. - cloud-init has built-in support for gzip-compressed user - data user data stored in aws secret manager is always gzip-compressed. - type: boolean required: - - instanceType + - hostGroupName + - vmGroupName type: object + networks: + description: Networks is the list of networks within this failure + domain + items: + type: string + type: array required: - - spec + - datacenter type: object - required: - - template - type: object - status: - description: AWSMachineTemplateStatus defines a status for an AWSMachineTemplate. - properties: - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Capacity defines the resource capacity for this machine. - This value is used for autoscaling from zero operations as defined - in: https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md' + zone: + description: Zone defines the name and type of a zone + properties: + autoConfigure: + description: AutoConfigure tags the Type which is specified in + the Topology + type: boolean + name: + description: Name is the name of the tag that represents this + failure domain + type: string + tagCategory: + description: TagCategory is the category used for the tag + type: string + type: + description: Type is the type of failure domain, the current values + are "Datacenter", "ComputeCluster" and "HostGroup" + enum: + - Datacenter + - ComputeCluster + - HostGroup + type: string + required: + - name + - tagCategory + - type type: object + required: + - region + - topology + - zone type: object type: object served: true storage: false - - name: v1beta2 + - deprecated: true + name: v1alpha4 schema: openAPIV3Schema: - description: AWSMachineTemplate is the schema for the Amazon EC2 Machine Templates - API. + description: "VSphereFailureDomain is the Schema for the vspherefailuredomains + API \n Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -7047,483 +2045,113 @@ spec: metadata: type: object spec: - description: AWSMachineTemplateSpec defines the desired state of AWSMachineTemplate. + description: VSphereFailureDomainSpec defines the desired state of VSphereFailureDomain properties: - template: - description: AWSMachineTemplateResource describes the data needed - to create am AWSMachine from a template. + region: + description: Region defines the name and type of a region properties: - metadata: - description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' - properties: - annotations: - additionalProperties: - type: string - description: 'Annotations is an unstructured key value map - stored with a resource that may be set by external tools - to store and retrieve arbitrary metadata. They are not queryable - and should be preserved when modifying objects. More info: - http://kubernetes.io/docs/user-guide/annotations' - type: object - labels: - additionalProperties: - type: string - description: 'Map of string keys and values that can be used - to organize and categorize (scope and select) objects. May - match selectors of replication controllers and services. - More info: http://kubernetes.io/docs/user-guide/labels' - type: object - type: object - spec: - description: Spec is the specification of the desired behavior - of the machine. + autoConfigure: + description: AutoConfigure tags the Type which is specified in + the Topology + type: boolean + name: + description: Name is the name of the tag that represents this + failure domain + type: string + tagCategory: + description: TagCategory is the category used for the tag + type: string + type: + description: Type is the type of failure domain, the current values + are "Datacenter", "ComputeCluster" and "HostGroup" + enum: + - Datacenter + - ComputeCluster + - HostGroup + type: string + required: + - name + - tagCategory + - type + type: object + topology: + description: Topology describes a given failure domain using vSphere + constructs + properties: + computeCluster: + description: ComputeCluster as the failure domain + type: string + datacenter: + description: The underlying infrastructure for this failure domain + Datacenter as the failure domain + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + hosts: + description: Hosts has information required for placement of machines + on VSphere hosts. properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups is an array of references - to security groups that should be applied to the instance. - These security groups would be set in addition to any security - groups defined at the cluster level or in the actuator. - It is possible to specify either IDs of Filters. Using Filters - will cause additional requests to AWS API and if tags change - the attached security groups might change too. - items: - description: AWSResourceReference is a reference to a specific - AWS resource by ID or filters. Only one of ID or Filters - may be specified. Specifying more than one will result - in a validation error. - properties: - filters: - description: 'Filters is a set of key/value pairs used - to identify a resource They are applied according - to the rules defined by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an - AWS resource. - properties: - name: - description: Name of the filter. Filter names - are case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to - add to an instance, in addition to the ones added by default - by the AWS provider. If both the AWSCluster and the AWSMachine - specify the same tag name with different values, the AWSMachine's - value takes precedence. - type: object - ami: - description: AMI is the reference to the AMI from which to - create the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will - look up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - cloudInit: - description: CloudInit defines options related to the bootstrapping - systems where CloudInit is used. - properties: - insecureSkipSecretsManager: - description: InsecureSkipSecretsManager, when set to true - will not use AWS Secrets Manager or AWS Systems Manager - Parameter Store to ensure privacy of userdata. By default, - a cloud-init boothook shell script is prepended to download - the userdata from Secrets Manager and additionally delete - the secret. - type: boolean - secretCount: - description: SecretCount is the number of secrets used - to form the complete secret - format: int32 - type: integer - secretPrefix: - description: SecretPrefix is the prefix for the secret - name. This is stored temporarily, and deleted when the - machine registers as a node against the workload cluster. - type: string - secureSecretsBackend: - description: SecureSecretsBackend, when set to parameter-store - will utilize the AWS Systems Manager Parameter Storage - to distribute secrets. By default or with the value - of secrets-manager, will use AWS Secrets Manager instead. - enum: - - secrets-manager - - ssm-parameter-store - type: string - type: object - iamInstanceProfile: - description: IAMInstanceProfile is a name of an IAM instance - profile to assign to the instance - type: string - ignition: - description: Ignition defined options related to the bootstrapping - systems where Ignition is used. - properties: - version: - default: "2.3" - description: Version defines which version of Ignition - will be used to generate bootstrap data. - enum: - - "2.3" - - "3.0" - - "3.1" - - "3.2" - - "3.3" - - "3.4" - type: string - type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating - system to use for image lookup the AMI is not set. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to - look up the image for this machine It will be ignored if - an explicit AMI is set. Supports substitutions for {{.BaseOS}} - and {{.K8sVersion}} with the base OS and kubernetes version, - respectively. The BaseOS will be the value in ImageLookupBaseOS - or ubuntu (the default), and the kubernetes version as defined - by the packages produced by kubernetes/release without v - as a prefix: 1.13.0, 1.12.5-mybuild.1, or 1.17.3. For example, - the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the - ubuntu base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to - use for image lookup if AMI is not set. - type: string - instanceID: - description: InstanceID is the EC2 instance ID for this machine. - type: string - instanceMetadataOptions: - description: InstanceMetadataOptions is the metadata options - for the EC2 instance. - properties: - httpEndpoint: - default: enabled - description: "Enables or disables the HTTP metadata endpoint - on your instances. \n If you specify a value of disabled, - you cannot access your instance metadata. \n Default: - enabled" - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: "The desired HTTP PUT response hop limit - for instance metadata requests. The larger the number, - the further instance metadata requests can travel. \n - Default: 1" - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: "The state of token usage for your instance - metadata requests. \n If the state is optional, you - can choose to retrieve instance metadata with or without - a session token on your request. If you retrieve the - IAM role credentials without a token, the version 1.0 - role credentials are returned. If you retrieve the IAM - role credentials using a valid session token, the version - 2.0 role credentials are returned. \n If the state is - required, you must send a session token with any instance - metadata retrieval requests. In this state, retrieving - the IAM role credentials always returns the version - 2.0 credentials; the version 1.0 credentials are not - available. \n Default: optional" - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: "Set to enabled to allow access to instance - tags from the instance metadata. Set to disabled to - turn off access to instance tags from the instance metadata. - For more information, see Work with instance tags using - the instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - \n Default: disabled" - enum: - - enabled - - disabled - type: string - type: object - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - minLength: 2 - type: string - networkInterfaces: - description: NetworkInterfaces is a list of ENIs to associate - with the instance. A maximum of 2 may be specified. - items: - type: string - maxItems: 2 - type: array - nonRootVolumes: - description: Configuration options for the non root storage - volumes. - items: - description: Volume encapsulates the configuration options - for the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should - be encrypted or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to - encrypt the volume. Can be either a KMS key ID or - ARN. If Encrypted is set and this is omitted, the - default AWS key will be used. The key must already - exist and be accessible by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for - the disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size - or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, - io1, etc...). - type: string - required: - - size - type: object - type: array - placementGroupName: - description: PlacementGroupName specifies the name of the - placement group in which to launch the instance. - type: string - providerID: - description: ProviderID is the unique identifier as specified - by the cloud provider. - type: string - publicIP: - description: 'PublicIP specifies whether the instance should - get a public IP. Precedence for this setting is as follows: - 1. This field if set 2. Cluster/flavor setting 3. Subnet - default' - type: boolean - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be - encrypted or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will - be used. The key must already exist and be accessible - by the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for - the disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size - or 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, - io1, etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions allows users to configure instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user - is willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach - to the instance. Valid values are empty string (do not use - SSH keys), a valid SSH key name, or omitted (use the default - SSH key name) + hostGroupName: + description: HostGroupName is the name of the Host group type: string - subnet: - description: Subnet is a reference to the subnet to use for - this instance. If not specified, the cluster subnet will - be used. - properties: - filters: - description: 'Filters is a set of key/value pairs used - to identify a resource They are applied according to - the rules defined by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an - AWS resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter - values. Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - enum: - - default - - dedicated - - host + vmGroupName: + description: VMGroupName is the name of the VM group type: string - uncompressedUserData: - description: UncompressedUserData specify whether the user - data is gzip-compressed before it is sent to ec2 instance. - cloud-init has built-in support for gzip-compressed user - data user data stored in aws secret manager is always gzip-compressed. - type: boolean required: - - instanceType + - hostGroupName + - vmGroupName type: object + networks: + description: Networks is the list of networks within this failure + domain + items: + type: string + type: array required: - - spec + - datacenter type: object - required: - - template - type: object - status: - description: AWSMachineTemplateStatus defines a status for an AWSMachineTemplate. - properties: - capacity: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: 'Capacity defines the resource capacity for this machine. - This value is used for autoscaling from zero operations as defined - in: https://github.com/kubernetes-sigs/cluster-api/blob/main/docs/proposals/20210310-opt-in-autoscaling-from-zero.md' + zone: + description: Zone defines the name and type of a zone + properties: + autoConfigure: + description: AutoConfigure tags the Type which is specified in + the Topology + type: boolean + name: + description: Name is the name of the tag that represents this + failure domain + type: string + tagCategory: + description: TagCategory is the category used for the tag + type: string + type: + description: Type is the type of failure domain, the current values + are "Datacenter", "ComputeCluster" and "HostGroup" + enum: + - Datacenter + - ComputeCluster + - HostGroup + type: string + required: + - name + - tagCategory + - type type: object + required: + - region + - topology + - zone type: object type: object served: true - storage: true ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsmanagedclusters.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSManagedCluster - listKind: AWSManagedClusterList - plural: awsmanagedclusters - shortNames: - - awsmc - singular: awsmanagedcluster - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Cluster to which this AWSManagedControl belongs - jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name - name: Cluster - type: string - - description: Control plane infrastructure is ready for worker nodes - jsonPath: .status.ready - name: Ready - type: string - - description: API Endpoint - jsonPath: .spec.controlPlaneEndpoint.host - name: Endpoint - priority: 1 - type: string - name: v1beta2 + storage: false + - name: v1beta1 schema: openAPIV3Schema: - description: AWSManagedCluster is the Schema for the awsmanagedclusters API + description: VSphereFailureDomain is the Schema for the vspherefailuredomains + API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -7538,70 +2166,120 @@ spec: metadata: type: object spec: - description: AWSManagedClusterSpec defines the desired state of AWSManagedCluster + description: VSphereFailureDomainSpec defines the desired state of VSphereFailureDomain properties: - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. + region: + description: Region defines the name and type of a region properties: - host: - description: The hostname on which the API server is serving. + autoConfigure: + description: "AutoConfigure tags the Type which is specified in + the Topology \n Deprecated: This field is going to be removed + in a future release." + type: boolean + name: + description: Name is the name of the tag that represents this + failure domain + type: string + tagCategory: + description: TagCategory is the category used for the tag + type: string + type: + description: Type is the type of failure domain, the current values + are "Datacenter", "ComputeCluster" and "HostGroup" + enum: + - Datacenter + - ComputeCluster + - HostGroup + type: string + required: + - name + - tagCategory + - type + type: object + topology: + description: Topology describes a given failure domain using vSphere + constructs + properties: + computeCluster: + description: ComputeCluster as the failure domain + type: string + datacenter: + description: Datacenter as the failure domain. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + hosts: + description: Hosts has information required for placement of machines + on VSphere hosts. + properties: + hostGroupName: + description: HostGroupName is the name of the Host group + type: string + vmGroupName: + description: VMGroupName is the name of the VM group + type: string + required: + - hostGroupName + - vmGroupName + type: object + networks: + description: Networks is the list of networks within this failure + domain + items: + type: string + type: array + required: + - datacenter + type: object + zone: + description: Zone defines the name and type of a zone + properties: + autoConfigure: + description: "AutoConfigure tags the Type which is specified in + the Topology \n Deprecated: This field is going to be removed + in a future release." + type: boolean + name: + description: Name is the name of the tag that represents this + failure domain + type: string + tagCategory: + description: TagCategory is the category used for the tag + type: string + type: + description: Type is the type of failure domain, the current values + are "Datacenter", "ComputeCluster" and "HostGroup" + enum: + - Datacenter + - ComputeCluster + - HostGroup type: string - port: - description: The port on which the API server is serving. - format: int32 - type: integer required: - - host - - port - type: object - type: object - status: - description: AWSManagedClusterStatus defines the observed state of AWSManagedCluster - properties: - failureDomains: - additionalProperties: - description: FailureDomainSpec is the Schema for Cluster API failure - domains. It allows controllers to understand how many failure - domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: FailureDomains specifies a list fo available availability - zones that can be used + - name + - tagCategory + - type type: object - ready: - description: Ready is when the AWSManagedControlPlane has a API server - URL. - type: boolean + required: + - region + - topology + - zone type: object type: object served: true storage: true - subresources: - status: {} --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert controller-gen.kubebuilder.io/version: v0.12.1 labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsmanagedcontrolplanes.controlplane.cluster.x-k8s.io + cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 + name: vspheremachines.infrastructure.cluster.x-k8s.io spec: conversion: strategy: Webhook @@ -7609,51 +2287,50 @@ spec: clientConfig: caBundle: Cg== service: - name: capa-webhook-service - namespace: capa-system + name: capv-webhook-service + namespace: capv-system path: /convert conversionReviewVersions: - v1 - v1beta1 - group: controlplane.cluster.x-k8s.io + group: infrastructure.cluster.x-k8s.io names: categories: - cluster-api - kind: AWSManagedControlPlane - listKind: AWSManagedControlPlaneList - plural: awsmanagedcontrolplanes - shortNames: - - awsmcp - singular: awsmanagedcontrolplane + kind: VSphereMachine + listKind: VSphereMachineList + plural: vspheremachines + singular: vspheremachine scope: Namespaced versions: - additionalPrinterColumns: - - description: Cluster to which this AWSManagedControl belongs + - description: Cluster to which this VSphereMachine belongs jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name name: Cluster type: string - - description: Control plane infrastructure is ready for worker nodes + - description: Machine ready status jsonPath: .status.ready name: Ready type: string - - description: AWS VPC the control plane is using - jsonPath: .spec.network.vpc.id - name: VPC + - description: VSphereMachine instance ID + jsonPath: .spec.providerID + name: ProviderID type: string - - description: API Endpoint - jsonPath: .spec.controlPlaneEndpoint.host - name: Endpoint + - description: Machine object which owns this VSphereMachine + jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name + name: Machine priority: 1 type: string - - description: Bastion IP address for breakglass access - jsonPath: .status.bastion.publicIp - name: Bastion IP - type: string - name: v1beta1 + - description: Time duration since creation of Machine + jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + name: v1alpha3 schema: openAPIV3Schema: - description: AWSManagedControlPlane is the schema for the Amazon EKS Managed - Control Plane API. + description: "VSphereMachine is the Schema for the vspheremachines API \n + Deprecated: This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -7668,1129 +2345,652 @@ spec: metadata: type: object spec: - description: AWSManagedControlPlaneSpec defines the desired state of an - Amazon EKS Cluster. + description: VSphereMachineSpec defines the desired state of VSphereMachine properties: - additionalTags: + cloneMode: + description: CloneMode specifies the type of clone operation. The + LinkedClone mode is only support for templates that have at least + one snapshot. If the template has no snapshots, then CloneMode defaults + to FullClone. When LinkedClone mode is enabled the DiskGiB field + is ignored as it is not possible to expand disks of linked clones. + Defaults to LinkedClone, but fails gracefully to FullClone if the + source of the clone operation has no snapshots. + type: string + customVMXKeys: additionalProperties: type: string - description: AdditionalTags is an optional set of tags to add to AWS - resources managed by the AWS provider, in addition to the ones added - by default. - type: object - addons: - description: Addons defines the EKS addons to enable with the EKS - cluster. - items: - description: Addon represents a EKS addon. - properties: - configuration: - description: Configuration of the EKS addon - type: string - conflictResolution: - default: none - description: ConflictResolution is used to declare what should - happen if there are parameter conflicts. Defaults to none - enum: - - overwrite - - none - type: string - name: - description: Name is the name of the addon - minLength: 2 - type: string - serviceAccountRoleARN: - description: ServiceAccountRoleArn is the ARN of an IAM role - to bind to the addons service account - type: string - version: - description: Version is the version of the addon to use - type: string - required: - - name - - version - type: object - type: array - associateOIDCProvider: - default: false - description: AssociateOIDCProvider can be enabled to automatically - create an identity provider for the controller for use with IAM - roles for service accounts - type: boolean - bastion: - description: Bastion contains options to configure the bastion host. - properties: - allowedCIDRBlocks: - description: AllowedCIDRBlocks is a list of CIDR blocks allowed - to access the bastion host. They are set as ingress rules for - the Bastion host's Security Group (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: AMI will use the specified AMI to boot the bastion. - If not specified, the AMI will default to one picked out in - public space. - type: string - disableIngressRules: - description: DisableIngressRules will ensure there are no Ingress - rules in the bastion host's security group. Requires AllowedCIDRBlocks - to be empty. - type: boolean - enabled: - description: Enabled allows this provider to create a bastion - host instance with a public ip to access the VPC private network. - type: boolean - instanceType: - description: InstanceType will use the specified instance type - for the bastion. If not specified, Cluster API Provider AWS - will use t3.micro for all regions except us-east-1, where t2.micro - will be the default. - type: string - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - 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. - format: int32 - type: integer - required: - - host - - port - type: object - disableVPCCNI: - default: false - description: DisableVPCCNI indicates that the Amazon VPC CNI should - be disabled. With EKS clusters the Amazon VPC CNI is automatically - installed into the cluster. For clusters where you want to use an - alternate CNI this option provides a way to specify that the Amazon - VPC CNI should be deleted. You cannot set this to true if you are - using the Amazon VPC CNI addon. - type: boolean - eksClusterName: - description: EKSClusterName allows you to specify the name of the - EKS cluster in AWS. If you don't specify a name then a default name - will be created based on the namespace and name of the managed control - plane. - type: string - encryptionConfig: - description: EncryptionConfig specifies the encryption configuration - for the cluster - properties: - provider: - description: Provider specifies the ARN or alias of the CMK (in - AWS KMS) - type: string - resources: - description: Resources specifies the resources to be encrypted - items: - type: string - type: array - type: object - endpointAccess: - description: Endpoints specifies access to this cluster's control - plane endpoints - properties: - private: - description: Private points VPC-internal control plane access - to the private endpoint - type: boolean - public: - description: Public controls whether control plane endpoints are - publicly accessible - type: boolean - publicCIDRs: - description: PublicCIDRs specifies which blocks can access the - public endpoint - items: - type: string - type: array - type: object - iamAuthenticatorConfig: - description: IAMAuthenticatorConfig allows the specification of any - additional user or role mappings for use when generating the aws-iam-authenticator - configuration. If this is nil the default configuration is still - generated for the cluster. - properties: - mapRoles: - description: RoleMappings is a list of role mappings - items: - description: RoleMapping represents a mapping from a IAM role - to Kubernetes users and groups. - properties: - groups: - description: Groups is a list of kubernetes RBAC groups - items: - type: string - type: array - rolearn: - description: RoleARN is the AWS ARN for the role to map - minLength: 31 - type: string - username: - description: UserName is a kubernetes RBAC user subject - type: string - required: - - groups - - rolearn - - username - type: object - type: array - mapUsers: - description: UserMappings is a list of user mappings - items: - description: UserMapping represents a mapping from an IAM user - to Kubernetes users and groups. - properties: - groups: - description: Groups is a list of kubernetes RBAC groups - items: - type: string - type: array - userarn: - description: UserARN is the AWS ARN for the user to map - minLength: 31 - type: string - username: - description: UserName is a kubernetes RBAC user subject - type: string - required: - - groups - - userarn - - username - type: object - type: array - type: object - identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling the managed control plane. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating system - used to look up machine images when a machine does not specify an - AMI. When set, this will be used for all cluster machines unless - a machine specifies a different ImageLookupBaseOS. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look up - machine images when a machine does not specify an AMI. When set, - this will be used for all cluster machines unless a machine specifies - a different ImageLookupOrg. Supports substitutions for {{.BaseOS}} - and {{.K8sVersion}} with the base OS and kubernetes version, respectively. - The BaseOS will be the value in ImageLookupBaseOS or ubuntu (the - default), and the kubernetes version as defined by the packages - produced by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to look up - machine images when a machine does not specify an AMI. When set, - this will be used for all cluster machines unless a machine specifies - a different ImageLookupOrg. - type: string - kubeProxy: - description: KubeProxy defines managed attributes of the kube-proxy - daemonset - properties: - disable: - default: false - description: Disable set to true indicates that kube-proxy should - be disabled. With EKS clusters kube-proxy is automatically installed - into the cluster. For clusters where you want to use kube-proxy - functionality that is provided with an alternate CNI, this option - provides a way to specify that the kube-proxy daemonset should - be deleted. You cannot set this to true if you are using the - Amazon kube-proxy addon. - type: boolean - type: object - logging: - description: Logging specifies which EKS Cluster logs should be enabled. - Entries for each of the enabled logs will be sent to CloudWatch - properties: - apiServer: - default: false - description: APIServer indicates if the Kubernetes API Server - log (kube-apiserver) shoulkd be enabled - type: boolean - audit: - default: false - description: Audit indicates if the Kubernetes API audit log should - be enabled - type: boolean - authenticator: - default: false - description: Authenticator indicates if the iam authenticator - log should be enabled - type: boolean - controllerManager: - default: false - description: ControllerManager indicates if the controller manager - (kube-controller-manager) log should be enabled - type: boolean - scheduler: - default: false - description: Scheduler indicates if the Kubernetes scheduler (kube-scheduler) - log should be enabled - type: boolean - required: - - apiServer - - audit - - authenticator - - controllerManager - - scheduler - type: object - network: - description: NetworkSpec encapsulates all things related to AWS network. - properties: - additionalControlPlaneIngressRules: - description: AdditionalControlPlaneIngressRules is an optional - set of ingress rules to add to the control plane - 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: - description: Description provides extended information about - the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress rule. - Accepted values are "-1" (all), "4" (IP in IP),"tcp", - "udp", "icmp", and "58" (ICMPv6), "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access from. - Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: The security group role to allow access from. - Cannot be specified with CidrBlocks. The field will be - combined with source security group IDs if specified. - items: - description: SecurityGroupRole defines the unique role - of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - cni: - description: CNI configuration - properties: - cniIngressRules: - description: CNIIngressRules specify rules to apply to control - plane and worker node security groups. The source for the - rule will be set to control plane and worker security group - IDs. - items: - description: CNIIngressRule defines an AWS ingress rule - for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the protocol - type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: SecurityGroupOverrides is an optional set of security - groups to use for cluster instances This is optional - if not - provided new security groups will be created for the cluster - type: object - 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. If you're bringing your subnet, set the - AWS subnet-id here, it must start with `subnet-`. \n When - the VPC is managed by CAPA, and you'd like the provider - to create a subnet for you, the id can be set to any placeholder - value that does not start with `subnet-`; upon creation, - the subnet AWS identifier will be populated in the `ResourceID` - field and the `id` field is going to be used as the subnet - name. If you specify a tag called `Name`, it takes precedence." - type: string - ipv6CidrBlock: - description: IPv6CidrBlock is the IPv6 CIDR block to be - used when the provider creates a managed VPC. A subnet - can have an IPv4 and an IPv6 address. IPv6 is only supported - in managed clusters, this field cannot be set on AWSCluster - object. - type: string - isIpv6: - description: IsIPv6 defines the subnet as an IPv6 subnet. - A subnet is IPv6 when it is associated with a VPC that - has IPv6 enabled. IPv6 is only supported in managed clusters, - this field cannot be set on AWSCluster object. - type: boolean - 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 - resourceID: - description: ResourceID is the subnet identifier from AWS, - READ ONLY. This field is populated when the provider manages - the 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 - required: - - id - type: object - type: array - x-kubernetes-list-map-keys: - - id - x-kubernetes-list-type: map - vpc: - description: VPC configuration. - properties: - availabilityZoneSelection: - default: Ordered - description: 'AvailabilityZoneSelection specifies how AZs - should be selected if there are more AZs in a region than - specified by AvailabilityZoneUsageLimit. There are 2 selection - schemes: Ordered - selects based on alphabetical order Random - - selects AZs randomly in a region Defaults to Ordered' - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: AvailabilityZoneUsageLimit specifies the maximum - number of availability zones (AZ) that should be used in - a region when automatically creating subnets. If a region - has more than this number of AZs then this number of AZs - will be picked randomly when creating default subnets. Defaults - to 3 - minimum: 1 - type: integer - cidrBlock: - description: CidrBlock is the CIDR block to be used when the - provider creates a managed VPC. Defaults to 10.0.0.0/16. - Mutually exclusive with IPAMPool. - 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 - ipamPool: - description: IPAMPool defines the IPAMv4 pool to be used for - VPC. Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this provider - should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool this provider - should use to create VPC. - type: string - netmaskLength: - description: The netmask length of the IPv4 CIDR you want - to allocate to VPC from an Amazon VPC IP Address Manager - (IPAM) pool. Defaults to /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - ipv6: - description: IPv6 contains ipv6 specific settings for the - network. Supported only in managed clusters. This field - cannot be set on AWSCluster object. - properties: - cidrBlock: - description: CidrBlock is the CIDR block provided by Amazon - when VPC has enabled IPv6. Mutually exclusive with IPAMPool. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the id of - the egress only internet gateway associated with an - IPv6 enabled VPC. - type: string - ipamPool: - description: IPAMPool defines the IPAMv6 pool to be used - for VPC. Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this provider - should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool this - provider should use to create VPC. - type: string - netmaskLength: - description: The netmask length of the IPv4 CIDR you - want to allocate to VPC from an Amazon VPC IP Address - Manager (IPAM) pool. Defaults to /16 for IPv4 if - not specified. - format: int64 - type: integer - type: object - poolId: - description: PoolID is the IP pool which must be defined - in case of BYO IP is defined. Must be specified if CidrBlock - is set. Mutually exclusive with IPAMPool. - type: string - type: object - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the resource. - type: object - type: object - type: object - oidcIdentityProviderConfig: - description: IdentityProviderconfig is used to specify the oidc provider - config to be attached with this eks cluster - properties: - clientId: - description: This is also known as audience. The ID for the client - application that makes authentication requests to the OpenID - identity provider. - type: string - groupsClaim: - description: The JWT claim that the provider uses to return your - groups. - type: string - groupsPrefix: - description: 'The prefix that is prepended to group claims to - prevent clashes with existing names (such as system: groups). - For example, the valueoidc: will create group names like oidc:engineering - and oidc:infra.' - type: string - identityProviderConfigName: - description: "The name of the OIDC provider configuration. \n - IdentityProviderConfigName is a required field" - type: string - issuerUrl: - description: The URL of the OpenID identity provider that allows - the API server to discover public signing keys for verifying - tokens. The URL must begin with https:// and should correspond - to the iss claim in the provider's OIDC ID tokens. Per the OIDC - standard, path components are allowed but query parameters are - not. Typically the URL consists of only a hostname, like https://server.example.org - or https://example.com. This URL should point to the level below - .well-known/openid-configuration and must be publicly accessible - over the internet. - type: string - requiredClaims: - additionalProperties: - type: string - description: The key value pairs that describe required claims - in the identity token. If set, each claim is verified to be - present in the token with a matching value. For the maximum - number of claims that you can require, see Amazon EKS service - quotas (https://docs.aws.amazon.com/eks/latest/userguide/service-quotas.html) - in the Amazon EKS User Guide. - type: object - tags: - additionalProperties: - type: string - description: tags to apply to oidc identity provider association - type: object - usernameClaim: - description: The JSON Web Token (JWT) claim to use as the username. - The default is sub, which is expected to be a unique identifier - of the end user. You can choose other claims, such as email - or name, depending on the OpenID identity provider. Claims other - than email are prefixed with the issuer URL to prevent naming - clashes with other plug-ins. - type: string - usernamePrefix: - description: The prefix that is prepended to username claims to - prevent clashes with existing names. If you do not provide this - field, and username is a value other than email, the prefix - defaults to issuerurl#. You can use the value - to disable all - prefixing. - type: string - type: object - region: - description: The AWS Region the cluster lives in. - type: string - roleAdditionalPolicies: - description: RoleAdditionalPolicies allows you to attach additional - polices to the control plane role. You must enable the EKSAllowAddRoles - feature flag to incorporate these into the created role. - items: - type: string - type: array - roleName: - description: RoleName specifies the name of IAM role that gives EKS - permission to make API calls. If the role is pre-existing we will - treat it as unmanaged and not delete it on deletion. If the EKSEnableIAM - feature flag is true and no name is supplied then a role is created. - minLength: 2 - type: string - secondaryCidrBlock: - description: SecondaryCidrBlock is the additional CIDR range to use - for pod IPs. Must be within the 100.64.0.0/10 or 198.19.0.0/16 range. - type: string - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - bastion host. Valid values are empty string (do not use SSH keys), - a valid SSH key name, or omitted (use the default SSH key name) - type: string - tokenMethod: - default: iam-authenticator - description: TokenMethod is used to specify the method for obtaining - a client token for communicating with EKS iam-authenticator - obtains - a client token using iam-authentictor aws-cli - obtains a client - token using the AWS CLI Defaults to iam-authenticator - enum: - - iam-authenticator - - aws-cli + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map + type: object + datacenter: + description: Datacenter is the name or inventory path of the datacenter + in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, in GiB. + Defaults to the eponymous property value in the template from which + the virtual machine is cloned. + format: int32 + type: integer + failureDomain: + description: FailureDomain is the failure domain unique identifier + this Machine should be attached to, as defined in Cluster API. For + this infrastructure provider, the name is equivalent to the name + of the VSphereDeploymentZone. type: string - version: - description: Version defines the desired Kubernetes version. If no - version number is supplied then the latest version of Kubernetes - that EKS supports will be used. - minLength: 2 - pattern: ^v?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.?(\.0|[1-9][0-9]*)?$ + folder: + description: Folder is the name or inventory path of the folder in + which the virtual machine is created/located. type: string - vpcCni: - description: VpcCni is used to set configuration options for the VPC - CNI plugin + memoryMiB: + description: MemoryMiB is the size of a virtual machine's memory, + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this machine's + VM. properties: - env: - description: Env defines a list of environment variables to apply - to the `aws-node` DaemonSet + devices: + description: Devices is the list of network devices used by the + virtual machine. TODO(akutz) Make sure at least one network + matches the ClusterSpec.CloudProviderConfiguration.Network.Name items: - description: EnvVar represents an environment variable present - in a Container. + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. properties: - name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. + deviceName: + description: DeviceName may be used to explicitly assign + a name to the network device as it exists in the guest + operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether or not + to use DHCP for IPv4 on this device. If true then IPAddrs + should not contain any IPv4 addresses. + type: boolean + dhcp6: + description: DHCP6 is a flag that indicates whether or not + to use DHCP for IPv6 on this device. If true then IPAddrs + should not contain any IPv6 addresses. + type: boolean + gateway4: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP6 is false. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 and/or + IPv6 addresses to assign to this device. IP addresses + must also specify the segment length in CIDR notation. + Required when DHCP4 and DHCP6 are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by this device. + It is generally a good idea to omit this field and allow + a MAC address to be generated. Please note that this value + must use the VMware OUI to work with the in-tree vSphere + cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission Unit + size in bytes. + format: int64 + type: integer + nameservers: + description: Nameservers is a list of IPv4 and/or IPv6 addresses + used as DNS nameservers. Please note that Linux allows + only three nameservers (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere network + to which the device will be connected. type: string - value: - description: 'Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in - the container and any service environment variables. If - a variable cannot be resolved, the reference in the input - string will be unchanged. Double $$ are reduced to a single - $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless - of whether the variable exists or not. Defaults to "".' + routes: + description: Routes is a list of optional, static routes + applied to the device. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains used + when resolving IP addresses with DNS. + items: + type: string + type: array + required: + - networkName + type: object + type: array + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR for the + Kubernetes API server endpoint on this machine + type: string + routes: + description: Routes is a list of optional, static routes applied + to the virtual machine. + items: + description: NetworkRouteSpec defines a static network route. + properties: + metric: + description: Metric is the weight/priority of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?' - type: string - optional: - description: Specify whether the ConfigMap or its - key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports metadata.name, - metadata.namespace, `metadata.labels['''']`, - `metadata.annotations['''']`, spec.nodeName, - spec.serviceAccountName, status.hostIP, status.podIP, - status.podIPs.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the - specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: 'Selects a resource of the container: only - resources limits and requests (limits.cpu, limits.memory, - limits.ephemeral-storage, requests.cpu, requests.memory - and requests.ephemeral-storage) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?' - type: string - optional: - description: Specify whether the Secret or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object required: - - name + - metric + - to + - via type: object type: array + required: + - devices type: object + numCPUs: + description: NumCPUs is the number of virtual processors in a virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to distribute + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + format: int32 + type: integer + providerID: + description: ProviderID is the virtual machine's BIOS UUID formated + as vsphere://12345678-1234-1234-1234-123456789abc + type: string + resourcePool: + description: ResourcePool is the name or inventory path of the resource + pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which to create + a linked clone. This field is ignored if LinkedClone is not enabled. + Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use with this + Virtual Machine + type: string + template: + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When this is set to empty, + this VirtualMachine would be created without TLS certificate validation + of the communication between Cluster API Provider vSphere and the + VMware vCenter server. + type: string + required: + - network + - template type: object status: - description: AWSManagedControlPlaneStatus defines the observed state of - an Amazon EKS Cluster. + description: VSphereMachineStatus defines the observed state of VSphereMachine properties: - addons: - description: Addons holds the current status of the EKS addons + addresses: + description: Addresses contains the VSphere instance associated addresses. items: - description: AddonState represents the state of an addon. + description: MachineAddress contains information for the node's + address. properties: - arn: - description: ARN is the AWS ARN of the addon + address: + description: The machine address. type: string - createdAt: - description: CreatedAt is the date and time the addon was created - at - format: date-time + type: + description: Machine address type, one of Hostname, ExternalIP + or InternalIP. type: string - issues: - description: Issues is a list of issue associated with the addon - items: - description: AddonIssue represents an issue with an addon. - properties: - code: - description: Code is the issue code - type: string - message: - description: Message is the textual description of the - issue - type: string - resourceIds: - description: ResourceIDs is a list of resource ids for - the issue - items: - type: string - type: array - type: object - type: array - modifiedAt: - description: ModifiedAt is the date and time the addon was last - modified + required: + - address + - type + type: object + type: array + conditions: + description: Conditions defines current service state of the VSphereMachine. + items: + description: Condition defines an observation of a Cluster API resource + operational state. + properties: + lastTransitionTime: + description: Last time the condition transitioned from one status + to another. This should be when the underlying condition changed. + If that is not known, then using the time when the API field + changed is acceptable. format: date-time type: string - name: - description: Name is the name of the addon + message: + description: A human readable message indicating details about + the transition. This field may be empty. + type: string + reason: + description: The reason for the condition's last transition + in CamelCase. The specific API may choose whether or not this + field is considered a guaranteed API. This field may not be + empty. type: string - serviceAccountRoleARN: - description: ServiceAccountRoleArn is the ARN of the IAM role - used for the service account + severity: + description: Severity provides an explicit classification of + Reason code, so the users or machines can immediately understand + the current situation and act accordingly. The Severity field + MUST be set only when Status=False. type: string status: - description: Status is the status of the addon + description: Status of the condition, one of True, False, Unknown. type: string - version: - description: Version is the version of the addon to use + type: + description: Type of condition in CamelCase or in foo.example.com/CamelCase. + Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. type: string required: - - arn - - name - - version + - status + - type type: object type: array - bastion: - description: Bastion holds details of the instance that is used as - a bastion jump box - properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - availabilityZone: - description: Availability zone of instance - type: string - 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 - instanceMetadataOptions: - description: InstanceMetadataOptions is the metadata options for - the EC2 instance. - properties: - httpEndpoint: - default: enabled - description: "Enables or disables the HTTP metadata endpoint - on your instances. \n If you specify a value of disabled, - you cannot access your instance metadata. \n Default: enabled" - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: "The desired HTTP PUT response hop limit for - instance metadata requests. The larger the number, the further - instance metadata requests can travel. \n Default: 1" - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: "The state of token usage for your instance metadata - requests. \n If the state is optional, you can choose to - retrieve instance metadata with or without a session token - on your request. If you retrieve the IAM role credentials - without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session - token, the version 2.0 role credentials are returned. \n - If the state is required, you must send a session token - with any instance metadata retrieval requests. In this state, - retrieving the IAM role credentials always returns the version - 2.0 credentials; the version 1.0 credentials are not available. - \n Default: optional" - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: "Set to enabled to allow access to instance tags - from the instance metadata. Set to disabled to turn off - access to instance tags from the instance metadata. For - more information, see Work with instance tags using the - instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - \n Default: disabled" - enum: - - enabled - - disabled + failureMessage: + description: "FailureMessage will be set in the event that there is + a terminal problem reconciling the Machine and will contain a more + verbose string suitable for logging and human consumption. \n This + field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over time (like + service outages), but instead indicate that something is fundamentally + wrong with the Machine's spec or the configuration of the controller, + and that manual intervention is required. Examples of terminal errors + would be invalid combinations of settings in the spec, values that + are unsupported by the controller, or the responsible controller + itself being critically misconfigured. \n Any transient errors that + occur during the reconciliation of Machines can be added as events + to the Machine object and/or logged in the controller's output." + type: string + failureReason: + description: "FailureReason will be set in the event that there is + a terminal problem reconciling the Machine and will contain a succinct + value suitable for machine interpretation. \n This field should + not be set for transitive errors that a controller faces that are + expected to be fixed automatically over time (like service outages), + but instead indicate that something is fundamentally wrong with + the Machine's spec or the configuration of the controller, and that + manual intervention is required. Examples of terminal errors would + be invalid combinations of settings in the spec, values that are + unsupported by the controller, or the responsible controller itself + being critically misconfigured. \n Any transient errors that occur + during the reconciliation of Machines can be added as events to + the Machine object and/or logged in the controller's output." + type: string + network: + description: Network returns the network status for each of the machine's + configured network interfaces. + items: + description: NetworkStatus provides information about one of a VM's + networks. + properties: + connected: + description: Connected is a flag that indicates whether this + network is currently connected to the VM. + type: boolean + ipAddrs: + description: IPAddrs is one or more IP addresses reported by + vm-tools. + items: type: string - type: object - instanceState: - description: The current state of the instance. - type: string - networkInterfaces: - description: Specifies ENIs attached to instance - items: + type: array + macAddr: + description: MACAddr is the MAC address of the network device. type: string - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. + networkName: + description: NetworkName is the name of the network. + type: string + required: + - macAddr + type: object + type: array + ready: + description: Ready is true when the provider resource is ready. + type: boolean + type: object + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - description: Cluster to which this VSphereMachine belongs + jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name + name: Cluster + type: string + - description: Machine ready status + jsonPath: .status.ready + name: Ready + type: string + - description: VSphereMachine instance ID + jsonPath: .spec.providerID + name: ProviderID + type: string + - description: Machine object which owns this VSphereMachine + jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name + name: Machine + priority: 1 + type: string + - description: Time duration since creation of Machine + jsonPath: .metadata.creationTimestamp + name: Age + type: date + deprecated: true + name: v1alpha4 + schema: + openAPIV3Schema: + description: "VSphereMachine is the Schema for the vspheremachines API \n + Deprecated: This type will be removed in one of the next releases." + 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: VSphereMachineSpec defines the desired state of VSphereMachine + properties: + cloneMode: + description: CloneMode specifies the type of clone operation. The + LinkedClone mode is only support for templates that have at least + one snapshot. If the template has no snapshots, then CloneMode defaults + to FullClone. When LinkedClone mode is enabled the DiskGiB field + is ignored as it is not possible to expand disks of linked clones. + Defaults to LinkedClone, but fails gracefully to FullClone if the + source of the clone operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: + type: string + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map + type: object + datacenter: + description: Datacenter is the name or inventory path of the datacenter + in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, in GiB. + Defaults to the eponymous property value in the template from which + the virtual machine is cloned. + format: int32 + type: integer + failureDomain: + description: FailureDomain is the failure domain unique identifier + this Machine should be attached to, as defined in Cluster API. For + this infrastructure provider, the name is equivalent to the name + of the VSphereDeploymentZone. + type: string + folder: + description: Folder is the name or inventory path of the folder in + which the virtual machine is created/located. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's memory, + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this machine's + VM. + properties: + devices: + description: Devices is the list of network devices used by the + virtual machine. TODO(akutz) Make sure at least one network + matches the ClusterSpec.CloudProviderConfiguration.Network.Name items: - description: Volume encapsulates the configuration options for - the storage device. + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. properties: deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. + description: DeviceName may be used to explicitly assign + a name to the network device as it exists in the guest + operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether or not + to use DHCP for IPv4 on this device. If true then IPAddrs + should not contain any IPv4 addresses. type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by - the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size or - 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. + dhcp6: + description: DHCP6 is a flag that indicates whether or not + to use DHCP for IPv6 on this device. If true then IPAddrs + should not contain any IPv6 addresses. + type: boolean + gateway4: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP6 is false. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 and/or + IPv6 addresses to assign to this device. IP addresses + must also specify the segment length in CIDR notation. + Required when DHCP4 and DHCP6 are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by this device. + It is generally a good idea to omit this field and allow + a MAC address to be generated. Please note that this value + must use the VMware OUI to work with the in-tree vSphere + cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission Unit + size in bytes. format: int64 type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). + nameservers: + description: Nameservers is a list of IPv4 and/or IPv6 addresses + used as DNS nameservers. Please note that Linux allows + only three nameservers (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere network + to which the device will be connected. type: string + routes: + description: Routes is a list of optional, static routes + applied to the device. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains used + when resolving IP addresses with DNS. + items: + type: string + type: array required: - - size + - networkName type: object type: array - placementGroupName: - description: PlacementGroupName specifies the name of the placement - group in which to launch the instance. - 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 - rootVolume: - description: Configuration options for the root storage volume. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by the - controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - securityGroupIds: - description: SecurityGroupIDs are one or more security group IDs - this instance belongs to. - items: - type: string - type: array - spotMarketOptions: - description: SpotMarketOptions option for configuring instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: The name of the SSH key pair. - type: string - 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 - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR for the + Kubernetes API server endpoint on this machine type: string - 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 - volumeIDs: - description: IDs of the instance's volumes + routes: + description: Routes is a list of optional, static routes applied + to the virtual machine. items: - type: string + description: NetworkRouteSpec defines a static network route. + properties: + metric: + description: Metric is the weight/priority of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object type: array required: - - id + - devices type: object + numCPUs: + description: NumCPUs is the number of virtual processors in a virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to distribute + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + format: int32 + type: integer + providerID: + description: ProviderID is the virtual machine's BIOS UUID formated + as vsphere://12345678-1234-1234-1234-123456789abc + type: string + resourcePool: + description: ResourcePool is the name or inventory path of the resource + pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which to create + a linked clone. This field is ignored if LinkedClone is not enabled. + Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use with this + Virtual Machine + type: string + template: + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When this is set to empty, + this VirtualMachine would be created without TLS certificate validation + of the communication between Cluster API Provider vSphere and the + VMware vCenter server. + type: string + required: + - network + - template + type: object + status: + description: VSphereMachineStatus defines the observed state of VSphereMachine + properties: + addresses: + description: Addresses contains the VSphere instance associated addresses. + items: + description: MachineAddress contains information for the node's + address. + properties: + address: + description: The machine address. + type: string + type: + description: Machine address type, one of Hostname, ExternalIP + or InternalIP. + type: string + required: + - address + - type + type: object + type: array conditions: - description: Conditions specifies the cpnditions for the managed control - plane + description: Conditions defines current service state of the VSphereMachine. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -8829,393 +3029,70 @@ spec: important. type: string required: - - lastTransitionTime - status - type type: object type: array - externalManagedControlPlane: - default: true - description: ExternalManagedControlPlane indicates to cluster-api - that the control plane is managed by an external service such as - AKS, EKS, GKE, etc. - type: boolean - failureDomains: - additionalProperties: - description: FailureDomainSpec is the Schema for Cluster API failure - domains. It allows controllers to understand how many failure - domains a cluster can optionally span across. - properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. - type: boolean - type: object - description: FailureDomains specifies a list fo available availability - zones that can be used - type: object failureMessage: - description: ErrorMessage indicates that there is a terminal problem - reconciling the state, and will be set to a descriptive error message. + description: "FailureMessage will be set in the event that there is + a terminal problem reconciling the Machine and will contain a more + verbose string suitable for logging and human consumption. \n This + field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over time (like + service outages), but instead indicate that something is fundamentally + wrong with the Machine's spec or the configuration of the controller, + and that manual intervention is required. Examples of terminal errors + would be invalid combinations of settings in the spec, values that + are unsupported by the controller, or the responsible controller + itself being critically misconfigured. \n Any transient errors that + occur during the reconciliation of Machines can be added as events + to the Machine object and/or logged in the controller's output." type: string - identityProviderStatus: - description: IdentityProviderStatus holds the status for associated - identity provider - properties: - arn: - description: ARN holds the ARN of associated identity provider - type: string - status: - description: Status holds current status of associated identity - provider - type: string - type: object - initialized: - description: Initialized denotes whether or not the control plane - has the uploaded kubernetes config-map. - type: boolean - networkStatus: - description: Networks holds details about the AWS networking resources - used by the control plane - properties: - apiServerElb: - description: APIServerELB is the Kubernetes api server load balancer. - properties: - arn: - description: ARN of the load balancer. Unlike the ClassicLB, - ARN is used mostly to define and get it. - type: string - attributes: - description: ClassicElbAttributes defines extra attributes - associated with the load balancer. - properties: - crossZoneLoadBalancing: - description: CrossZoneLoadBalancing enables the classic - load balancer load balancing. - type: boolean - 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 - availabilityZones: - description: AvailabilityZones is an array of availability - zones in the VPC attached to the load balancer. - items: - type: string - type: array - dnsName: - description: DNSName is the dns name of the load balancer. - type: string - elbAttributes: - additionalProperties: - type: string - description: ELBAttributes defines extra attributes associated - with v2 load balancers. - type: object - elbListeners: - description: ELBListeners is an array of listeners associated - with the load balancer. There must be at least one. - items: - description: Listener defines an AWS network load balancer - listener. - properties: - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - targetGroup: - description: TargetGroupSpec specifies target group - settings for a given listener. This is created first, - and the ARN is then passed to the listener. - properties: - name: - description: Name of the TargetGroup. Must be unique - over the same group of listeners. - type: string - port: - description: Port is the exposed port - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - enum: - - tcp - - tls - - udp - - TCP - - TLS - - UDP - type: string - targetGroupHealthCheck: - description: HealthCheck is the elb health check - associated with the load balancer. - properties: - intervalSeconds: - format: int64 - type: integer - path: - type: string - port: - type: string - protocol: - type: string - thresholdCount: - format: int64 - type: integer - timeoutSeconds: - format: int64 - type: integer - type: object - vpcId: - type: string - required: - - name - - port - - protocol - - vpcId - type: object - required: - - port - - protocol - - targetGroup - type: object - type: array - 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: ClassicELBListeners 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: ELBProtocol defines listener protocols - for a load balancer. - type: string - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - required: - - instancePort - - instanceProtocol - - port - - protocol - type: object - type: array - loadBalancerType: - description: LoadBalancerType sets the type for a load balancer. - The default type is classic. - enum: - - classic - - elb - - alb - - nlb - type: string - 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. + failureReason: + description: "FailureReason will be set in the event that there is + a terminal problem reconciling the Machine and will contain a succinct + value suitable for machine interpretation. \n This field should + not be set for transitive errors that a controller faces that are + expected to be fixed automatically over time (like service outages), + but instead indicate that something is fundamentally wrong with + the Machine's spec or the configuration of the controller, and that + manual intervention is required. Examples of terminal errors would + be invalid combinations of settings in the spec, values that are + unsupported by the controller, or the responsible controller itself + being critically misconfigured. \n Any transient errors that occur + during the reconciliation of Machines can be added as events to + the Machine object and/or logged in the controller's output." + type: string + network: + description: Network returns the network status for each of the machine's + configured network interfaces. + items: + description: NetworkStatus provides information about one of a VM's + networks. + properties: + connected: + description: Connected is a flag that indicates whether this + network is currently connected to the VM. + type: boolean + ipAddrs: + description: IPAddrs is one or more IP addresses reported by + vm-tools. + items: 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 - natGatewaysIPs: - description: NatGatewaysIPs contains the public IPs of the NAT - Gateways - items: - type: string - type: array - 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: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: - type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP in - IP),"tcp", "udp", "icmp", and "58" (ICMPv6), "50" - (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: - type: string - type: array - sourceSecurityGroupRoles: - description: The security group role to allow access - from. Cannot be specified with CidrBlocks. The field - will be combined with source security group IDs - if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional - type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - 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 - - 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 - oidcProvider: - description: OIDCProvider holds the status of the identity provider - for this cluster - properties: - arn: - description: ARN holds the ARN of the provider - type: string - trustPolicy: - description: TrustPolicy contains the boilerplate IAM trust policy - to use for IRSA - type: string - type: object + type: array + macAddr: + description: MACAddr is the MAC address of the network device. + type: string + networkName: + description: NetworkName is the name of the network. + type: string + required: + - macAddr + type: object + type: array ready: - default: false - description: Ready denotes that the AWSManagedControlPlane API Server - is ready to receive requests and that the VPC infra is ready. + description: Ready is true when the provider resource is ready. type: boolean - required: - - ready type: object type: object served: true @@ -9223,32 +3100,31 @@ spec: subresources: status: {} - additionalPrinterColumns: - - description: Cluster to which this AWSManagedControl belongs + - description: Cluster to which this VSphereMachine belongs jsonPath: .metadata.labels.cluster\.x-k8s\.io/cluster-name name: Cluster type: string - - description: Control plane infrastructure is ready for worker nodes + - description: Machine ready status jsonPath: .status.ready name: Ready type: string - - description: AWS VPC the control plane is using - jsonPath: .spec.network.vpc.id - name: VPC + - description: VSphereMachine instance ID + jsonPath: .spec.providerID + name: ProviderID type: string - - description: API Endpoint - jsonPath: .spec.controlPlaneEndpoint.host - name: Endpoint + - description: Machine object which owns with this VSphereMachine + jsonPath: .metadata.ownerReferences[?(@.kind=="Machine")].name + name: Machine priority: 1 type: string - - description: Bastion IP address for breakglass access - jsonPath: .status.bastion.publicIp - name: Bastion IP - type: string - name: v1beta2 + - description: Time duration since creation of Machine + jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta1 schema: openAPIV3Schema: - description: AWSManagedControlPlane is the schema for the Amazon EKS Managed - Control Plane API. + description: VSphereMachine is the Schema for the vspheremachines API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -9263,1133 +3139,455 @@ spec: metadata: type: object spec: - description: AWSManagedControlPlaneSpec defines the desired state of an - Amazon EKS Cluster. + description: VSphereMachineSpec defines the desired state of VSphereMachine properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to AWS - resources managed by the AWS provider, in addition to the ones added - by default. - type: object - addons: - description: Addons defines the EKS addons to enable with the EKS - cluster. + additionalDisksGiB: + description: AdditionalDisksGiB holds the sizes of additional disks + of the virtual machine, in GiB Defaults to the eponymous property + value in the template from which the virtual machine is cloned. items: - description: Addon represents a EKS addon. - properties: - configuration: - description: Configuration of the EKS addon - type: string - conflictResolution: - default: overwrite - description: ConflictResolution is used to declare what should - happen if there are parameter conflicts. Defaults to none - enum: - - overwrite - - none - type: string - name: - description: Name is the name of the addon - minLength: 2 - type: string - serviceAccountRoleARN: - description: ServiceAccountRoleArn is the ARN of an IAM role - to bind to the addons service account - type: string - version: - description: Version is the version of the addon to use - type: string - required: - - name - - version - type: object + format: int32 + type: integer type: array - associateOIDCProvider: - default: false - description: AssociateOIDCProvider can be enabled to automatically - create an identity provider for the controller for use with IAM - roles for service accounts - type: boolean - bastion: - description: Bastion contains options to configure the bastion host. - properties: - allowedCIDRBlocks: - description: AllowedCIDRBlocks is a list of CIDR blocks allowed - to access the bastion host. They are set as ingress rules for - the Bastion host's Security Group (defaults to 0.0.0.0/0). - items: - type: string - type: array - ami: - description: AMI will use the specified AMI to boot the bastion. - If not specified, the AMI will default to one picked out in - public space. - type: string - disableIngressRules: - description: DisableIngressRules will ensure there are no Ingress - rules in the bastion host's security group. Requires AllowedCIDRBlocks - to be empty. - type: boolean - enabled: - description: Enabled allows this provider to create a bastion - host instance with a public ip to access the VPC private network. - type: boolean - instanceType: - description: InstanceType will use the specified instance type - for the bastion. If not specified, Cluster API Provider AWS - will use t3.micro for all regions except us-east-1, where t2.micro - will be the default. - type: string - type: object - controlPlaneEndpoint: - description: ControlPlaneEndpoint represents the endpoint used to - communicate with the control plane. - 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. - format: int32 - type: integer - required: - - host - - port - type: object - eksClusterName: - description: EKSClusterName allows you to specify the name of the - EKS cluster in AWS. If you don't specify a name then a default name - will be created based on the namespace and name of the managed control - plane. - type: string - encryptionConfig: - description: EncryptionConfig specifies the encryption configuration - for the cluster - properties: - provider: - description: Provider specifies the ARN or alias of the CMK (in - AWS KMS) - type: string - resources: - description: Resources specifies the resources to be encrypted - items: - type: string - type: array - type: object - endpointAccess: - description: Endpoints specifies access to this cluster's control - plane endpoints - properties: - private: - description: Private points VPC-internal control plane access - to the private endpoint - type: boolean - public: - description: Public controls whether control plane endpoints are - publicly accessible - type: boolean - publicCIDRs: - description: PublicCIDRs specifies which blocks can access the - public endpoint - items: - type: string - type: array + cloneMode: + description: CloneMode specifies the type of clone operation. The + LinkedClone mode is only support for templates that have at least + one snapshot. If the template has no snapshots, then CloneMode defaults + to FullClone. When LinkedClone mode is enabled the DiskGiB field + is ignored as it is not possible to expand disks of linked clones. + Defaults to LinkedClone, but fails gracefully to FullClone if the + source of the clone operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: + type: string + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map type: object - iamAuthenticatorConfig: - description: IAMAuthenticatorConfig allows the specification of any - additional user or role mappings for use when generating the aws-iam-authenticator - configuration. If this is nil the default configuration is still - generated for the cluster. + datacenter: + description: Datacenter is the name or inventory path of the datacenter + in which the virtual machine is created/located. Defaults to * which + selects the default datacenter. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, in GiB. + Defaults to the eponymous property value in the template from which + the virtual machine is cloned. + format: int32 + type: integer + failureDomain: + description: FailureDomain is the failure domain unique identifier + this Machine should be attached to, as defined in Cluster API. For + this infrastructure provider, the name is equivalent to the name + of the VSphereDeploymentZone. + type: string + folder: + description: Folder is the name or inventory path of the folder in + which the virtual machine is created/located. + type: string + guestSoftPowerOffTimeout: + description: "GuestSoftPowerOffTimeout sets the wait timeout for shutdown + in the VM guest. The VM will be powered off forcibly after the timeout + if the VM is still up and running when the PowerOffMode is set to + trySoft. \n This parameter only applies when the PowerOffMode is + set to trySoft. \n If omitted, the timeout defaults to 5 minutes." + type: string + hardwareVersion: + description: HardwareVersion is the hardware version of the virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. Check the compatibility + with the ESXi version before setting the value. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's memory, + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this machine's + VM. properties: - mapRoles: - description: RoleMappings is a list of role mappings - items: - description: RoleMapping represents a mapping from a IAM role - to Kubernetes users and groups. - properties: - groups: - description: Groups is a list of kubernetes RBAC groups - items: - type: string - type: array - rolearn: - description: RoleARN is the AWS ARN for the role to map - minLength: 31 - type: string - username: - description: UserName is a kubernetes RBAC user subject - type: string - required: - - groups - - rolearn - - username - type: object - type: array - mapUsers: - description: UserMappings is a list of user mappings + devices: + description: Devices is the list of network devices used by the + virtual machine. TODO(akutz) Make sure at least one network + matches the ClusterSpec.CloudProviderConfiguration.Network.Name items: - description: UserMapping represents a mapping from an IAM user - to Kubernetes users and groups. + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. properties: - groups: - description: Groups is a list of kubernetes RBAC groups + addressesFromPools: + description: AddressesFromPools is a list of IPAddressPools + that should be assigned to IPAddressClaims. The machine's + cloud-init metadata will be populated with IPAddresses + fulfilled by an IPAM provider. items: - type: string + description: TypedLocalObjectReference contains enough + information to let you locate the typed referenced object + inside the same namespace. + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic type: array - userarn: - description: UserARN is the AWS ARN for the user to map - minLength: 31 - type: string - username: - description: UserName is a kubernetes RBAC user subject - type: string - required: - - groups - - userarn - - username - type: object - type: array - type: object - identityRef: - description: IdentityRef is a reference to a identity to be used when - reconciling the managed control plane. - properties: - kind: - description: Kind of the identity. - enum: - - AWSClusterControllerIdentity - - AWSClusterRoleIdentity - - AWSClusterStaticIdentity - type: string - name: - description: Name of the identity. - minLength: 1 - type: string - required: - - kind - - name - type: object - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating system - used to look up machine images when a machine does not specify an - AMI. When set, this will be used for all cluster machines unless - a machine specifies a different ImageLookupBaseOS. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look up - machine images when a machine does not specify an AMI. When set, - this will be used for all cluster machines unless a machine specifies - a different ImageLookupOrg. Supports substitutions for {{.BaseOS}} - and {{.K8sVersion}} with the base OS and kubernetes version, respectively. - The BaseOS will be the value in ImageLookupBaseOS or ubuntu (the - default), and the kubernetes version as defined by the packages - produced by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to look up - machine images when a machine does not specify an AMI. When set, - this will be used for all cluster machines unless a machine specifies - a different ImageLookupOrg. - type: string - kubeProxy: - description: KubeProxy defines managed attributes of the kube-proxy - daemonset - properties: - disable: - default: false - description: Disable set to true indicates that kube-proxy should - be disabled. With EKS clusters kube-proxy is automatically installed - into the cluster. For clusters where you want to use kube-proxy - functionality that is provided with an alternate CNI, this option - provides a way to specify that the kube-proxy daemonset should - be deleted. You cannot set this to true if you are using the - Amazon kube-proxy addon. - type: boolean - type: object - logging: - description: Logging specifies which EKS Cluster logs should be enabled. - Entries for each of the enabled logs will be sent to CloudWatch - properties: - apiServer: - default: false - description: APIServer indicates if the Kubernetes API Server - log (kube-apiserver) shoulkd be enabled - type: boolean - audit: - default: false - description: Audit indicates if the Kubernetes API audit log should - be enabled - type: boolean - authenticator: - default: false - description: Authenticator indicates if the iam authenticator - log should be enabled - type: boolean - controllerManager: - default: false - description: ControllerManager indicates if the controller manager - (kube-controller-manager) log should be enabled - type: boolean - scheduler: - default: false - description: Scheduler indicates if the Kubernetes scheduler (kube-scheduler) - log should be enabled - type: boolean - required: - - apiServer - - audit - - authenticator - - controllerManager - - scheduler - type: object - network: - description: NetworkSpec encapsulates all things related to AWS network. - properties: - additionalControlPlaneIngressRules: - description: AdditionalControlPlaneIngressRules is an optional - set of ingress rules to add to the control plane - 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. + deviceName: + description: DeviceName may be used to explicitly assign + a name to the network device as it exists in the guest + operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether or not + to use DHCP for IPv4 on this device. If true then IPAddrs + should not contain any IPv4 addresses. + type: boolean + dhcp4Overrides: + description: DHCP4Overrides allows for the control over + several DHCP behaviors. Overrides will only be applied + when the corresponding DHCP flag is set. Only configured + values will be sent, omitted values will default to distribution + defaults. Dependent on support in the network stack for + your distribution. For more information see the netplan + reference (https://netplan.io/reference#dhcp-overrides) + properties: + hostname: + description: Hostname is the name which will be sent + to the DHCP server instead of the machine's hostname. + type: string + routeMetric: + description: RouteMetric is used to prioritize routes + for devices. A lower metric for an interface will + have a higher priority. + type: integer + sendHostname: + description: SendHostname when `true`, the hostname + of the machine will be sent to the DHCP server. + type: boolean + useDNS: + description: UseDNS when `true`, the DNS servers in + the DHCP server will be used and take precedence. + type: boolean + useDomains: + description: UseDomains can take the values `true`, + `false`, or `route`. When `true`, the domain name + from the DHCP server will be used as the DNS search + domain for this device. When `route`, the domain name + from the DHCP response will be used for routing DNS + only, not for searching. + type: string + useHostname: + description: UseHostname when `true`, the hostname from + the DHCP server will be set as the transient hostname + of the machine. + type: boolean + useMTU: + description: UseMTU when `true`, the MTU from the DHCP + server will be set as the MTU of the device. + type: boolean + useNTP: + description: UseNTP when `true`, the NTP servers from + the DHCP server will be used by systemd-timesyncd + and take precedence. + type: boolean + useRoutes: + description: UseRoutes when `true`, the routes from + the DHCP server will be installed in the routing table. + type: string + type: object + dhcp6: + description: DHCP6 is a flag that indicates whether or not + to use DHCP for IPv6 on this device. If true then IPAddrs + should not contain any IPv6 addresses. + type: boolean + dhcp6Overrides: + description: DHCP6Overrides allows for the control over + several DHCP behaviors. Overrides will only be applied + when the corresponding DHCP flag is set. Only configured + values will be sent, omitted values will default to distribution + defaults. Dependent on support in the network stack for + your distribution. For more information see the netplan + reference (https://netplan.io/reference#dhcp-overrides) + properties: + hostname: + description: Hostname is the name which will be sent + to the DHCP server instead of the machine's hostname. + type: string + routeMetric: + description: RouteMetric is used to prioritize routes + for devices. A lower metric for an interface will + have a higher priority. + type: integer + sendHostname: + description: SendHostname when `true`, the hostname + of the machine will be sent to the DHCP server. + type: boolean + useDNS: + description: UseDNS when `true`, the DNS servers in + the DHCP server will be used and take precedence. + type: boolean + useDomains: + description: UseDomains can take the values `true`, + `false`, or `route`. When `true`, the domain name + from the DHCP server will be used as the DNS search + domain for this device. When `route`, the domain name + from the DHCP response will be used for routing DNS + only, not for searching. + type: string + useHostname: + description: UseHostname when `true`, the hostname from + the DHCP server will be set as the transient hostname + of the machine. + type: boolean + useMTU: + description: UseMTU when `true`, the MTU from the DHCP + server will be set as the MTU of the device. + type: boolean + useNTP: + description: UseNTP when `true`, the NTP servers from + the DHCP server will be used by systemd-timesyncd + and take precedence. + type: boolean + useRoutes: + description: UseRoutes when `true`, the routes from + the DHCP server will be installed in the routing table. + type: string + type: object + gateway4: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by this device. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 and/or + IPv6 addresses to assign to this device. IP addresses + must also specify the segment length in CIDR notation. + Required when DHCP4 and DHCP6 are both false. items: type: string type: array - description: - description: Description provides extended information about - the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. + macAddr: + description: MACAddr is the MAC address used by this device. + It is generally a good idea to omit this field and allow + a MAC address to be generated. Please note that this value + must use the VMware OUI to work with the in-tree vSphere + cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission Unit + size in bytes. format: int64 type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access from. - Cannot be specified with SourceSecurityGroupID. + nameservers: + description: Nameservers is a list of IPv4 and/or IPv6 addresses + used as DNS nameservers. Please note that Linux allows + only three nameservers (https://linux.die.net/man/5/resolv.conf). items: type: string type: array - protocol: - description: Protocol is the protocol for the ingress rule. - Accepted values are "-1" (all), "4" (IP in IP),"tcp", - "udp", "icmp", and "58" (ICMPv6), "50" (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" + networkName: + description: NetworkName is the name of the vSphere network + to which the device will be connected. type: string - sourceSecurityGroupIds: - description: The security group id to allow access from. - Cannot be specified with CidrBlocks. + routes: + description: Routes is a list of optional, static routes + applied to the device. items: - type: string + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object type: array - sourceSecurityGroupRoles: - description: The security group role to allow access from. - Cannot be specified with CidrBlocks. The field will be - combined with source security group IDs if specified. + searchDomains: + description: SearchDomains is a list of search domains used + when resolving IP addresses with DNS. items: - description: SecurityGroupRole defines the unique role - of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional type: string type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer required: - - description - - fromPort - - protocol - - toPort + - networkName type: object type: array - cni: - description: CNI configuration - properties: - cniIngressRules: - description: CNIIngressRules specify rules to apply to control - plane and worker node security groups. The source for the - rule will be set to control plane and worker security group - IDs. - items: - description: CNIIngressRule defines an AWS ingress rule - for CNI requirements. - properties: - description: - type: string - fromPort: - format: int64 - type: integer - protocol: - description: SecurityGroupProtocol defines the protocol - type for a security group rule. - type: string - toPort: - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - type: object - securityGroupOverrides: - additionalProperties: - type: string - description: SecurityGroupOverrides is an optional set of security - groups to use for cluster instances This is optional - if not - provided new security groups will be created for the cluster - type: object - subnets: - description: Subnets configuration. + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR for the + Kubernetes API server endpoint on this machine + type: string + routes: + description: Routes is a list of optional, static routes applied + to the virtual machine. items: - description: SubnetSpec configures an AWS Subnet. + description: NetworkRouteSpec defines a static network route. 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. If you're bringing your subnet, set the - AWS subnet-id here, it must start with `subnet-`. \n When - the VPC is managed by CAPA, and you'd like the provider - to create a subnet for you, the id can be set to any placeholder - value that does not start with `subnet-`; upon creation, - the subnet AWS identifier will be populated in the `ResourceID` - field and the `id` field is going to be used as the subnet - name. If you specify a tag called `Name`, it takes precedence." - type: string - ipv6CidrBlock: - description: IPv6CidrBlock is the IPv6 CIDR block to be - used when the provider creates a managed VPC. A subnet - can have an IPv4 and an IPv6 address. IPv6 is only supported - in managed clusters, this field cannot be set on AWSCluster - object. - type: string - isIpv6: - description: IsIPv6 defines the subnet as an IPv6 subnet. - A subnet is IPv6 when it is associated with a VPC that - has IPv6 enabled. IPv6 is only supported in managed clusters, - this field cannot be set on AWSCluster object. - type: boolean - 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 - resourceID: - description: ResourceID is the subnet identifier from AWS, - READ ONLY. This field is populated when the provider manages - the subnet. + metric: + description: Metric is the weight/priority of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. type: string - routeTableId: - description: RouteTableID is the routing table id associated - with the subnet. + via: + description: Via is an IPv4 or IPv6 address. type: string - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the - resource. - type: object required: - - id + - metric + - to + - via type: object type: array - x-kubernetes-list-map-keys: - - id - x-kubernetes-list-type: map - vpc: - description: VPC configuration. - properties: - availabilityZoneSelection: - default: Ordered - description: 'AvailabilityZoneSelection specifies how AZs - should be selected if there are more AZs in a region than - specified by AvailabilityZoneUsageLimit. There are 2 selection - schemes: Ordered - selects based on alphabetical order Random - - selects AZs randomly in a region Defaults to Ordered' - enum: - - Ordered - - Random - type: string - availabilityZoneUsageLimit: - default: 3 - description: AvailabilityZoneUsageLimit specifies the maximum - number of availability zones (AZ) that should be used in - a region when automatically creating subnets. If a region - has more than this number of AZs then this number of AZs - will be picked randomly when creating default subnets. Defaults - to 3 - minimum: 1 - type: integer - cidrBlock: - description: CidrBlock is the CIDR block to be used when the - provider creates a managed VPC. Defaults to 10.0.0.0/16. - Mutually exclusive with IPAMPool. - 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 - ipamPool: - description: IPAMPool defines the IPAMv4 pool to be used for - VPC. Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this provider - should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool this provider - should use to create VPC. - type: string - netmaskLength: - description: The netmask length of the IPv4 CIDR you want - to allocate to VPC from an Amazon VPC IP Address Manager - (IPAM) pool. Defaults to /16 for IPv4 if not specified. - format: int64 - type: integer - type: object - ipv6: - description: IPv6 contains ipv6 specific settings for the - network. Supported only in managed clusters. This field - cannot be set on AWSCluster object. - properties: - cidrBlock: - description: CidrBlock is the CIDR block provided by Amazon - when VPC has enabled IPv6. Mutually exclusive with IPAMPool. - type: string - egressOnlyInternetGatewayId: - description: EgressOnlyInternetGatewayID is the id of - the egress only internet gateway associated with an - IPv6 enabled VPC. - type: string - ipamPool: - description: IPAMPool defines the IPAMv6 pool to be used - for VPC. Mutually exclusive with CidrBlock. - properties: - id: - description: ID is the ID of the IPAM pool this provider - should use to create VPC. - type: string - name: - description: Name is the name of the IPAM pool this - provider should use to create VPC. - type: string - netmaskLength: - description: The netmask length of the IPv4 CIDR you - want to allocate to VPC from an Amazon VPC IP Address - Manager (IPAM) pool. Defaults to /16 for IPv4 if - not specified. - format: int64 - type: integer - type: object - poolId: - description: PoolID is the IP pool which must be defined - in case of BYO IP is defined. Must be specified if CidrBlock - is set. Mutually exclusive with IPAMPool. - type: string - type: object - tags: - additionalProperties: - type: string - description: Tags is a collection of tags describing the resource. - type: object - type: object - type: object - oidcIdentityProviderConfig: - description: IdentityProviderconfig is used to specify the oidc provider - config to be attached with this eks cluster - properties: - clientId: - description: This is also known as audience. The ID for the client - application that makes authentication requests to the OpenID - identity provider. - type: string - groupsClaim: - description: The JWT claim that the provider uses to return your - groups. - type: string - groupsPrefix: - description: 'The prefix that is prepended to group claims to - prevent clashes with existing names (such as system: groups). - For example, the valueoidc: will create group names like oidc:engineering - and oidc:infra.' - type: string - identityProviderConfigName: - description: "The name of the OIDC provider configuration. \n - IdentityProviderConfigName is a required field" - type: string - issuerUrl: - description: The URL of the OpenID identity provider that allows - the API server to discover public signing keys for verifying - tokens. The URL must begin with https:// and should correspond - to the iss claim in the provider's OIDC ID tokens. Per the OIDC - standard, path components are allowed but query parameters are - not. Typically the URL consists of only a hostname, like https://server.example.org - or https://example.com. This URL should point to the level below - .well-known/openid-configuration and must be publicly accessible - over the internet. - type: string - requiredClaims: - additionalProperties: - type: string - description: The key value pairs that describe required claims - in the identity token. If set, each claim is verified to be - present in the token with a matching value. For the maximum - number of claims that you can require, see Amazon EKS service - quotas (https://docs.aws.amazon.com/eks/latest/userguide/service-quotas.html) - in the Amazon EKS User Guide. - type: object - tags: - additionalProperties: - type: string - description: tags to apply to oidc identity provider association - type: object - usernameClaim: - description: The JSON Web Token (JWT) claim to use as the username. - The default is sub, which is expected to be a unique identifier - of the end user. You can choose other claims, such as email - or name, depending on the OpenID identity provider. Claims other - than email are prefixed with the issuer URL to prevent naming - clashes with other plug-ins. - type: string - usernamePrefix: - description: The prefix that is prepended to username claims to - prevent clashes with existing names. If you do not provide this - field, and username is a value other than email, the prefix - defaults to issuerurl#. You can use the value - to disable all - prefixing. - type: string + required: + - devices type: object - partition: - description: Partition is the AWS security partition being used. Defaults - to "aws" + numCPUs: + description: NumCPUs is the number of virtual processors in a virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to distribute + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + format: int32 + type: integer + os: + description: OS is the Operating System of the virtual machine Defaults + to Linux + type: string + pciDevices: + description: PciDevices is the list of pci devices used by the virtual + machine. + items: + description: PCIDeviceSpec defines virtual machine's PCI configuration + properties: + deviceId: + description: DeviceID is the device ID of a virtual machine's + PCI, in integer. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int32 + type: integer + vendorId: + description: VendorId is the vendor ID of a virtual machine's + PCI, in integer. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int32 + type: integer + type: object + type: array + powerOffMode: + default: hard + description: "PowerOffMode describes the desired behavior when powering + off a VM. \n There are three, supported power off modes: hard, soft, + and trySoft. The first mode, hard, is the equivalent of a physical + system's power cord being ripped from the wall. The soft mode requires + the VM's guest to have VM Tools installed and attempts to gracefully + shut down the VM. Its variant, trySoft, first attempts a graceful + shutdown, and if that fails or the VM is not in a powered off state + after reaching the GuestSoftPowerOffTimeout, the VM is halted. \n + If omitted, the mode defaults to hard." + enum: + - hard + - soft + - trySoft + type: string + providerID: + description: ProviderID is the virtual machine's BIOS UUID formated + as vsphere://12345678-1234-1234-1234-123456789abc + type: string + resourcePool: + description: ResourcePool is the name or inventory path of the resource + pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. type: string - region: - description: The AWS Region the cluster lives in. + snapshot: + description: Snapshot is the name of the snapshot from which to create + a linked clone. This field is ignored if LinkedClone is not enabled. + Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use with this + Virtual Machine type: string - roleAdditionalPolicies: - description: RoleAdditionalPolicies allows you to attach additional - polices to the control plane role. You must enable the EKSAllowAddRoles - feature flag to incorporate these into the created role. + tagIDs: + description: TagIDs is an optional set of tags to add to an instance. + Specified tagIDs must use URN-notation instead of display names. items: type: string type: array - roleName: - description: RoleName specifies the name of IAM role that gives EKS - permission to make API calls. If the role is pre-existing we will - treat it as unmanaged and not delete it on deletion. If the EKSEnableIAM - feature flag is true and no name is supplied then a role is created. - minLength: 2 - type: string - secondaryCidrBlock: - description: SecondaryCidrBlock is the additional CIDR range to use - for pod IPs. Must be within the 100.64.0.0/10 or 198.19.0.0/16 range. - type: string - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to the - bastion host. Valid values are empty string (do not use SSH keys), - a valid SSH key name, or omitted (use the default SSH key name) - type: string - tokenMethod: - default: iam-authenticator - description: TokenMethod is used to specify the method for obtaining - a client token for communicating with EKS iam-authenticator - obtains - a client token using iam-authentictor aws-cli - obtains a client - token using the AWS CLI Defaults to iam-authenticator - enum: - - iam-authenticator - - aws-cli + template: + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 type: string - version: - description: Version defines the desired Kubernetes version. If no - version number is supplied then the latest version of Kubernetes - that EKS supports will be used. - minLength: 2 - pattern: ^v?(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.?(\.0|[1-9][0-9]*)?$ + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When this is set to empty, + this VirtualMachine would be created without TLS certificate validation + of the communication between Cluster API Provider vSphere and the + VMware vCenter server. type: string - vpcCni: - description: VpcCni is used to set configuration options for the VPC - CNI plugin - properties: - disable: - default: false - description: Disable indicates that the Amazon VPC CNI should - be disabled. With EKS clusters the Amazon VPC CNI is automatically - installed into the cluster. For clusters where you want to use - an alternate CNI this option provides a way to specify that - the Amazon VPC CNI should be deleted. You cannot set this to - true if you are using the Amazon VPC CNI addon. - type: boolean - env: - description: Env defines a list of environment variables to apply - to the `aws-node` DaemonSet - items: - description: EnvVar represents an environment variable present - in a Container. - properties: - name: - description: Name of the environment variable. Must be a - C_IDENTIFIER. - type: string - value: - description: 'Variable references $(VAR_NAME) are expanded - using the previously defined environment variables in - the container and any service environment variables. If - a variable cannot be resolved, the reference in the input - string will be unchanged. Double $$ are reduced to a single - $, which allows for escaping the $(VAR_NAME) syntax: i.e. - "$$(VAR_NAME)" will produce the string literal "$(VAR_NAME)". - Escaped references will never be expanded, regardless - of whether the variable exists or not. Defaults to "".' - type: string - valueFrom: - description: Source for the environment variable's value. - Cannot be used if value is not empty. - properties: - configMapKeyRef: - description: Selects a key of a ConfigMap. - properties: - key: - description: The key to select. - type: string - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?' - type: string - optional: - description: Specify whether the ConfigMap or its - key must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - fieldRef: - description: 'Selects a field of the pod: supports metadata.name, - metadata.namespace, `metadata.labels['''']`, - `metadata.annotations['''']`, spec.nodeName, - spec.serviceAccountName, status.hostIP, status.podIP, - status.podIPs.' - properties: - apiVersion: - description: Version of the schema the FieldPath - is written in terms of, defaults to "v1". - type: string - fieldPath: - description: Path of the field to select in the - specified API version. - type: string - required: - - fieldPath - type: object - x-kubernetes-map-type: atomic - resourceFieldRef: - description: 'Selects a resource of the container: only - resources limits and requests (limits.cpu, limits.memory, - limits.ephemeral-storage, requests.cpu, requests.memory - and requests.ephemeral-storage) are currently supported.' - properties: - containerName: - description: 'Container name: required for volumes, - optional for env vars' - type: string - divisor: - anyOf: - - type: integer - - type: string - description: Specifies the output format of the - exposed resources, defaults to "1" - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - resource: - description: 'Required: resource to select' - type: string - required: - - resource - type: object - x-kubernetes-map-type: atomic - secretKeyRef: - description: Selects a key of a secret in the pod's - namespace - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, - uid?' - type: string - optional: - description: Specify whether the Secret or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - required: - - name - type: object - type: array - type: object + required: + - network + - template type: object status: - description: AWSManagedControlPlaneStatus defines the observed state of - an Amazon EKS Cluster. + description: VSphereMachineStatus defines the observed state of VSphereMachine properties: - addons: - description: Addons holds the current status of the EKS addons + addresses: + description: Addresses contains the VSphere instance associated addresses. items: - description: AddonState represents the state of an addon. + description: MachineAddress contains information for the node's + address. properties: - arn: - description: ARN is the AWS ARN of the addon - type: string - createdAt: - description: CreatedAt is the date and time the addon was created - at - format: date-time - type: string - issues: - description: Issues is a list of issue associated with the addon - items: - description: AddonIssue represents an issue with an addon. - properties: - code: - description: Code is the issue code - type: string - message: - description: Message is the textual description of the - issue - type: string - resourceIds: - description: ResourceIDs is a list of resource ids for - the issue - items: - type: string - type: array - type: object - type: array - modifiedAt: - description: ModifiedAt is the date and time the addon was last - modified - format: date-time - type: string - name: - description: Name is the name of the addon - type: string - serviceAccountRoleARN: - description: ServiceAccountRoleArn is the ARN of the IAM role - used for the service account - type: string - status: - description: Status is the status of the addon + address: + description: The machine address. type: string - version: - description: Version is the version of the addon to use + type: + description: Machine address type, one of Hostname, ExternalIP, + InternalIP, ExternalDNS or InternalDNS. type: string required: - - arn - - name - - version + - address + - type type: object type: array - bastion: - description: Bastion holds details of the instance that is used as - a bastion jump box - properties: - addresses: - description: Addresses contains the AWS instance associated addresses. - items: - description: MachineAddress contains information for the node's - address. - properties: - address: - description: The machine address. - type: string - type: - description: Machine address type, one of Hostname, ExternalIP, - InternalIP, ExternalDNS or InternalDNS. - type: string - required: - - address - - type - type: object - type: array - availabilityZone: - description: Availability zone of instance - type: string - 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 - instanceMetadataOptions: - description: InstanceMetadataOptions is the metadata options for - the EC2 instance. - properties: - httpEndpoint: - default: enabled - description: "Enables or disables the HTTP metadata endpoint - on your instances. \n If you specify a value of disabled, - you cannot access your instance metadata. \n Default: enabled" - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: "The desired HTTP PUT response hop limit for - instance metadata requests. The larger the number, the further - instance metadata requests can travel. \n Default: 1" - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: "The state of token usage for your instance metadata - requests. \n If the state is optional, you can choose to - retrieve instance metadata with or without a session token - on your request. If you retrieve the IAM role credentials - without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session - token, the version 2.0 role credentials are returned. \n - If the state is required, you must send a session token - with any instance metadata retrieval requests. In this state, - retrieving the IAM role credentials always returns the version - 2.0 credentials; the version 1.0 credentials are not available. - \n Default: optional" - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: "Set to enabled to allow access to instance tags - from the instance metadata. Set to disabled to turn off - access to instance tags from the instance metadata. For - more information, see Work with instance tags using the - instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - \n Default: disabled" - enum: - - enabled - - disabled - type: string - type: object - instanceState: - description: The current state of the instance. - type: string - networkInterfaces: - description: Specifies ENIs attached to instance - items: - type: string - type: array - nonRootVolumes: - description: Configuration options for the non root storage volumes. - items: - description: Volume encapsulates the configuration options for - the storage device. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by - the controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage - device. Must be greater than the image snapshot size or - 8 (whichever is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported - for the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - type: array - placementGroupName: - description: PlacementGroupName specifies the name of the placement - group in which to launch the instance. - 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 - rootVolume: - description: Configuration options for the root storage volume. - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by the - controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - securityGroupIds: - description: SecurityGroupIDs are one or more security group IDs - this instance belongs to. - items: - type: string - type: array - spotMarketOptions: - description: SpotMarketOptions option for configuring instances - to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: The name of the SSH key pair. - type: string - 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 - tenancy: - description: Tenancy indicates if instance should run on shared - or single-tenant hardware. - type: string - 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 - volumeIDs: - description: IDs of the instance's volumes - items: - type: string - type: array - required: - - id - type: object conditions: - description: Conditions specifies the cpnditions for the managed control - plane + description: Conditions defines current service state of the VSphereMachine. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -10433,433 +3631,782 @@ spec: - type type: object type: array - externalManagedControlPlane: - default: true - description: ExternalManagedControlPlane indicates to cluster-api - that the control plane is managed by an external service such as - AKS, EKS, GKE, etc. - type: boolean - failureDomains: - additionalProperties: - description: FailureDomainSpec is the Schema for Cluster API failure - domains. It allows controllers to understand how many failure - domains a cluster can optionally span across. + failureMessage: + description: "FailureMessage will be set in the event that there is + a terminal problem reconciling the Machine and will contain a more + verbose string suitable for logging and human consumption. \n This + field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over time (like + service outages), but instead indicate that something is fundamentally + wrong with the Machine's spec or the configuration of the controller, + and that manual intervention is required. Examples of terminal errors + would be invalid combinations of settings in the spec, values that + are unsupported by the controller, or the responsible controller + itself being critically misconfigured. \n Any transient errors that + occur during the reconciliation of Machines can be added as events + to the Machine object and/or logged in the controller's output." + type: string + failureReason: + description: "FailureReason will be set in the event that there is + a terminal problem reconciling the Machine and will contain a succinct + value suitable for machine interpretation. \n This field should + not be set for transitive errors that a controller faces that are + expected to be fixed automatically over time (like service outages), + but instead indicate that something is fundamentally wrong with + the Machine's spec or the configuration of the controller, and that + manual intervention is required. Examples of terminal errors would + be invalid combinations of settings in the spec, values that are + unsupported by the controller, or the responsible controller itself + being critically misconfigured. \n Any transient errors that occur + during the reconciliation of Machines can be added as events to + the Machine object and/or logged in the controller's output." + type: string + network: + description: Network returns the network status for each of the machine's + configured network interfaces. + items: + description: NetworkStatus provides information about one of a VM's + networks. properties: - attributes: - additionalProperties: - type: string - description: Attributes is a free form map of attributes an - infrastructure provider might use or require. - type: object - controlPlane: - description: ControlPlane determines if this failure domain - is suitable for use by control plane machines. + connected: + description: Connected is a flag that indicates whether this + network is currently connected to the VM. type: boolean + ipAddrs: + description: IPAddrs is one or more IP addresses reported by + vm-tools. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address of the network device. + type: string + networkName: + description: NetworkName is the name of the network. + type: string + required: + - macAddr type: object - description: FailureDomains specifies a list fo available availability - zones that can be used - type: object - failureMessage: - description: ErrorMessage indicates that there is a terminal problem - reconciling the state, and will be set to a descriptive error message. - type: string - identityProviderStatus: - description: IdentityProviderStatus holds the status for associated - identity provider - properties: - arn: - description: ARN holds the ARN of associated identity provider - type: string - status: - description: Status holds current status of associated identity - provider - type: string - type: object - initialized: - description: Initialized denotes whether or not the control plane - has the uploaded kubernetes config-map. + type: array + ready: + description: Ready is true when the provider resource is ready. type: boolean - networkStatus: - description: Networks holds details about the AWS networking resources - used by the control plane + type: object + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 + name: vspheremachinetemplates.infrastructure.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capv-webhook-service + namespace: capv-system + path: /convert + conversionReviewVersions: + - v1 + - v1beta1 + group: infrastructure.cluster.x-k8s.io + names: + categories: + - cluster-api + kind: VSphereMachineTemplate + listKind: VSphereMachineTemplateList + plural: vspheremachinetemplates + singular: vspheremachinetemplate + scope: Namespaced + versions: + - deprecated: true + name: v1alpha3 + schema: + openAPIV3Schema: + description: "VSphereMachineTemplate is the Schema for the vspheremachinetemplates + API \n Deprecated: This type will be removed in one of the next releases." + 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: VSphereMachineTemplateSpec defines the desired state of VSphereMachineTemplate + properties: + template: + description: VSphereMachineTemplateResource describes the data needed + to create a VSphereMachine from a template properties: - apiServerElb: - description: APIServerELB is the Kubernetes api server load balancer. + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' properties: - arn: - description: ARN of the load balancer. Unlike the ClassicLB, - ARN is used mostly to define and get it. - type: string - attributes: - description: ClassicElbAttributes defines extra attributes - associated with the load balancer. - properties: - crossZoneLoadBalancing: - description: CrossZoneLoadBalancing enables the classic - load balancer load balancing. - type: boolean - 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 - availabilityZones: - description: AvailabilityZones is an array of availability - zones in the VPC attached to the load balancer. - items: + annotations: + additionalProperties: type: string - type: array - dnsName: - description: DNSName is the dns name of the load balancer. + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + generateName: + description: "GenerateName is an optional prefix, used by + the server, to generate a unique name ONLY IF the Name field + has not been provided. If this field is used, the name returned + to the client will be different than the name passed. This + value will also be combined with a unique suffix. The provided + value has the same validation rules as the Name field, and + may be truncated by the length of the suffix required to + make the value unique on the server. \n If this field is + specified and the generated name exists, the server will + NOT return a 409 - instead, it will either return 201 Created + or 500 with Reason ServerTimeout indicating a unique name + could not be found in the time allotted, and the client + should retry (optionally after the time indicated in the + Retry-After header). \n Applied only if Name is not specified. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency + \n Deprecated: This field has no function and is going to + be removed in a next release." type: string - elbAttributes: + labels: additionalProperties: type: string - description: ELBAttributes defines extra attributes associated - with v2 load balancers. + description: 'Map of string keys and values that can be used + to organize and categorize (scope and select) objects. May + match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' type: object - elbListeners: - description: ELBListeners is an array of listeners associated - with the load balancer. There must be at least one. + name: + description: "Name must be unique within a namespace. Is required + when creating resources, although some resources may allow + a client to request the generation of an appropriate name + automatically. Name is primarily intended for creation idempotence + and configuration definition. Cannot be updated. More info: + http://kubernetes.io/docs/user-guide/identifiers#names \n + Deprecated: This field has no function and is going to be + removed in a next release." + type: string + namespace: + description: "Namespace defines the space within each name + must be unique. An empty namespace is equivalent to the + \"default\" namespace, but \"default\" is the canonical + representation. Not all objects are required to be scoped + to a namespace - the value of this field for those objects + will be empty. \n Must be a DNS_LABEL. Cannot be updated. + More info: http://kubernetes.io/docs/user-guide/namespaces + \n Deprecated: This field has no function and is going to + be removed in a next release." + type: string + ownerReferences: + description: "List of objects depended by this object. If + ALL objects in the list have been deleted, this object will + be garbage collected. If this object is managed by a controller, + then an entry in this list will point to this controller, + with the controller field set to true. There cannot be more + than one managing controller. \n Deprecated: This field + has no function and is going to be removed in a next release." items: - description: Listener defines an AWS network load balancer - listener. + description: OwnerReference contains enough information + to let you identify an owning object. An owning object + must be in the same namespace as the dependent, or be + cluster-scoped, so there is no namespace field. properties: - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. + apiVersion: + description: API version of the referent. + type: string + blockOwnerDeletion: + description: If true, AND if the owner has the "foregroundDeletion" + finalizer, then the owner cannot be deleted from the + key-value store until this reference is removed. See + https://kubernetes.io/docs/concepts/architecture/garbage-collection/#foreground-deletion + for how the garbage collector interacts with this + field and enforces the foreground deletion. Defaults + to false. To set this field, a user needs "delete" + permission of the owner, otherwise 422 (Unprocessable + Entity) will be returned. + type: boolean + controller: + description: If true, this reference points to the managing + controller. + type: boolean + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' type: string - targetGroup: - description: TargetGroupSpec specifies target group - settings for a given listener. This is created first, - and the ARN is then passed to the listener. + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#names' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names#uids' + type: string + required: + - apiVersion + - kind + - name + - uid + type: object + x-kubernetes-map-type: atomic + type: array + type: object + spec: + description: Spec is the specification of the desired behavior + of the machine. + properties: + cloneMode: + description: CloneMode specifies the type of clone operation. + The LinkedClone mode is only support for templates that + have at least one snapshot. If the template has no snapshots, + then CloneMode defaults to FullClone. When LinkedClone mode + is enabled the DiskGiB field is ignored as it is not possible + to expand disks of linked clones. Defaults to LinkedClone, + but fails gracefully to FullClone if the source of the clone + operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: + type: string + description: CustomVMXKeys is a dictionary of advanced VMX + options that can be set on VM Defaults to empty map + type: object + datacenter: + description: Datacenter is the name or inventory path of the + datacenter in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the + datastore in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, + in GiB. Defaults to the eponymous property value in the + template from which the virtual machine is cloned. + format: int32 + type: integer + failureDomain: + description: FailureDomain is the failure domain unique identifier + this Machine should be attached to, as defined in Cluster + API. For this infrastructure provider, the name is equivalent + to the name of the VSphereDeploymentZone. + type: string + folder: + description: Folder is the name or inventory path of the folder + in which the virtual machine is created/located. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's + memory, in MiB. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this + machine's VM. + properties: + devices: + description: Devices is the list of network devices used + by the virtual machine. TODO(akutz) Make sure at least + one network matches the ClusterSpec.CloudProviderConfiguration.Network.Name + items: + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. properties: - name: - description: Name of the TargetGroup. Must be unique - over the same group of listeners. + deviceName: + description: DeviceName may be used to explicitly + assign a name to the network device as it exists + in the guest operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether + or not to use DHCP for IPv4 on this device. If + true then IPAddrs should not contain any IPv4 + addresses. + type: boolean + dhcp6: + description: DHCP6 is a flag that indicates whether + or not to use DHCP for IPv6 on this device. If + true then IPAddrs should not contain any IPv6 + addresses. + type: boolean + gateway4: + description: Gateway4 is the IPv4 gateway used by + this device. Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by + this device. Required when DHCP6 is false. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 + and/or IPv6 addresses to assign to this device. + IP addresses must also specify the segment length + in CIDR notation. Required when DHCP4 and DHCP6 + are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by + this device. It is generally a good idea to omit + this field and allow a MAC address to be generated. + Please note that this value must use the VMware + OUI to work with the in-tree vSphere cloud provider. type: string - port: - description: Port is the exposed port + mtu: + description: MTU is the device’s Maximum Transmission + Unit size in bytes. format: int64 type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - enum: - - tcp - - tls - - udp - - TCP - - TLS - - UDP - type: string - targetGroupHealthCheck: - description: HealthCheck is the elb health check - associated with the load balancer. - properties: - intervalSeconds: - format: int64 - type: integer - path: - type: string - port: - type: string - protocol: - type: string - thresholdCount: - format: int64 - type: integer - timeoutSeconds: - format: int64 - type: integer - type: object - vpcId: + nameservers: + description: Nameservers is a list of IPv4 and/or + IPv6 addresses used as DNS nameservers. Please + note that Linux allows only three nameservers + (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere + network to which the device will be connected. type: string + routes: + description: Routes is a list of optional, static + routes applied to the device. + items: + description: NetworkRouteSpec defines a static + network route. + properties: + metric: + description: Metric is the weight/priority + of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains + used when resolving IP addresses with DNS. + items: + type: string + type: array required: - - name - - port - - protocol - - vpcId + - networkName type: object - required: - - port - - protocol - - targetGroup - type: object - type: array - 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: array + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR + for the Kubernetes API server endpoint on this machine 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 + routes: + description: Routes is a list of optional, static routes + applied to the virtual machine. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array required: - - healthyThreshold - - interval - - target - - timeout - - unhealthyThreshold + - devices type: object - listeners: - description: ClassicELBListeners 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: ELBProtocol defines listener protocols - for a load balancer. - type: string - port: - format: int64 - type: integer - protocol: - description: ELBProtocol defines listener protocols - for a load balancer. - type: string - required: - - instancePort - - instanceProtocol - - port - - protocol - type: object - type: array - loadBalancerType: - description: LoadBalancerType sets the type for a load balancer. - The default type is classic. - enum: - - classic - - elb - - alb - - nlb - type: string - 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. + numCPUs: + description: NumCPUs is the number of virtual processors in + a virtual machine. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to + distribute CPUs in this virtual machine. Defaults to the + eponymous property value in the template from which the + virtual machine is cloned. + format: int32 + type: integer + providerID: + description: ProviderID is the virtual machine's BIOS UUID + formated as vsphere://12345678-1234-1234-1234-123456789abc + type: string + resourcePool: + description: ResourcePool is the name or inventory path of + the resource pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere + server on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which + to create a linked clone. This field is ignored if LinkedClone + is not enabled. Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use + with this Virtual Machine + type: string + template: + description: Template is the name or inventory path of the + template used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum + of the given vCenter server's host certificate When this + is set to empty, this VirtualMachine would be created without + TLS certificate validation of the communication between + Cluster API Provider vSphere and the VMware vCenter server. 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: + required: + - network + - template + type: object + required: + - spec + type: object + required: + - template + type: object + type: object + served: true + storage: false + - deprecated: true + name: v1alpha4 + schema: + openAPIV3Schema: + description: "VSphereMachineTemplate is the Schema for the vspheremachinetemplates + API \n Deprecated: This type will be removed in one of the next releases." + 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: VSphereMachineTemplateSpec defines the desired state of VSphereMachineTemplate + properties: + template: + description: VSphereMachineTemplateResource describes the data needed + to create a VSphereMachine from a template + properties: + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' + properties: + annotations: + additionalProperties: type: string - type: array - tags: + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: additionalProperties: type: string - description: Tags is a map of tags associated with the load - balancer. + description: 'Map of string keys and values that can be used + to organize and categorize (scope and select) objects. May + match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' type: object type: object - natGatewaysIPs: - description: NatGatewaysIPs contains the public IPs of the NAT - Gateways - items: - type: string - type: array - securityGroups: - additionalProperties: - description: SecurityGroup defines an AWS security group. - properties: - id: - description: ID is a unique identifier. + spec: + description: Spec is the specification of the desired behavior + of the machine. + properties: + cloneMode: + description: CloneMode specifies the type of clone operation. + The LinkedClone mode is only support for templates that + have at least one snapshot. If the template has no snapshots, + then CloneMode defaults to FullClone. When LinkedClone mode + is enabled the DiskGiB field is ignored as it is not possible + to expand disks of linked clones. Defaults to LinkedClone, + but fails gracefully to FullClone if the source of the clone + operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: 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: + description: CustomVMXKeys is a dictionary of advanced VMX + options that can be set on VM Defaults to empty map + type: object + datacenter: + description: Datacenter is the name or inventory path of the + datacenter in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the + datastore in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, + in GiB. Defaults to the eponymous property value in the + template from which the virtual machine is cloned. + format: int32 + type: integer + failureDomain: + description: FailureDomain is the failure domain unique identifier + this Machine should be attached to, as defined in Cluster + API. For this infrastructure provider, the name is equivalent + to the name of the VSphereDeploymentZone. + type: string + folder: + description: Folder is the name or inventory path of the folder + in which the virtual machine is created/located. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's + memory, in MiB. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this + machine's VM. + properties: + devices: + description: Devices is the list of network devices used + by the virtual machine. TODO(akutz) Make sure at least + one network matches the ClusterSpec.CloudProviderConfiguration.Network.Name + items: + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. + properties: + deviceName: + description: DeviceName may be used to explicitly + assign a name to the network device as it exists + in the guest operating system. type: string - type: array - description: - description: Description provides extended information - about the ingress rule. - type: string - fromPort: - description: FromPort is the start of port range. - format: int64 - type: integer - ipv6CidrBlocks: - description: List of IPv6 CIDR blocks to allow access - from. Cannot be specified with SourceSecurityGroupID. - items: + dhcp4: + description: DHCP4 is a flag that indicates whether + or not to use DHCP for IPv4 on this device. If + true then IPAddrs should not contain any IPv4 + addresses. + type: boolean + dhcp6: + description: DHCP6 is a flag that indicates whether + or not to use DHCP for IPv6 on this device. If + true then IPAddrs should not contain any IPv6 + addresses. + type: boolean + gateway4: + description: Gateway4 is the IPv4 gateway used by + this device. Required when DHCP4 is false. type: string - type: array - protocol: - description: Protocol is the protocol for the ingress - rule. Accepted values are "-1" (all), "4" (IP in - IP),"tcp", "udp", "icmp", and "58" (ICMPv6), "50" - (ESP). - enum: - - "-1" - - "4" - - tcp - - udp - - icmp - - "58" - - "50" - type: string - sourceSecurityGroupIds: - description: The security group id to allow access - from. Cannot be specified with CidrBlocks. - items: + gateway6: + description: Gateway4 is the IPv4 gateway used by + this device. Required when DHCP6 is false. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 + and/or IPv6 addresses to assign to this device. + IP addresses must also specify the segment length + in CIDR notation. Required when DHCP4 and DHCP6 + are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by + this device. It is generally a good idea to omit + this field and allow a MAC address to be generated. + Please note that this value must use the VMware + OUI to work with the in-tree vSphere cloud provider. type: string - type: array - sourceSecurityGroupRoles: - description: The security group role to allow access - from. Cannot be specified with CidrBlocks. The field - will be combined with source security group IDs - if specified. - items: - description: SecurityGroupRole defines the unique - role of a security group. - enum: - - bastion - - node - - controlplane - - apiserver-lb - - lb - - node-eks-additional + mtu: + description: MTU is the device’s Maximum Transmission + Unit size in bytes. + format: int64 + type: integer + nameservers: + description: Nameservers is a list of IPv4 and/or + IPv6 addresses used as DNS nameservers. Please + note that Linux allows only three nameservers + (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere + network to which the device will be connected. type: string - type: array - toPort: - description: ToPort is the end of port range. - format: int64 - type: integer - required: - - description - - fromPort - - protocol - - toPort - type: object - type: array - name: - description: Name is the security group name. - type: string - tags: - additionalProperties: + routes: + description: Routes is a list of optional, static + routes applied to the device. + items: + description: NetworkRouteSpec defines a static + network route. + properties: + metric: + description: Metric is the weight/priority + of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains + used when resolving IP addresses with DNS. + items: + type: string + type: array + required: + - networkName + type: object + type: array + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR + for the Kubernetes API server endpoint on this machine type: string - description: Tags is a map of tags associated with the security - group. - type: object - required: - - id - - 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 - oidcProvider: - description: OIDCProvider holds the status of the identity provider - for this cluster - properties: - arn: - description: ARN holds the ARN of the provider - type: string - trustPolicy: - description: TrustPolicy contains the boilerplate IAM trust policy - to use for IRSA - type: string + routes: + description: Routes is a list of optional, static routes + applied to the virtual machine. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + required: + - devices + type: object + numCPUs: + description: NumCPUs is the number of virtual processors in + a virtual machine. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to + distribute CPUs in this virtual machine. Defaults to the + eponymous property value in the template from which the + virtual machine is cloned. + format: int32 + type: integer + providerID: + description: ProviderID is the virtual machine's BIOS UUID + formated as vsphere://12345678-1234-1234-1234-123456789abc + type: string + resourcePool: + description: ResourcePool is the name or inventory path of + the resource pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere + server on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which + to create a linked clone. This field is ignored if LinkedClone + is not enabled. Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use + with this Virtual Machine + type: string + template: + description: Template is the name or inventory path of the + template used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum + of the given vCenter server's host certificate When this + is set to empty, this VirtualMachine would be created without + TLS certificate validation of the communication between + Cluster API Provider vSphere and the VMware vCenter server. + type: string + required: + - network + - template + type: object + required: + - spec type: object - ready: - default: false - description: Ready denotes that the AWSManagedControlPlane API Server - is ready to receive requests and that the VPC infra is ready. - type: boolean required: - - ready + - template type: object type: object served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: awsmanagedmachinepools.infrastructure.cluster.x-k8s.io -spec: - group: infrastructure.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: AWSManagedMachinePool - listKind: AWSManagedMachinePoolList - plural: awsmanagedmachinepools - shortNames: - - awsmmp - singular: awsmanagedmachinepool - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: MachinePool ready status - jsonPath: .status.ready - name: Ready - type: string - - description: Number of replicas - jsonPath: .status.replicas - name: Replicas - type: integer - name: v1beta1 + storage: false + - name: v1beta1 schema: openAPIV3Schema: - description: AWSManagedMachinePool is the Schema for the awsmanagedmachinepools - API. + description: VSphereMachineTemplate is the Schema for the vspheremachinetemplates + API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -10874,440 +4421,540 @@ spec: metadata: type: object spec: - description: AWSManagedMachinePoolSpec defines the desired state of AWSManagedMachinePool. + description: VSphereMachineTemplateSpec defines the desired state of VSphereMachineTemplate properties: - additionalTags: - additionalProperties: - type: string - description: AdditionalTags is an optional set of tags to add to AWS - resources managed by the AWS provider, in addition to the ones added - by default. - type: object - amiType: - default: AL2_x86_64 - description: AMIType defines the AMI type - enum: - - AL2_x86_64 - - AL2_x86_64_GPU - - AL2_ARM_64 - - CUSTOM - type: string - amiVersion: - description: AMIVersion defines the desired AMI release version. If - no version number is supplied then the latest version for the Kubernetes - version will be used - minLength: 2 - type: string - availabilityZones: - description: AvailabilityZones is an array of availability zones instances - can run in - items: - type: string - type: array - awsLaunchTemplate: - description: AWSLaunchTemplate specifies the launch template to use - to create the managed node group. If AWSLaunchTemplate is specified, - certain node group configuraions outside of launch template are - prohibited (https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html). + template: + description: VSphereMachineTemplateResource describes the data needed + to create a VSphereMachine from a template properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups is an array of references - to security groups that should be applied to the instances. - These security groups would be set in addition to any security - groups defined at the cluster level or in the actuator. - items: - description: AWSResourceReference is a reference to a specific - AWS resource by ID or filters. Only one of ID or Filters may - be specified. Specifying more than one will result in a validation - error. - properties: - filters: - description: 'Filters is a set of key/value pairs used to - identify a resource They are applied according to the - rules defined by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' - items: - description: Filter is a filter used to identify an AWS - resource. - properties: - name: - description: Name of the filter. Filter names are - case-sensitive. - type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array - required: - - name - - values - type: object - type: array - id: - description: ID of resource - type: string - type: object - type: array - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. + metadata: + description: 'Standard object''s metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata' properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look - up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string + annotations: + additionalProperties: + type: string + description: 'Annotations is an unstructured key value map + stored with a resource that may be set by external tools + to store and retrieve arbitrary metadata. They are not queryable + and should be preserved when modifying objects. More info: + http://kubernetes.io/docs/user-guide/annotations' + type: object + labels: + additionalProperties: + type: string + description: 'Map of string keys and values that can be used + to organize and categorize (scope and select) objects. May + match selectors of replication controllers and services. + More info: http://kubernetes.io/docs/user-guide/labels' + type: object type: object - iamInstanceProfile: - description: The name or the Amazon Resource Name (ARN) of the - instance profile associated with the IAM role for the instance. - The instance profile contains the IAM role. - type: string - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating - system to use for image lookup the AMI is not set. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look - up the image for this machine It will be ignored if an explicit - AMI is set. Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} - with the base OS and kubernetes version, respectively. The BaseOS - will be the value in ImageLookupBaseOS or ubuntu (the default), - and the kubernetes version as defined by the packages produced - by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use - for image lookup if AMI is not set. - type: string - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - type: string - name: - description: The name of the launch template. - type: string - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume + spec: + description: Spec is the specification of the desired behavior + of the machine. properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by the - controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 + additionalDisksGiB: + description: AdditionalDisksGiB holds the sizes of additional + disks of the virtual machine, in GiB Defaults to the eponymous + property value in the template from which the virtual machine + is cloned. + items: + format: int32 + type: integer + type: array + cloneMode: + description: CloneMode specifies the type of clone operation. + The LinkedClone mode is only support for templates that + have at least one snapshot. If the template has no snapshots, + then CloneMode defaults to FullClone. When LinkedClone mode + is enabled the DiskGiB field is ignored as it is not possible + to expand disks of linked clones. Defaults to LinkedClone, + but fails gracefully to FullClone if the source of the clone + operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: + type: string + description: CustomVMXKeys is a dictionary of advanced VMX + options that can be set on VM Defaults to empty map + type: object + datacenter: + description: Datacenter is the name or inventory path of the + datacenter in which the virtual machine is created/located. + Defaults to * which selects the default datacenter. + type: string + datastore: + description: Datastore is the name or inventory path of the + datastore in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, + in GiB. Defaults to the eponymous property value in the + template from which the virtual machine is cloned. + format: int32 type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. + failureDomain: + description: FailureDomain is the failure domain unique identifier + this Machine should be attached to, as defined in Cluster + API. For this infrastructure provider, the name is equivalent + to the name of the VSphereDeploymentZone. + type: string + folder: + description: Folder is the name or inventory path of the folder + in which the virtual machine is created/located. + type: string + guestSoftPowerOffTimeout: + description: "GuestSoftPowerOffTimeout sets the wait timeout + for shutdown in the VM guest. The VM will be powered off + forcibly after the timeout if the VM is still up and running + when the PowerOffMode is set to trySoft. \n This parameter + only applies when the PowerOffMode is set to trySoft. \n + If omitted, the timeout defaults to 5 minutes." + type: string + hardwareVersion: + description: HardwareVersion is the hardware version of the + virtual machine. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + Check the compatibility with the ESXi version before setting + the value. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's + memory, in MiB. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. format: int64 type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions are options for configuring AWSMachinePool - instances to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to - the instance. Valid values are empty string (do not use SSH - keys), a valid SSH key name, or omitted (use the default SSH - key name) - type: string - versionNumber: - description: 'VersionNumber is the version of the launch template - that is applied. Typically a new version is created when at - least one of the following happens: 1) A new launch template - spec is applied. 2) One or more parameters in an existing template - is changed. 3) A new AMI is discovered.' - format: int64 - type: integer - type: object - capacityType: - default: onDemand - description: CapacityType specifies the capacity type for the ASG - behind this pool - enum: - - onDemand - - spot - type: string - diskSize: - description: DiskSize specifies the root disk size - format: int32 - type: integer - eksNodegroupName: - description: EKSNodegroupName specifies the name of the nodegroup - in AWS corresponding to this MachinePool. If you don't specify a - name then a default name will be created based on the namespace - and name of the managed machine pool. - type: string - instanceType: - description: InstanceType specifies the AWS instance type - type: string - labels: - additionalProperties: - type: string - description: Labels specifies labels for the Kubernetes node objects - type: object - providerIDList: - description: ProviderIDList are the provider IDs of instances in the - autoscaling group corresponding to the nodegroup represented by - this machine pool - items: - type: string - type: array - remoteAccess: - description: RemoteAccess specifies how machines can be accessed remotely - properties: - public: - description: Public specifies whether to open port 22 to the public - internet - type: boolean - sourceSecurityGroups: - description: SourceSecurityGroups specifies which security groups - are allowed access - items: - type: string - type: array - sshKeyName: - description: SSHKeyName specifies which EC2 SSH key can be used - to access machines. If left empty, the key from the control - plane is used. - type: string - type: object - roleAdditionalPolicies: - description: RoleAdditionalPolicies allows you to attach additional - polices to the node group role. You must enable the EKSAllowAddRoles - feature flag to incorporate these into the created role. - items: - type: string - type: array - roleName: - description: RoleName specifies the name of IAM role for the node - group. If the role is pre-existing we will treat it as unmanaged - and not delete it on deletion. If the EKSEnableIAM feature flag - is true and no name is supplied then a role is created. - type: string - scaling: - description: Scaling specifies scaling for the ASG behind this pool - properties: - maxSize: - format: int32 - type: integer - minSize: - format: int32 - type: integer - type: object - subnetIDs: - description: SubnetIDs specifies which subnets are used for the auto - scaling group of this nodegroup - items: - type: string - type: array - taints: - description: Taints specifies the taints to apply to the nodes of - the machine pool - items: - description: Taint defines the specs for a Kubernetes taint. - properties: - effect: - description: Effect specifies the effect for the taint - enum: - - no-schedule - - no-execute - - prefer-no-schedule - type: string - key: - description: Key is the key of the taint - type: string - value: - description: Value is the value of the taint - type: string - required: - - effect - - key - - value - type: object - type: array - updateConfig: - description: UpdateConfig holds the optional config to control the - behaviour of the update to the nodegroup. - properties: - maxUnavailable: - description: MaxUnavailable is the maximum number of nodes unavailable - at once during a version update. Nodes will be updated in parallel. - The maximum number is 100. - maximum: 100 - minimum: 1 - type: integer - maxUnavailablePrecentage: - description: MaxUnavailablePercentage is the maximum percentage - of nodes unavailable during a version update. This percentage - of nodes will be updated in parallel, up to 100 nodes at once. - maximum: 100 - minimum: 1 - type: integer - type: object - type: object - status: - description: AWSManagedMachinePoolStatus defines the observed state of - AWSManagedMachinePool. - properties: - conditions: - description: Conditions defines current service state of the managed - machine pool - items: - description: Condition defines an observation of a Cluster API resource - operational state. - properties: - lastTransitionTime: - description: Last time the condition transitioned from one status - to another. This should be when the underlying condition changed. - If that is not known, then using the time when the API field - changed is acceptable. - format: date-time - type: string - message: - description: A human readable message indicating details about - the transition. This field may be empty. - type: string - reason: - description: The reason for the condition's last transition - in CamelCase. The specific API may choose whether or not this - field is considered a guaranteed API. This field may not be - empty. - type: string - severity: - description: Severity provides an explicit classification of - Reason code, so the users or machines can immediately understand - the current situation and act accordingly. The Severity field - MUST be set only when Status=False. - type: string - status: - description: Status of the condition, one of True, False, Unknown. - type: string - type: - description: Type of condition in CamelCase or in foo.example.com/CamelCase. - Many .condition.type values are consistent across resources - like Available, but because arbitrary conditions can be useful - (see .node.status.conditions), the ability to deconflict is - important. - type: string - required: - - lastTransitionTime - - status - - type - type: object - type: array - failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the MachinePool and will contain - a more verbose string suitable for logging and human consumption. - \n This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the MachinePool's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of MachinePools can be added as - events to the MachinePool object and/or logged in the controller's - output." - type: string - failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the MachinePool and will contain - a succinct value suitable for machine interpretation. \n This field - should not be set for transitive errors that a controller faces - that are expected to be fixed automatically over time (like service - outages), but instead indicate that something is fundamentally wrong - with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of MachinePools can be added as - events to the MachinePool object and/or logged in the controller's - output." - type: string - launchTemplateID: - description: The ID of the launch template - type: string - launchTemplateVersion: - description: The version of the launch template - type: string - ready: - default: false - description: Ready denotes that the AWSManagedMachinePool nodegroup - has joined the cluster - type: boolean - replicas: - description: Replicas is the most recently observed number of replicas. - format: int32 - type: integer + network: + description: Network is the network configuration for this + machine's VM. + properties: + devices: + description: Devices is the list of network devices used + by the virtual machine. TODO(akutz) Make sure at least + one network matches the ClusterSpec.CloudProviderConfiguration.Network.Name + items: + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. + properties: + addressesFromPools: + description: AddressesFromPools is a list of IPAddressPools + that should be assigned to IPAddressClaims. The + machine's cloud-init metadata will be populated + with IPAddresses fulfilled by an IPAM provider. + items: + description: TypedLocalObjectReference contains + enough information to let you locate the typed + referenced object inside the same namespace. + properties: + apiGroup: + description: APIGroup is the group for the + resource being referenced. If APIGroup is + not specified, the specified Kind must be + in the core API group. For any other third-party + types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource + being referenced + type: string + name: + description: Name is the name of resource + being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + type: array + deviceName: + description: DeviceName may be used to explicitly + assign a name to the network device as it exists + in the guest operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether + or not to use DHCP for IPv4 on this device. If + true then IPAddrs should not contain any IPv4 + addresses. + type: boolean + dhcp4Overrides: + description: DHCP4Overrides allows for the control + over several DHCP behaviors. Overrides will only + be applied when the corresponding DHCP flag is + set. Only configured values will be sent, omitted + values will default to distribution defaults. + Dependent on support in the network stack for + your distribution. For more information see the + netplan reference (https://netplan.io/reference#dhcp-overrides) + properties: + hostname: + description: Hostname is the name which will + be sent to the DHCP server instead of the + machine's hostname. + type: string + routeMetric: + description: RouteMetric is used to prioritize + routes for devices. A lower metric for an + interface will have a higher priority. + type: integer + sendHostname: + description: SendHostname when `true`, the hostname + of the machine will be sent to the DHCP server. + type: boolean + useDNS: + description: UseDNS when `true`, the DNS servers + in the DHCP server will be used and take precedence. + type: boolean + useDomains: + description: UseDomains can take the values + `true`, `false`, or `route`. When `true`, + the domain name from the DHCP server will + be used as the DNS search domain for this + device. When `route`, the domain name from + the DHCP response will be used for routing + DNS only, not for searching. + type: string + useHostname: + description: UseHostname when `true`, the hostname + from the DHCP server will be set as the transient + hostname of the machine. + type: boolean + useMTU: + description: UseMTU when `true`, the MTU from + the DHCP server will be set as the MTU of + the device. + type: boolean + useNTP: + description: UseNTP when `true`, the NTP servers + from the DHCP server will be used by systemd-timesyncd + and take precedence. + type: boolean + useRoutes: + description: UseRoutes when `true`, the routes + from the DHCP server will be installed in + the routing table. + type: string + type: object + dhcp6: + description: DHCP6 is a flag that indicates whether + or not to use DHCP for IPv6 on this device. If + true then IPAddrs should not contain any IPv6 + addresses. + type: boolean + dhcp6Overrides: + description: DHCP6Overrides allows for the control + over several DHCP behaviors. Overrides will only + be applied when the corresponding DHCP flag is + set. Only configured values will be sent, omitted + values will default to distribution defaults. + Dependent on support in the network stack for + your distribution. For more information see the + netplan reference (https://netplan.io/reference#dhcp-overrides) + properties: + hostname: + description: Hostname is the name which will + be sent to the DHCP server instead of the + machine's hostname. + type: string + routeMetric: + description: RouteMetric is used to prioritize + routes for devices. A lower metric for an + interface will have a higher priority. + type: integer + sendHostname: + description: SendHostname when `true`, the hostname + of the machine will be sent to the DHCP server. + type: boolean + useDNS: + description: UseDNS when `true`, the DNS servers + in the DHCP server will be used and take precedence. + type: boolean + useDomains: + description: UseDomains can take the values + `true`, `false`, or `route`. When `true`, + the domain name from the DHCP server will + be used as the DNS search domain for this + device. When `route`, the domain name from + the DHCP response will be used for routing + DNS only, not for searching. + type: string + useHostname: + description: UseHostname when `true`, the hostname + from the DHCP server will be set as the transient + hostname of the machine. + type: boolean + useMTU: + description: UseMTU when `true`, the MTU from + the DHCP server will be set as the MTU of + the device. + type: boolean + useNTP: + description: UseNTP when `true`, the NTP servers + from the DHCP server will be used by systemd-timesyncd + and take precedence. + type: boolean + useRoutes: + description: UseRoutes when `true`, the routes + from the DHCP server will be installed in + the routing table. + type: string + type: object + gateway4: + description: Gateway4 is the IPv4 gateway used by + this device. Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by + this device. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 + and/or IPv6 addresses to assign to this device. IP + addresses must also specify the segment length + in CIDR notation. Required when DHCP4 and DHCP6 + are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by + this device. It is generally a good idea to omit + this field and allow a MAC address to be generated. + Please note that this value must use the VMware + OUI to work with the in-tree vSphere cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission + Unit size in bytes. + format: int64 + type: integer + nameservers: + description: Nameservers is a list of IPv4 and/or + IPv6 addresses used as DNS nameservers. Please + note that Linux allows only three nameservers + (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere + network to which the device will be connected. + type: string + routes: + description: Routes is a list of optional, static + routes applied to the device. + items: + description: NetworkRouteSpec defines a static + network route. + properties: + metric: + description: Metric is the weight/priority + of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains + used when resolving IP addresses with DNS. + items: + type: string + type: array + required: + - networkName + type: object + type: array + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR + for the Kubernetes API server endpoint on this machine + type: string + routes: + description: Routes is a list of optional, static routes + applied to the virtual machine. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + required: + - devices + type: object + numCPUs: + description: NumCPUs is the number of virtual processors in + a virtual machine. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to + distribute CPUs in this virtual machine. Defaults to the + eponymous property value in the template from which the + virtual machine is cloned. + format: int32 + type: integer + os: + description: OS is the Operating System of the virtual machine + Defaults to Linux + type: string + pciDevices: + description: PciDevices is the list of pci devices used by + the virtual machine. + items: + description: PCIDeviceSpec defines virtual machine's PCI + configuration + properties: + deviceId: + description: DeviceID is the device ID of a virtual + machine's PCI, in integer. Defaults to the eponymous + property value in the template from which the virtual + machine is cloned. + format: int32 + type: integer + vendorId: + description: VendorId is the vendor ID of a virtual + machine's PCI, in integer. Defaults to the eponymous + property value in the template from which the virtual + machine is cloned. + format: int32 + type: integer + type: object + type: array + powerOffMode: + default: hard + description: "PowerOffMode describes the desired behavior + when powering off a VM. \n There are three, supported power + off modes: hard, soft, and trySoft. The first mode, hard, + is the equivalent of a physical system's power cord being + ripped from the wall. The soft mode requires the VM's guest + to have VM Tools installed and attempts to gracefully shut + down the VM. Its variant, trySoft, first attempts a graceful + shutdown, and if that fails or the VM is not in a powered + off state after reaching the GuestSoftPowerOffTimeout, the + VM is halted. \n If omitted, the mode defaults to hard." + enum: + - hard + - soft + - trySoft + type: string + providerID: + description: ProviderID is the virtual machine's BIOS UUID + formated as vsphere://12345678-1234-1234-1234-123456789abc + type: string + resourcePool: + description: ResourcePool is the name or inventory path of + the resource pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere + server on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which + to create a linked clone. This field is ignored if LinkedClone + is not enabled. Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use + with this Virtual Machine + type: string + tagIDs: + description: TagIDs is an optional set of tags to add to an + instance. Specified tagIDs must use URN-notation instead + of display names. + items: + type: string + type: array + template: + description: Template is the name or inventory path of the + template used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum + of the given vCenter server's host certificate When this + is set to empty, this VirtualMachine would be created without + TLS certificate validation of the communication between + Cluster API Provider vSphere and the VMware vCenter server. + type: string + required: + - network + - template + type: object + required: + - spec + type: object required: - - ready + - template type: object type: object served: true - storage: false - subresources: - status: {} - - additionalPrinterColumns: - - description: MachinePool ready status - jsonPath: .status.ready - name: Ready - type: string - - description: Number of replicas - jsonPath: .status.replicas - name: Replicas - type: integer - name: v1beta2 + storage: true +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert + controller-gen.kubebuilder.io/version: v0.12.1 + labels: + cluster.x-k8s.io/provider: infrastructure-vsphere + cluster.x-k8s.io/v1beta1: v1beta1 + name: vspherevms.infrastructure.cluster.x-k8s.io +spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + caBundle: Cg== + service: + name: capv-webhook-service + namespace: capv-system + path: /convert + conversionReviewVersions: + - v1 + - v1beta1 + group: infrastructure.cluster.x-k8s.io + names: + categories: + - cluster-api + kind: VSphereVM + listKind: VSphereVMList + plural: vspherevms + singular: vspherevm + scope: Namespaced + versions: + - deprecated: true + name: v1alpha3 schema: openAPIV3Schema: - description: AWSManagedMachinePool is the Schema for the awsmanagedmachinepools - API. + description: "VSphereVM is the Schema for the vspherevms API \n Deprecated: + This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -11322,389 +4969,285 @@ spec: metadata: type: object spec: - description: AWSManagedMachinePoolSpec defines the desired state of AWSManagedMachinePool. + description: VSphereVMSpec defines the desired state of VSphereVM. properties: - additionalTags: + biosUUID: + description: BiosUUID is the the VM's BIOS UUID that is assigned at + runtime after the VM has been created. This field is required at + runtime for other controllers that read this CRD as unstructured + data. + type: string + bootstrapRef: + description: BootstrapRef is a reference to a bootstrap provider-specific + resource that holds configuration details. This field is optional + in case no bootstrap data is required to create a VM. + properties: + 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/sig-architecture/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/sig-architecture/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 + x-kubernetes-map-type: atomic + cloneMode: + description: CloneMode specifies the type of clone operation. The + LinkedClone mode is only support for templates that have at least + one snapshot. If the template has no snapshots, then CloneMode defaults + to FullClone. When LinkedClone mode is enabled the DiskGiB field + is ignored as it is not possible to expand disks of linked clones. + Defaults to LinkedClone, but fails gracefully to FullClone if the + source of the clone operation has no snapshots. + type: string + customVMXKeys: additionalProperties: type: string - description: AdditionalTags is an optional set of tags to add to AWS - resources managed by the AWS provider, in addition to the ones added - by default. + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map type: object - amiType: - default: AL2_x86_64 - description: AMIType defines the AMI type - enum: - - AL2_x86_64 - - AL2_x86_64_GPU - - AL2_ARM_64 - - CUSTOM - type: string - amiVersion: - description: AMIVersion defines the desired AMI release version. If - no version number is supplied then the latest version for the Kubernetes - version will be used - minLength: 2 - type: string - availabilityZoneSubnetType: - description: AvailabilityZoneSubnetType specifies which type of subnets - to use when an availability zone is specified. - enum: - - public - - private - - all - type: string - availabilityZones: - description: AvailabilityZones is an array of availability zones instances - can run in - items: - type: string - type: array - awsLaunchTemplate: - description: AWSLaunchTemplate specifies the launch template to use - to create the managed node group. If AWSLaunchTemplate is specified, - certain node group configuraions outside of launch template are - prohibited (https://docs.aws.amazon.com/eks/latest/userguide/launch-templates.html). + datacenter: + description: Datacenter is the name or inventory path of the datacenter + in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, in GiB. + Defaults to the eponymous property value in the template from which + the virtual machine is cloned. + format: int32 + type: integer + folder: + description: Folder is the name or inventory path of the folder in + which the virtual machine is created/located. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's memory, + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this machine's + VM. properties: - additionalSecurityGroups: - description: AdditionalSecurityGroups is an array of references - to security groups that should be applied to the instances. - These security groups would be set in addition to any security - groups defined at the cluster level or in the actuator. + devices: + description: Devices is the list of network devices used by the + virtual machine. TODO(akutz) Make sure at least one network + matches the ClusterSpec.CloudProviderConfiguration.Network.Name items: - description: AWSResourceReference is a reference to a specific - AWS resource by ID or filters. Only one of ID or Filters may - be specified. Specifying more than one will result in a validation - error. + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. properties: - filters: - description: 'Filters is a set of key/value pairs used to - identify a resource They are applied according to the - rules defined by the AWS API: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Filtering.html' + deviceName: + description: DeviceName may be used to explicitly assign + a name to the network device as it exists in the guest + operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether or not + to use DHCP for IPv4 on this device. If true then IPAddrs + should not contain any IPv4 addresses. + type: boolean + dhcp6: + description: DHCP6 is a flag that indicates whether or not + to use DHCP for IPv6 on this device. If true then IPAddrs + should not contain any IPv6 addresses. + type: boolean + gateway4: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP6 is false. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 and/or + IPv6 addresses to assign to this device. IP addresses + must also specify the segment length in CIDR notation. + Required when DHCP4 and DHCP6 are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by this device. + It is generally a good idea to omit this field and allow + a MAC address to be generated. Please note that this value + must use the VMware OUI to work with the in-tree vSphere + cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission Unit + size in bytes. + format: int64 + type: integer + nameservers: + description: Nameservers is a list of IPv4 and/or IPv6 addresses + used as DNS nameservers. Please note that Linux allows + only three nameservers (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere network + to which the device will be connected. + type: string + routes: + description: Routes is a list of optional, static routes + applied to the device. items: - description: Filter is a filter used to identify an AWS - resource. + description: NetworkRouteSpec defines a static network + route. properties: - name: - description: Name of the filter. Filter names are - case-sensitive. + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. type: string - values: - description: Values includes one or more filter values. - Filter values are case-sensitive. - items: - type: string - type: array required: - - name - - values + - metric + - to + - via type: object type: array - id: - description: ID of resource - type: string + searchDomains: + description: SearchDomains is a list of search domains used + when resolving IP addresses with DNS. + items: + type: string + type: array + required: + - networkName type: object type: array - ami: - description: AMI is the reference to the AMI from which to create - the machine instance. - properties: - eksLookupType: - description: EKSOptimizedLookupType If specified, will look - up an EKS Optimized image in SSM Parameter store - enum: - - AmazonLinux - - AmazonLinuxGPU - type: string - id: - description: ID of resource - type: string - type: object - iamInstanceProfile: - description: The name or the Amazon Resource Name (ARN) of the - instance profile associated with the IAM role for the instance. - The instance profile contains the IAM role. - type: string - imageLookupBaseOS: - description: ImageLookupBaseOS is the name of the base operating - system to use for image lookup the AMI is not set. - type: string - imageLookupFormat: - description: 'ImageLookupFormat is the AMI naming format to look - up the image for this machine It will be ignored if an explicit - AMI is set. Supports substitutions for {{.BaseOS}} and {{.K8sVersion}} - with the base OS and kubernetes version, respectively. The BaseOS - will be the value in ImageLookupBaseOS or ubuntu (the default), - and the kubernetes version as defined by the packages produced - by kubernetes/release without v as a prefix: 1.13.0, 1.12.5-mybuild.1, - or 1.17.3. For example, the default image format of capa-ami-{{.BaseOS}}-?{{.K8sVersion}}-* - will end up searching for AMIs that match the pattern capa-ami-ubuntu-?1.18.0-* - for a Machine that is targeting kubernetes v1.18.0 and the ubuntu - base OS. See also: https://golang.org/pkg/text/template/' - type: string - imageLookupOrg: - description: ImageLookupOrg is the AWS Organization ID to use - for image lookup if AMI is not set. - type: string - instanceMetadataOptions: - description: InstanceMetadataOptions defines the behavior for - applying metadata to instances. - properties: - httpEndpoint: - default: enabled - description: "Enables or disables the HTTP metadata endpoint - on your instances. \n If you specify a value of disabled, - you cannot access your instance metadata. \n Default: enabled" - enum: - - enabled - - disabled - type: string - httpPutResponseHopLimit: - default: 1 - description: "The desired HTTP PUT response hop limit for - instance metadata requests. The larger the number, the further - instance metadata requests can travel. \n Default: 1" - format: int64 - maximum: 64 - minimum: 1 - type: integer - httpTokens: - default: optional - description: "The state of token usage for your instance metadata - requests. \n If the state is optional, you can choose to - retrieve instance metadata with or without a session token - on your request. If you retrieve the IAM role credentials - without a token, the version 1.0 role credentials are returned. - If you retrieve the IAM role credentials using a valid session - token, the version 2.0 role credentials are returned. \n - If the state is required, you must send a session token - with any instance metadata retrieval requests. In this state, - retrieving the IAM role credentials always returns the version - 2.0 credentials; the version 1.0 credentials are not available. - \n Default: optional" - enum: - - optional - - required - type: string - instanceMetadataTags: - default: disabled - description: "Set to enabled to allow access to instance tags - from the instance metadata. Set to disabled to turn off - access to instance tags from the instance metadata. For - more information, see Work with instance tags using the - instance metadata (https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Using_Tags.html#work-with-tags-in-IMDS). - \n Default: disabled" - enum: - - enabled - - disabled - type: string - type: object - instanceType: - description: 'InstanceType is the type of instance to create. - Example: m4.xlarge' - type: string - name: - description: The name of the launch template. - type: string - rootVolume: - description: RootVolume encapsulates the configuration options - for the root volume - properties: - deviceName: - description: Device name - type: string - encrypted: - description: Encrypted is whether the volume should be encrypted - or not. - type: boolean - encryptionKey: - description: EncryptionKey is the KMS key to use to encrypt - the volume. Can be either a KMS key ID or ARN. If Encrypted - is set and this is omitted, the default AWS key will be - used. The key must already exist and be accessible by the - controller. - type: string - iops: - description: IOPS is the number of IOPS requested for the - disk. Not applicable to all types. - format: int64 - type: integer - size: - description: Size specifies size (in Gi) of the storage device. - Must be greater than the image snapshot size or 8 (whichever - is greater). - format: int64 - minimum: 8 - type: integer - throughput: - description: Throughput to provision in MiB/s supported for - the volume type. Not applicable to all types. - format: int64 - type: integer - type: - description: Type is the type of the volume (e.g. gp2, io1, - etc...). - type: string - required: - - size - type: object - spotMarketOptions: - description: SpotMarketOptions are options for configuring AWSMachinePool - instances to be run using AWS Spot instances. - properties: - maxPrice: - description: MaxPrice defines the maximum price the user is - willing to pay for Spot VM instances - type: string - type: object - sshKeyName: - description: SSHKeyName is the name of the ssh key to attach to - the instance. Valid values are empty string (do not use SSH - keys), a valid SSH key name, or omitted (use the default SSH - key name) + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR for the + Kubernetes API server endpoint on this machine type: string - versionNumber: - description: 'VersionNumber is the version of the launch template - that is applied. Typically a new version is created when at - least one of the following happens: 1) A new launch template - spec is applied. 2) One or more parameters in an existing template - is changed. 3) A new AMI is discovered.' - format: int64 - type: integer + routes: + description: Routes is a list of optional, static routes applied + to the virtual machine. + items: + description: NetworkRouteSpec defines a static network route. + properties: + metric: + description: Metric is the weight/priority of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + required: + - devices type: object - capacityType: - default: onDemand - description: CapacityType specifies the capacity type for the ASG - behind this pool - enum: - - onDemand - - spot - type: string - diskSize: - description: DiskSize specifies the root disk size + numCPUs: + description: NumCPUs is the number of virtual processors in a virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. format: int32 type: integer - eksNodegroupName: - description: EKSNodegroupName specifies the name of the nodegroup - in AWS corresponding to this MachinePool. If you don't specify a - name then a default name will be created based on the namespace - and name of the managed machine pool. + numCoresPerSocket: + description: NumCPUs is the number of cores among which to distribute + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + format: int32 + type: integer + resourcePool: + description: ResourcePool is the name or inventory path of the resource + pool in which the virtual machine is created/located. type: string - instanceType: - description: InstanceType specifies the AWS instance type + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. type: string - labels: - additionalProperties: - type: string - description: Labels specifies labels for the Kubernetes node objects - type: object - providerIDList: - description: ProviderIDList are the provider IDs of instances in the - autoscaling group corresponding to the nodegroup represented by - this machine pool - items: - type: string - type: array - remoteAccess: - description: RemoteAccess specifies how machines can be accessed remotely - properties: - public: - description: Public specifies whether to open port 22 to the public - internet - type: boolean - sourceSecurityGroups: - description: SourceSecurityGroups specifies which security groups - are allowed access - items: - type: string - type: array - sshKeyName: - description: SSHKeyName specifies which EC2 SSH key can be used - to access machines. If left empty, the key from the control - plane is used. - type: string - type: object - roleAdditionalPolicies: - description: RoleAdditionalPolicies allows you to attach additional - polices to the node group role. You must enable the EKSAllowAddRoles - feature flag to incorporate these into the created role. - items: - type: string - type: array - roleName: - description: RoleName specifies the name of IAM role for the node - group. If the role is pre-existing we will treat it as unmanaged - and not delete it on deletion. If the EKSEnableIAM feature flag - is true and no name is supplied then a role is created. + snapshot: + description: Snapshot is the name of the snapshot from which to create + a linked clone. This field is ignored if LinkedClone is not enabled. + Defaults to the source's current snapshot. type: string - scaling: - description: Scaling specifies scaling for the ASG behind this pool - properties: - maxSize: - format: int32 - type: integer - minSize: - format: int32 - type: integer - type: object - subnetIDs: - description: SubnetIDs specifies which subnets are used for the auto - scaling group of this nodegroup - items: - type: string - type: array - taints: - description: Taints specifies the taints to apply to the nodes of - the machine pool - items: - description: Taint defines the specs for a Kubernetes taint. - properties: - effect: - description: Effect specifies the effect for the taint - enum: - - no-schedule - - no-execute - - prefer-no-schedule - type: string - key: - description: Key is the key of the taint - type: string - value: - description: Value is the value of the taint - type: string - required: - - effect - - key - - value - type: object - type: array - updateConfig: - description: UpdateConfig holds the optional config to control the - behaviour of the update to the nodegroup. - properties: - maxUnavailable: - description: MaxUnavailable is the maximum number of nodes unavailable - at once during a version update. Nodes will be updated in parallel. - The maximum number is 100. - maximum: 100 - minimum: 1 - type: integer - maxUnavailablePercentage: - description: MaxUnavailablePercentage is the maximum percentage - of nodes unavailable during a version update. This percentage - of nodes will be updated in parallel, up to 100 nodes at once. - maximum: 100 - minimum: 1 - type: integer - type: object + storagePolicyName: + description: StoragePolicyName of the storage policy to use with this + Virtual Machine + type: string + template: + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When this is set to empty, + this VirtualMachine would be created without TLS certificate validation + of the communication between Cluster API Provider vSphere and the + VMware vCenter server. + type: string + required: + - network + - template type: object status: - description: AWSManagedMachinePoolStatus defines the observed state of - AWSManagedMachinePool. + description: VSphereVMStatus defines the observed state of VSphereVM properties: + addresses: + description: Addresses is a list of the VM's IP addresses. This field + is required at runtime for other controllers that read this CRD + as unstructured data. + items: + type: string + type: array + cloneMode: + description: CloneMode is the type of clone operation used to clone + this VM. Since LinkedMode is the default but fails gracefully if + the source of the clone has no snapshots, this field may be used + to determine the actual type of clone operation used to create this + VM. + type: string conditions: - description: Conditions defines current service state of the managed - machine pool + description: Conditions defines current service state of the VSphereVM. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -11743,118 +5286,89 @@ spec: important. type: string required: - - lastTransitionTime - status - type type: object type: array - failureMessage: - description: "FailureMessage will be set in the event that there is - a terminal problem reconciling the MachinePool and will contain - a more verbose string suitable for logging and human consumption. - \n This field should not be set for transitive errors that a controller - faces that are expected to be fixed automatically over time (like - service outages), but instead indicate that something is fundamentally - wrong with the MachinePool's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of MachinePools can be added as - events to the MachinePool object and/or logged in the controller's - output." - type: string - failureReason: - description: "FailureReason will be set in the event that there is - a terminal problem reconciling the MachinePool and will contain - a succinct value suitable for machine interpretation. \n This field - should not be set for transitive errors that a controller faces - that are expected to be fixed automatically over time (like service - outages), but instead indicate that something is fundamentally wrong - with the Machine's spec or the configuration of the controller, - and that manual intervention is required. Examples of terminal errors - would be invalid combinations of settings in the spec, values that - are unsupported by the controller, or the responsible controller - itself being critically misconfigured. \n Any transient errors that - occur during the reconciliation of MachinePools can be added as - events to the MachinePool object and/or logged in the controller's - output." + failureMessage: + description: "FailureMessage will be set in the event that there is + a terminal problem reconciling the vspherevm and will contain a + more verbose string suitable for logging and human consumption. + \n This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over time (like + service outages), but instead indicate that something is fundamentally + wrong with the vm. \n Any transient errors that occur during the + reconciliation of vspherevms can be added as events to the vspherevm + object and/or logged in the controller's output." + type: string + failureReason: + description: "FailureReason will be set in the event that there is + a terminal problem reconciling the vspherevm and will contain a + succinct value suitable for vm interpretation. \n This field should + not be set for transitive errors that a controller faces that are + expected to be fixed automatically over time (like service outages), + but instead indicate that something is fundamentally wrong with + the vm. \n Any transient errors that occur during the reconciliation + of vspherevms can be added as events to the vspherevm object and/or + logged in the controller's output." + type: string + network: + description: Network returns the network status for each of the machine's + configured network interfaces. + items: + description: NetworkStatus provides information about one of a VM's + networks. + properties: + connected: + description: Connected is a flag that indicates whether this + network is currently connected to the VM. + type: boolean + ipAddrs: + description: IPAddrs is one or more IP addresses reported by + vm-tools. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address of the network device. + type: string + networkName: + description: NetworkName is the name of the network. + type: string + required: + - macAddr + type: object + type: array + ready: + description: Ready is true when the provider resource is ready. This + field is required at runtime for other controllers that read this + CRD as unstructured data. + type: boolean + retryAfter: + description: RetryAfter tracks the time we can retry queueing a task + format: date-time type: string - launchTemplateID: - description: The ID of the launch template + snapshot: + description: Snapshot is the name of the snapshot from which the VM + was cloned if LinkedMode is enabled. type: string - launchTemplateVersion: - description: The version of the launch template + taskRef: + description: TaskRef is a managed object reference to a Task related + to the machine. This value is set automatically at runtime and should + not be set or modified by users. type: string - ready: - default: false - description: Ready denotes that the AWSManagedMachinePool nodegroup - has joined the cluster - type: boolean - replicas: - description: Replicas is the most recently observed number of replicas. - format: int32 - type: integer - required: - - ready type: object type: object served: true - storage: true + storage: false subresources: status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: eksconfigs.bootstrap.cluster.x-k8s.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - caBundle: Cg== - service: - name: capa-webhook-service - namespace: capa-system - path: /convert - conversionReviewVersions: - - v1 - - v1beta1 - group: bootstrap.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: EKSConfig - listKind: EKSConfigList - plural: eksconfigs - shortNames: - - eksc - singular: eksconfig - scope: Namespaced - versions: - - additionalPrinterColumns: - - description: Bootstrap configuration is ready - jsonPath: .status.ready - name: Ready - type: string - - description: Name of Secret containing bootstrap data - jsonPath: .status.dataSecretName - name: DataSecretName - type: string - name: v1beta1 + - deprecated: true + name: v1alpha4 schema: openAPIV3Schema: - description: EKSConfig is the schema for the Amazon EKS Machine Bootstrap - Configuration API. + description: "VSphereVM is the Schema for the vspherevms API \n Deprecated: + This type will be removed in one of the next releases." properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -11869,61 +5383,285 @@ spec: metadata: type: object spec: - description: EKSConfigSpec defines the desired state of Amazon EKS Bootstrap - Configuration. + description: VSphereVMSpec defines the desired state of VSphereVM. properties: - apiRetryAttempts: - description: APIRetryAttempts is the number of retry attempts for - AWS API call. - type: integer - containerRuntime: - description: ContainerRuntime specify the container runtime to use - when bootstrapping EKS. - type: string - dnsClusterIP: - description: DNSClusterIP overrides the IP address to use for DNS - queries within the cluster. - type: string - dockerConfigJson: - description: DockerConfigJson is used for the contents of the /etc/docker/daemon.json - file. Useful if you want a custom config differing from the default - one in the AMI. This is expected to be a json string. - type: string - kubeletExtraArgs: + biosUUID: + description: BiosUUID is the the VM's BIOS UUID that is assigned at + runtime after the VM has been created. This field is required at + runtime for other controllers that read this CRD as unstructured + data. + type: string + bootstrapRef: + description: BootstrapRef is a reference to a bootstrap provider-specific + resource that holds configuration details. This field is optional + in case no bootstrap data is required to create a VM. + properties: + 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/sig-architecture/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/sig-architecture/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 + x-kubernetes-map-type: atomic + cloneMode: + description: CloneMode specifies the type of clone operation. The + LinkedClone mode is only support for templates that have at least + one snapshot. If the template has no snapshots, then CloneMode defaults + to FullClone. When LinkedClone mode is enabled the DiskGiB field + is ignored as it is not possible to expand disks of linked clones. + Defaults to LinkedClone, but fails gracefully to FullClone if the + source of the clone operation has no snapshots. + type: string + customVMXKeys: additionalProperties: type: string - description: KubeletExtraArgs passes the specified kubelet args into - the Amazon EKS machine bootstrap script + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map type: object - pauseContainer: - description: PauseContainer allows customization of the pause container - to use. + datacenter: + description: Datacenter is the name or inventory path of the datacenter + in which the virtual machine is created/located. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, in GiB. + Defaults to the eponymous property value in the template from which + the virtual machine is cloned. + format: int32 + type: integer + folder: + description: Folder is the name or inventory path of the folder in + which the virtual machine is created/located. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's memory, + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this machine's + VM. properties: - accountNumber: - description: AccountNumber is the AWS account number to pull the - pause container from. - type: string - version: - description: Version is the tag of the pause container to use. + devices: + description: Devices is the list of network devices used by the + virtual machine. TODO(akutz) Make sure at least one network + matches the ClusterSpec.CloudProviderConfiguration.Network.Name + items: + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. + properties: + deviceName: + description: DeviceName may be used to explicitly assign + a name to the network device as it exists in the guest + operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether or not + to use DHCP for IPv4 on this device. If true then IPAddrs + should not contain any IPv4 addresses. + type: boolean + dhcp6: + description: DHCP6 is a flag that indicates whether or not + to use DHCP for IPv6 on this device. If true then IPAddrs + should not contain any IPv6 addresses. + type: boolean + gateway4: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP6 is false. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 and/or + IPv6 addresses to assign to this device. IP addresses + must also specify the segment length in CIDR notation. + Required when DHCP4 and DHCP6 are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by this device. + It is generally a good idea to omit this field and allow + a MAC address to be generated. Please note that this value + must use the VMware OUI to work with the in-tree vSphere + cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission Unit + size in bytes. + format: int64 + type: integer + nameservers: + description: Nameservers is a list of IPv4 and/or IPv6 addresses + used as DNS nameservers. Please note that Linux allows + only three nameservers (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere network + to which the device will be connected. + type: string + routes: + description: Routes is a list of optional, static routes + applied to the device. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains used + when resolving IP addresses with DNS. + items: + type: string + type: array + required: + - networkName + type: object + type: array + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR for the + Kubernetes API server endpoint on this machine type: string + routes: + description: Routes is a list of optional, static routes applied + to the virtual machine. + items: + description: NetworkRouteSpec defines a static network route. + properties: + metric: + description: Metric is the weight/priority of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array required: - - accountNumber - - version + - devices type: object - serviceIPV6Cidr: - description: ServiceIPV6Cidr is the ipv6 cidr range of the cluster. - If this is specified then the ip family will be set to ipv6. + numCPUs: + description: NumCPUs is the number of virtual processors in a virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to distribute + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + format: int32 + type: integer + resourcePool: + description: ResourcePool is the name or inventory path of the resource + pool in which the virtual machine is created/located. type: string - useMaxPods: - description: UseMaxPods sets --max-pods for the kubelet when true. - type: boolean + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which to create + a linked clone. This field is ignored if LinkedClone is not enabled. + Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use with this + Virtual Machine + type: string + template: + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 + type: string + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When this is set to empty, + this VirtualMachine would be created without TLS certificate validation + of the communication between Cluster API Provider vSphere and the + VMware vCenter server. + type: string + required: + - network + - template type: object status: - description: EKSConfigStatus defines the observed state of the Amazon - EKS Bootstrap Configuration. + description: VSphereVMStatus defines the observed state of VSphereVM properties: + addresses: + description: Addresses is a list of the VM's IP addresses. This field + is required at runtime for other controllers that read this CRD + as unstructured data. + items: + type: string + type: array + cloneMode: + description: CloneMode is the type of clone operation used to clone + this VM. Since LinkedMode is the default but fails gracefully if + the source of the clone has no snapshots, this field may be used + to determine the actual type of clone operation used to create this + VM. + type: string conditions: - description: Conditions defines current service state of the EKSConfig. + description: Conditions defines current service state of the VSphereVM. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -11962,50 +5700,87 @@ spec: important. type: string required: - - lastTransitionTime - status - type type: object type: array - dataSecretName: - description: DataSecretName is the name of the secret that stores - the bootstrap data script. - type: string failureMessage: - description: FailureMessage will be set on non-retryable errors + description: "FailureMessage will be set in the event that there is + a terminal problem reconciling the vspherevm and will contain a + more verbose string suitable for logging and human consumption. + \n This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over time (like + service outages), but instead indicate that something is fundamentally + wrong with the vm. \n Any transient errors that occur during the + reconciliation of vspherevms can be added as events to the vspherevm + object and/or logged in the controller's output." type: string failureReason: - description: FailureReason will be set on non-retryable errors + description: "FailureReason will be set in the event that there is + a terminal problem reconciling the vspherevm and will contain a + succinct value suitable for vm interpretation. \n This field should + not be set for transitive errors that a controller faces that are + expected to be fixed automatically over time (like service outages), + but instead indicate that something is fundamentally wrong with + the vm. \n Any transient errors that occur during the reconciliation + of vspherevms can be added as events to the vspherevm object and/or + logged in the controller's output." type: string - observedGeneration: - description: ObservedGeneration is the latest generation observed - by the controller. - format: int64 - type: integer + network: + description: Network returns the network status for each of the machine's + configured network interfaces. + items: + description: NetworkStatus provides information about one of a VM's + networks. + properties: + connected: + description: Connected is a flag that indicates whether this + network is currently connected to the VM. + type: boolean + ipAddrs: + description: IPAddrs is one or more IP addresses reported by + vm-tools. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address of the network device. + type: string + networkName: + description: NetworkName is the name of the network. + type: string + required: + - macAddr + type: object + type: array ready: - description: Ready indicates the BootstrapData secret is ready to - be consumed + description: Ready is true when the provider resource is ready. This + field is required at runtime for other controllers that read this + CRD as unstructured data. type: boolean + retryAfter: + description: RetryAfter tracks the time we can retry queueing a task + format: date-time + type: string + snapshot: + description: Snapshot is the name of the snapshot from which the VM + was cloned if LinkedMode is enabled. + type: string + taskRef: + description: TaskRef is a managed object reference to a Task related + to the machine. This value is set automatically at runtime and should + not be set or modified by users. + type: string type: object type: object served: true storage: false subresources: status: {} - - additionalPrinterColumns: - - description: Bootstrap configuration is ready - jsonPath: .status.ready - name: Ready - type: string - - description: Name of Secret containing bootstrap data - jsonPath: .status.dataSecretName - name: DataSecretName - type: string - name: v1beta2 + - name: v1beta1 schema: openAPIV3Schema: - description: EKSConfig is the schema for the Amazon EKS Machine Bootstrap - Configuration API. + description: VSphereVM is the Schema for the vspherevms API properties: apiVersion: description: 'APIVersion defines the versioned schema of this representation @@ -12020,304 +5795,486 @@ spec: metadata: type: object spec: - description: EKSConfigSpec defines the desired state of Amazon EKS Bootstrap - Configuration. + description: VSphereVMSpec defines the desired state of VSphereVM. properties: - apiRetryAttempts: - description: APIRetryAttempts is the number of retry attempts for - AWS API call. + additionalDisksGiB: + description: AdditionalDisksGiB holds the sizes of additional disks + of the virtual machine, in GiB Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + items: + format: int32 + type: integer + type: array + biosUUID: + description: BiosUUID is the the VM's BIOS UUID that is assigned at + runtime after the VM has been created. This field is required at + runtime for other controllers that read this CRD as unstructured + data. + type: string + bootstrapRef: + description: BootstrapRef is a reference to a bootstrap provider-specific + resource that holds configuration details. This field is optional + in case no bootstrap data is required to create a VM. + properties: + 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/sig-architecture/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/sig-architecture/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 + x-kubernetes-map-type: atomic + cloneMode: + description: CloneMode specifies the type of clone operation. The + LinkedClone mode is only support for templates that have at least + one snapshot. If the template has no snapshots, then CloneMode defaults + to FullClone. When LinkedClone mode is enabled the DiskGiB field + is ignored as it is not possible to expand disks of linked clones. + Defaults to LinkedClone, but fails gracefully to FullClone if the + source of the clone operation has no snapshots. + type: string + customVMXKeys: + additionalProperties: + type: string + description: CustomVMXKeys is a dictionary of advanced VMX options + that can be set on VM Defaults to empty map + type: object + datacenter: + description: Datacenter is the name or inventory path of the datacenter + in which the virtual machine is created/located. Defaults to * which + selects the default datacenter. + type: string + datastore: + description: Datastore is the name or inventory path of the datastore + in which the virtual machine is created/located. + type: string + diskGiB: + description: DiskGiB is the size of a virtual machine's disk, in GiB. + Defaults to the eponymous property value in the template from which + the virtual machine is cloned. + format: int32 type: integer - boostrapCommandOverride: - description: BootstrapCommandOverride allows you to override the bootstrap - command to use for EKS nodes. - type: string - containerRuntime: - description: ContainerRuntime specify the container runtime to use - when bootstrapping EKS. - type: string - diskSetup: - description: DiskSetup specifies options for the creation of partition - tables and file systems on devices. + folder: + description: Folder is the name or inventory path of the folder in + which the virtual machine is created/located. + type: string + guestSoftPowerOffTimeout: + description: "GuestSoftPowerOffTimeout sets the wait timeout for shutdown + in the VM guest. The VM will be powered off forcibly after the timeout + if the VM is still up and running when the PowerOffMode is set to + trySoft. \n This parameter only applies when the PowerOffMode is + set to trySoft. \n If omitted, the timeout defaults to 5 minutes." + type: string + hardwareVersion: + description: HardwareVersion is the hardware version of the virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. Check the compatibility + with the ESXi version before setting the value. + type: string + memoryMiB: + description: MemoryMiB is the size of a virtual machine's memory, + in MiB. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int64 + type: integer + network: + description: Network is the network configuration for this machine's + VM. properties: - filesystems: - description: Filesystems specifies the list of file systems to - setup. + devices: + description: Devices is the list of network devices used by the + virtual machine. TODO(akutz) Make sure at least one network + matches the ClusterSpec.CloudProviderConfiguration.Network.Name items: - description: Filesystem defines the file systems to be created. + description: NetworkDeviceSpec defines the network configuration + for a virtual machine's network device. properties: - device: - description: Device specifies the device name - type: string - extraOpts: - description: ExtraOpts defined extra options to add to the - command for creating the file system. + addressesFromPools: + description: AddressesFromPools is a list of IPAddressPools + that should be assigned to IPAddressClaims. The machine's + cloud-init metadata will be populated with IPAddresses + fulfilled by an IPAM provider. items: - type: string + description: TypedLocalObjectReference contains enough + information to let you locate the typed referenced object + inside the same namespace. + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic type: array - filesystem: - description: Filesystem specifies the file system type. - type: string - label: - description: Label specifies the file system label to be - used. If set to None, no label is used. - type: string - overwrite: - description: Overwrite defines whether or not to overwrite - any existing filesystem. If true, any pre-existing file - system will be destroyed. Use with Caution. - type: boolean - partition: - description: 'Partition specifies the partition to use. - The valid options are: "auto|any", "auto", "any", "none", - and , where NUM is the actual partition number.' - type: string - required: - - device - - filesystem - - label - type: object - type: array - partitions: - description: Partitions specifies the list of the partitions to - setup. - items: - description: Partition defines how to create and layout a partition. - properties: - device: - description: Device is the name of the device. - type: string - layout: - description: Layout specifies the device layout. If it is - true, a single partition will be created for the entire - device. When layout is false, it means don't partition - or ignore existing partitioning. + deviceName: + description: DeviceName may be used to explicitly assign + a name to the network device as it exists in the guest + operating system. + type: string + dhcp4: + description: DHCP4 is a flag that indicates whether or not + to use DHCP for IPv4 on this device. If true then IPAddrs + should not contain any IPv4 addresses. type: boolean - overwrite: - description: Overwrite describes whether to skip checks - and create the partition if a partition or filesystem - is found on the device. Use with caution. Default is 'false'. + dhcp4Overrides: + description: DHCP4Overrides allows for the control over + several DHCP behaviors. Overrides will only be applied + when the corresponding DHCP flag is set. Only configured + values will be sent, omitted values will default to distribution + defaults. Dependent on support in the network stack for + your distribution. For more information see the netplan + reference (https://netplan.io/reference#dhcp-overrides) + properties: + hostname: + description: Hostname is the name which will be sent + to the DHCP server instead of the machine's hostname. + type: string + routeMetric: + description: RouteMetric is used to prioritize routes + for devices. A lower metric for an interface will + have a higher priority. + type: integer + sendHostname: + description: SendHostname when `true`, the hostname + of the machine will be sent to the DHCP server. + type: boolean + useDNS: + description: UseDNS when `true`, the DNS servers in + the DHCP server will be used and take precedence. + type: boolean + useDomains: + description: UseDomains can take the values `true`, + `false`, or `route`. When `true`, the domain name + from the DHCP server will be used as the DNS search + domain for this device. When `route`, the domain name + from the DHCP response will be used for routing DNS + only, not for searching. + type: string + useHostname: + description: UseHostname when `true`, the hostname from + the DHCP server will be set as the transient hostname + of the machine. + type: boolean + useMTU: + description: UseMTU when `true`, the MTU from the DHCP + server will be set as the MTU of the device. + type: boolean + useNTP: + description: UseNTP when `true`, the NTP servers from + the DHCP server will be used by systemd-timesyncd + and take precedence. + type: boolean + useRoutes: + description: UseRoutes when `true`, the routes from + the DHCP server will be installed in the routing table. + type: string + type: object + dhcp6: + description: DHCP6 is a flag that indicates whether or not + to use DHCP for IPv6 on this device. If true then IPAddrs + should not contain any IPv6 addresses. type: boolean - tableType: - description: 'TableType specifies the tupe of partition - table. The following are supported: ''mbr'': default and - setups a MS-DOS partition table ''gpt'': setups a GPT - partition table' - type: string - required: - - device - - layout - type: object - type: array - type: object - dnsClusterIP: - description: DNSClusterIP overrides the IP address to use for DNS - queries within the cluster. - type: string - dockerConfigJson: - description: DockerConfigJson is used for the contents of the /etc/docker/daemon.json - file. Useful if you want a custom config differing from the default - one in the AMI. This is expected to be a json string. - type: string - files: - description: Files specifies extra files to be passed to user_data - upon creation. - items: - description: File defines the input for generating write_files in - cloud-init. - properties: - append: - description: Append specifies whether to append Content to existing - file if Path exists. - type: boolean - content: - description: Content is the actual content of the file. - type: string - contentFrom: - description: ContentFrom is a referenced source of content to - populate the file. - properties: - secret: - description: Secret represents a secret that should populate - this file. + dhcp6Overrides: + description: DHCP6Overrides allows for the control over + several DHCP behaviors. Overrides will only be applied + when the corresponding DHCP flag is set. Only configured + values will be sent, omitted values will default to distribution + defaults. Dependent on support in the network stack for + your distribution. For more information see the netplan + reference (https://netplan.io/reference#dhcp-overrides) properties: - key: - description: Key is the key in the secret's data map - for this value. + hostname: + description: Hostname is the name which will be sent + to the DHCP server instead of the machine's hostname. type: string - name: - description: Name of the secret in the KubeadmBootstrapConfig's - namespace to use. + routeMetric: + description: RouteMetric is used to prioritize routes + for devices. A lower metric for an interface will + have a higher priority. + type: integer + sendHostname: + description: SendHostname when `true`, the hostname + of the machine will be sent to the DHCP server. + type: boolean + useDNS: + description: UseDNS when `true`, the DNS servers in + the DHCP server will be used and take precedence. + type: boolean + useDomains: + description: UseDomains can take the values `true`, + `false`, or `route`. When `true`, the domain name + from the DHCP server will be used as the DNS search + domain for this device. When `route`, the domain name + from the DHCP response will be used for routing DNS + only, not for searching. + type: string + useHostname: + description: UseHostname when `true`, the hostname from + the DHCP server will be set as the transient hostname + of the machine. + type: boolean + useMTU: + description: UseMTU when `true`, the MTU from the DHCP + server will be set as the MTU of the device. + type: boolean + useNTP: + description: UseNTP when `true`, the NTP servers from + the DHCP server will be used by systemd-timesyncd + and take precedence. + type: boolean + useRoutes: + description: UseRoutes when `true`, the routes from + the DHCP server will be installed in the routing table. type: string - required: - - key - - name type: object + gateway4: + description: Gateway4 is the IPv4 gateway used by this device. + Required when DHCP4 is false. + type: string + gateway6: + description: Gateway4 is the IPv4 gateway used by this device. + type: string + ipAddrs: + description: IPAddrs is a list of one or more IPv4 and/or + IPv6 addresses to assign to this device. IP addresses + must also specify the segment length in CIDR notation. + Required when DHCP4 and DHCP6 are both false. + items: + type: string + type: array + macAddr: + description: MACAddr is the MAC address used by this device. + It is generally a good idea to omit this field and allow + a MAC address to be generated. Please note that this value + must use the VMware OUI to work with the in-tree vSphere + cloud provider. + type: string + mtu: + description: MTU is the device’s Maximum Transmission Unit + size in bytes. + format: int64 + type: integer + nameservers: + description: Nameservers is a list of IPv4 and/or IPv6 addresses + used as DNS nameservers. Please note that Linux allows + only three nameservers (https://linux.die.net/man/5/resolv.conf). + items: + type: string + type: array + networkName: + description: NetworkName is the name of the vSphere network + to which the device will be connected. + type: string + routes: + description: Routes is a list of optional, static routes + applied to the device. + items: + description: NetworkRouteSpec defines a static network + route. + properties: + metric: + description: Metric is the weight/priority of the + route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object + type: array + searchDomains: + description: SearchDomains is a list of search domains used + when resolving IP addresses with DNS. + items: + type: string + type: array required: - - secret + - networkName type: object - encoding: - description: Encoding specifies the encoding of the file contents. - enum: - - base64 - - gzip - - gzip+base64 - 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: - - path - type: object - type: array - kubeletExtraArgs: - additionalProperties: - type: string - description: KubeletExtraArgs passes the specified kubelet args into - the Amazon EKS machine bootstrap script - type: object - mounts: - description: Mounts specifies a list of mount points to be setup. - items: - description: MountPoints defines input for generated mounts in cloud-init. - items: + type: array + preferredAPIServerCidr: + description: PreferredAPIServeCIDR is the preferred CIDR for the + Kubernetes API server endpoint on this machine type: string - type: array - type: array - ntp: - description: NTP specifies NTP configuration - properties: - enabled: - description: Enabled specifies whether NTP should be enabled - type: boolean - servers: - description: Servers specifies which NTP servers to use + routes: + description: Routes is a list of optional, static routes applied + to the virtual machine. items: - type: string + description: NetworkRouteSpec defines a static network route. + properties: + metric: + description: Metric is the weight/priority of the route. + format: int32 + type: integer + to: + description: To is an IPv4 or IPv6 address. + type: string + via: + description: Via is an IPv4 or IPv6 address. + type: string + required: + - metric + - to + - via + type: object type: array - type: object - pauseContainer: - description: PauseContainer allows customization of the pause container - to use. - properties: - accountNumber: - description: AccountNumber is the AWS account number to pull the - pause container from. - type: string - version: - description: Version is the tag of the pause container to use. - type: string required: - - accountNumber - - version + - devices type: object - postBootstrapCommands: - description: PostBootstrapCommands specifies extra commands to run - after bootstrapping nodes to the cluster + numCPUs: + description: NumCPUs is the number of virtual processors in a virtual + machine. Defaults to the eponymous property value in the template + from which the virtual machine is cloned. + format: int32 + type: integer + numCoresPerSocket: + description: NumCPUs is the number of cores among which to distribute + CPUs in this virtual machine. Defaults to the eponymous property + value in the template from which the virtual machine is cloned. + format: int32 + type: integer + os: + description: OS is the Operating System of the virtual machine Defaults + to Linux + type: string + pciDevices: + description: PciDevices is the list of pci devices used by the virtual + machine. items: - type: string + description: PCIDeviceSpec defines virtual machine's PCI configuration + properties: + deviceId: + description: DeviceID is the device ID of a virtual machine's + PCI, in integer. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int32 + type: integer + vendorId: + description: VendorId is the vendor ID of a virtual machine's + PCI, in integer. Defaults to the eponymous property value + in the template from which the virtual machine is cloned. + format: int32 + type: integer + type: object type: array - preBootstrapCommands: - description: PreBootstrapCommands specifies extra commands to run - before bootstrapping nodes to the cluster + powerOffMode: + default: hard + description: "PowerOffMode describes the desired behavior when powering + off a VM. \n There are three, supported power off modes: hard, soft, + and trySoft. The first mode, hard, is the equivalent of a physical + system's power cord being ripped from the wall. The soft mode requires + the VM's guest to have VM Tools installed and attempts to gracefully + shut down the VM. Its variant, trySoft, first attempts a graceful + shutdown, and if that fails or the VM is not in a powered off state + after reaching the GuestSoftPowerOffTimeout, the VM is halted. \n + If omitted, the mode defaults to hard." + enum: + - hard + - soft + - trySoft + type: string + resourcePool: + description: ResourcePool is the name or inventory path of the resource + pool in which the virtual machine is created/located. + type: string + server: + description: Server is the IP address or FQDN of the vSphere server + on which the virtual machine is created/located. + type: string + snapshot: + description: Snapshot is the name of the snapshot from which to create + a linked clone. This field is ignored if LinkedClone is not enabled. + Defaults to the source's current snapshot. + type: string + storagePolicyName: + description: StoragePolicyName of the storage policy to use with this + Virtual Machine + type: string + tagIDs: + description: TagIDs is an optional set of tags to add to an instance. + Specified tagIDs must use URN-notation instead of display names. items: type: string type: array - serviceIPV6Cidr: - description: ServiceIPV6Cidr is the ipv6 cidr range of the cluster. - If this is specified then the ip family will be set to ipv6. + template: + description: Template is the name or inventory path of the template + used to clone the virtual machine. + minLength: 1 type: string - useMaxPods: - description: UseMaxPods sets --max-pods for the kubelet when true. - type: boolean - users: - description: Users specifies extra users to add - items: - description: User defines the input for a generated user in cloud-init. - properties: - gecos: - description: Gecos specifies the gecos to use for the user - type: string - groups: - description: Groups specifies the additional groups for the - user - type: string - homeDir: - description: HomeDir specifies the home directory to use for - the user - type: string - inactive: - description: Inactive specifies whether to mark the user as - inactive - type: boolean - lockPassword: - description: LockPassword specifies if password login should - be disabled - type: boolean - name: - description: Name specifies the username - type: string - passwd: - description: Passwd specifies a hashed password for the user - type: string - passwdFrom: - description: PasswdFrom is a referenced source of passwd to - populate the passwd. - properties: - secret: - description: Secret represents a secret that should populate - this password. - properties: - key: - description: Key is the key in the secret's data map - for this value. - type: string - name: - description: Name of the secret in the KubeadmBootstrapConfig's - namespace to use. - type: string - required: - - key - - name - type: object - required: - - secret - type: object - primaryGroup: - description: PrimaryGroup specifies the primary group for the - user - type: string - shell: - description: Shell specifies the user's shell - type: string - sshAuthorizedKeys: - description: SSHAuthorizedKeys specifies a list of ssh authorized - keys for the user - items: - type: string - type: array - sudo: - description: Sudo specifies a sudo role for the user - type: string - required: - - name - type: object - type: array + thumbprint: + description: Thumbprint is the colon-separated SHA-1 checksum of the + given vCenter server's host certificate When this is set to empty, + this VirtualMachine would be created without TLS certificate validation + of the communication between Cluster API Provider vSphere and the + VMware vCenter server. + type: string + required: + - network + - template type: object status: - description: EKSConfigStatus defines the observed state of the Amazon - EKS Bootstrap Configuration. + description: VSphereVMStatus defines the observed state of VSphereVM properties: + addresses: + description: Addresses is a list of the VM's IP addresses. This field + is required at runtime for other controllers that read this CRD + as unstructured data. + items: + type: string + type: array + cloneMode: + description: CloneMode is the type of clone operation used to clone + this VM. Since LinkedMode is the default but fails gracefully if + the source of the clone has no snapshots, this field may be used + to determine the actual type of clone operation used to create this + VM. + type: string conditions: - description: Conditions defines current service state of the EKSConfig. + description: Conditions defines current service state of the VSphereVM. items: description: Condition defines an observation of a Cluster API resource operational state. @@ -12361,515 +6318,103 @@ spec: - type type: object type: array - dataSecretName: - description: DataSecretName is the name of the secret that stores - the bootstrap data script. - type: string - failureMessage: - description: FailureMessage will be set on non-retryable errors - type: string - failureReason: - description: FailureReason will be set on non-retryable errors - type: string - observedGeneration: - description: ObservedGeneration is the latest generation observed - by the controller. - format: int64 - type: integer - ready: - description: Ready indicates the BootstrapData secret is ready to - be consumed - type: boolean - type: object - type: object - served: true - storage: true - subresources: - status: {} ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert - controller-gen.kubebuilder.io/version: v0.12.1 - labels: - cluster.x-k8s.io/provider: infrastructure-aws - cluster.x-k8s.io/v1alpha3: v1alpha3 - cluster.x-k8s.io/v1alpha4: v1alpha4 - cluster.x-k8s.io/v1beta1: v1beta1_v1beta2 - name: eksconfigtemplates.bootstrap.cluster.x-k8s.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - caBundle: Cg== - service: - name: capa-webhook-service - namespace: capa-system - path: /convert - conversionReviewVersions: - - v1 - - v1beta1 - group: bootstrap.cluster.x-k8s.io - names: - categories: - - cluster-api - kind: EKSConfigTemplate - listKind: EKSConfigTemplateList - plural: eksconfigtemplates - shortNames: - - eksct - singular: eksconfigtemplate - scope: Namespaced - versions: - - name: v1beta1 - schema: - openAPIV3Schema: - description: EKSConfigTemplate is the Amazon EKS Bootstrap Configuration Template - 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: EKSConfigTemplateSpec defines the desired state of templated - EKSConfig Amazon EKS Bootstrap Configuration resources. - properties: - template: - description: EKSConfigTemplateResource defines the Template structure. - properties: - spec: - description: EKSConfigSpec defines the desired state of Amazon - EKS Bootstrap Configuration. - properties: - apiRetryAttempts: - description: APIRetryAttempts is the number of retry attempts - for AWS API call. - type: integer - containerRuntime: - description: ContainerRuntime specify the container runtime - to use when bootstrapping EKS. - type: string - dnsClusterIP: - description: DNSClusterIP overrides the IP address to use - for DNS queries within the cluster. - type: string - dockerConfigJson: - description: DockerConfigJson is used for the contents of - the /etc/docker/daemon.json file. Useful if you want a custom - config differing from the default one in the AMI. This is - expected to be a json string. - type: string - kubeletExtraArgs: - additionalProperties: - type: string - description: KubeletExtraArgs passes the specified kubelet - args into the Amazon EKS machine bootstrap script - type: object - pauseContainer: - description: PauseContainer allows customization of the pause - container to use. - properties: - accountNumber: - description: AccountNumber is the AWS account number to - pull the pause container from. - type: string - version: - description: Version is the tag of the pause container - to use. - type: string - required: - - accountNumber - - version - type: object - serviceIPV6Cidr: - description: ServiceIPV6Cidr is the ipv6 cidr range of the - cluster. If this is specified then the ip family will be - set to ipv6. - type: string - useMaxPods: - description: UseMaxPods sets --max-pods for the kubelet when - true. - type: boolean - type: object - type: object - required: - - template - type: object - type: object - served: true - storage: false - - name: v1beta2 - schema: - openAPIV3Schema: - description: EKSConfigTemplate is the Amazon EKS Bootstrap Configuration Template - 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/sig-architecture/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/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: EKSConfigTemplateSpec defines the desired state of templated - EKSConfig Amazon EKS Bootstrap Configuration resources. - properties: - template: - description: EKSConfigTemplateResource defines the Template structure. - properties: - spec: - description: EKSConfigSpec defines the desired state of Amazon - EKS Bootstrap Configuration. - properties: - apiRetryAttempts: - description: APIRetryAttempts is the number of retry attempts - for AWS API call. - type: integer - boostrapCommandOverride: - description: BootstrapCommandOverride allows you to override - the bootstrap command to use for EKS nodes. - type: string - containerRuntime: - description: ContainerRuntime specify the container runtime - to use when bootstrapping EKS. - type: string - diskSetup: - description: DiskSetup specifies options for the creation - of partition tables and file systems on devices. - properties: - filesystems: - description: Filesystems specifies the list of file systems - to setup. - items: - description: Filesystem defines the file systems to - be created. - properties: - device: - description: Device specifies the device name - type: string - extraOpts: - description: ExtraOpts defined extra options to - add to the command for creating the file system. - items: - type: string - type: array - filesystem: - description: Filesystem specifies the file system - type. - type: string - label: - description: Label specifies the file system label - to be used. If set to None, no label is used. - type: string - overwrite: - description: Overwrite defines whether or not to - overwrite any existing filesystem. If true, any - pre-existing file system will be destroyed. Use - with Caution. - type: boolean - partition: - description: 'Partition specifies the partition - to use. The valid options are: "auto|any", "auto", - "any", "none", and , where NUM is the actual - partition number.' - type: string - required: - - device - - filesystem - - label - type: object - type: array - partitions: - description: Partitions specifies the list of the partitions - to setup. - items: - description: Partition defines how to create and layout - a partition. - properties: - device: - description: Device is the name of the device. - type: string - layout: - description: Layout specifies the device layout. - If it is true, a single partition will be created - for the entire device. When layout is false, it - means don't partition or ignore existing partitioning. - type: boolean - overwrite: - description: Overwrite describes whether to skip - checks and create the partition if a partition - or filesystem is found on the device. Use with - caution. Default is 'false'. - type: boolean - tableType: - description: 'TableType specifies the tupe of partition - table. The following are supported: ''mbr'': default - and setups a MS-DOS partition table ''gpt'': setups - a GPT partition table' - type: string - required: - - device - - layout - type: object - type: array - type: object - dnsClusterIP: - description: DNSClusterIP overrides the IP address to use - for DNS queries within the cluster. - type: string - dockerConfigJson: - description: DockerConfigJson is used for the contents of - the /etc/docker/daemon.json file. Useful if you want a custom - config differing from the default one in the AMI. This is - expected to be a json string. - type: string - files: - description: Files specifies extra files to be passed to user_data - upon creation. - items: - description: File defines the input for generating write_files - in cloud-init. - properties: - append: - description: Append specifies whether to append Content - to existing file if Path exists. - type: boolean - content: - description: Content is the actual content of the file. - type: string - contentFrom: - description: ContentFrom is a referenced source of content - to populate the file. - properties: - secret: - description: Secret represents a secret that should - populate this file. - properties: - key: - description: Key is the key in the secret's - data map for this value. - type: string - name: - description: Name of the secret in the KubeadmBootstrapConfig's - namespace to use. - type: string - required: - - key - - name - type: object - required: - - secret - type: object - encoding: - description: Encoding specifies the encoding of the - file contents. - enum: - - base64 - - gzip - - gzip+base64 - 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: - - path - type: object - type: array - kubeletExtraArgs: - additionalProperties: - type: string - description: KubeletExtraArgs passes the specified kubelet - args into the Amazon EKS machine bootstrap script - type: object - mounts: - description: Mounts specifies a list of mount points to be - setup. - items: - description: MountPoints defines input for generated mounts - in cloud-init. - items: - type: string - type: array - type: array - ntp: - description: NTP specifies NTP configuration - properties: - enabled: - description: Enabled specifies whether NTP should be enabled - type: boolean - servers: - description: Servers specifies which NTP servers to use - items: - type: string - type: array - type: object - pauseContainer: - description: PauseContainer allows customization of the pause - container to use. - properties: - accountNumber: - description: AccountNumber is the AWS account number to - pull the pause container from. - type: string - version: - description: Version is the tag of the pause container - to use. - type: string - required: - - accountNumber - - version - type: object - postBootstrapCommands: - description: PostBootstrapCommands specifies extra commands - to run after bootstrapping nodes to the cluster - items: - type: string - type: array - preBootstrapCommands: - description: PreBootstrapCommands specifies extra commands - to run before bootstrapping nodes to the cluster - items: - type: string - type: array - serviceIPV6Cidr: - description: ServiceIPV6Cidr is the ipv6 cidr range of the - cluster. If this is specified then the ip family will be - set to ipv6. + failureMessage: + description: "FailureMessage will be set in the event that there is + a terminal problem reconciling the vspherevm and will contain a + more verbose string suitable for logging and human consumption. + \n This field should not be set for transitive errors that a controller + faces that are expected to be fixed automatically over time (like + service outages), but instead indicate that something is fundamentally + wrong with the vm. \n Any transient errors that occur during the + reconciliation of vspherevms can be added as events to the vspherevm + object and/or logged in the controller's output." + type: string + failureReason: + description: "FailureReason will be set in the event that there is + a terminal problem reconciling the vspherevm and will contain a + succinct value suitable for vm interpretation. \n This field should + not be set for transitive errors that a controller faces that are + expected to be fixed automatically over time (like service outages), + but instead indicate that something is fundamentally wrong with + the vm. \n Any transient errors that occur during the reconciliation + of vspherevms can be added as events to the vspherevm object and/or + logged in the controller's output." + type: string + host: + description: Host describes the hostname or IP address of the infrastructure + host that the VSphereVM is residing on. + type: string + moduleUUID: + description: ModuleUUID is the unique identifier for the vCenter cluster + module construct which is used to configure anti-affinity. Objects + with the same ModuleUUID will be anti-affined, meaning that the + vCenter DRS will best effort schedule the VMs on separate hosts. + type: string + network: + description: Network returns the network status for each of the machine's + configured network interfaces. + items: + description: NetworkStatus provides information about one of a VM's + networks. + properties: + connected: + description: Connected is a flag that indicates whether this + network is currently connected to the VM. + type: boolean + ipAddrs: + description: IPAddrs is one or more IP addresses reported by + vm-tools. + items: type: string - useMaxPods: - description: UseMaxPods sets --max-pods for the kubelet when - true. - type: boolean - users: - description: Users specifies extra users to add - items: - description: User defines the input for a generated user - in cloud-init. - properties: - gecos: - description: Gecos specifies the gecos to use for the - user - type: string - groups: - description: Groups specifies the additional groups - for the user - type: string - homeDir: - description: HomeDir specifies the home directory to - use for the user - type: string - inactive: - description: Inactive specifies whether to mark the - user as inactive - type: boolean - lockPassword: - description: LockPassword specifies if password login - should be disabled - type: boolean - name: - description: Name specifies the username - type: string - passwd: - description: Passwd specifies a hashed password for - the user - type: string - passwdFrom: - description: PasswdFrom is a referenced source of passwd - to populate the passwd. - properties: - secret: - description: Secret represents a secret that should - populate this password. - properties: - key: - description: Key is the key in the secret's - data map for this value. - type: string - name: - description: Name of the secret in the KubeadmBootstrapConfig's - namespace to use. - type: string - required: - - key - - name - type: object - required: - - secret - type: object - primaryGroup: - description: PrimaryGroup specifies the primary group - for the user - type: string - shell: - description: Shell specifies the user's shell - type: string - sshAuthorizedKeys: - description: SSHAuthorizedKeys specifies a list of ssh - authorized keys for the user - items: - type: string - type: array - sudo: - description: Sudo specifies a sudo role for the user - type: string - required: - - name - type: object - type: array - type: object - type: object - required: - - template + type: array + macAddr: + description: MACAddr is the MAC address of the network device. + type: string + networkName: + description: NetworkName is the name of the network. + type: string + required: + - macAddr + type: object + type: array + ready: + description: Ready is true when the provider resource is ready. This + field is required at runtime for other controllers that read this + CRD as unstructured data. + type: boolean + retryAfter: + description: RetryAfter tracks the time we can retry queueing a task + format: date-time + type: string + snapshot: + description: Snapshot is the name of the snapshot from which the VM + was cloned if LinkedMode is enabled. + type: string + taskRef: + description: TaskRef is a managed object reference to a Task related + to the machine. This value is set automatically at runtime and should + not be set or modified by users. + type: string + vmRef: + description: VMRef is the the VM's Managed Object Reference on vSphere. + It can be used by consumers to programatically get this VM representation + on vSphere in case of the need to retrieve informations. This field + is set once the machine is created and should not be changed + type: string type: object type: object served: true storage: true ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - annotations: - ${AWS_CONTROLLER_IAM_ROLE/#arn/eks.amazonaws.com/role-arn: arn} - labels: - cluster.x-k8s.io/provider: infrastructure-aws - control-plane: controller-manager - name: capa-controller-manager - namespace: capa-system + subresources: + status: {} --- apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-leader-elect-role - namespace: capa-system + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-leader-election-role + namespace: capv-system rules: - apiGroups: - "" @@ -12910,19 +6455,45 @@ rules: - patch - delete --- +aggregationRule: + clusterRoleSelectors: + - matchLabels: + capv.infrastucture.cluster.x-k8s.io/aggregate-to-manager: "true" +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-aggregated-manager-role +rules: [] +--- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-manager-role + capv.infrastucture.cluster.x-k8s.io/aggregate-to-manager: "true" + cluster.x-k8s.io/aggregate-to-manager: "true" + cluster.x-k8s.io/provider: infrastructure-vsphere + kubeadm.controlplane.cluster.x-k8s.io/aggregate-to-manager: "true" + name: capv-manager-role rules: - apiGroups: - "" resources: + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - "" + resources: + - configmaps - events + - nodes verbs: - create + - delete - get - list - patch @@ -12931,56 +6502,78 @@ rules: - apiGroups: - "" resources: - - namespaces + - configmaps/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - events verbs: + - create - get - list + - patch + - update - watch - apiGroups: - "" resources: - - secrets + - persistentvolumeclaims verbs: - create - delete - get - list - - patch - update - watch - apiGroups: - - bootstrap.cluster.x-k8s.io + - "" resources: - - eksconfigs + - persistentvolumeclaims/status verbs: - get - - list - patch - update - - watch - apiGroups: - - bootstrap.cluster.x-k8s.io + - "" + resources: + - secrets + verbs: + - get +- apiGroups: + - "" resources: - - eksconfigs/status + - serviceaccounts verbs: + - create + - delete - get + - list - patch - update + - watch - apiGroups: - - cluster.x-k8s.io + - "" resources: - - clusters - - clusters/status + - services verbs: - get - list - watch +- apiGroups: + - "" + resources: + - services/status + verbs: + - get - apiGroups: - cluster.x-k8s.io resources: - clusters - - machinepools - - machines + - clusters/status verbs: - get - list @@ -12996,7 +6589,8 @@ rules: - apiGroups: - cluster.x-k8s.io resources: - - machinepools + - machinedeployments + - machinesets verbs: - get - list @@ -13004,8 +6598,7 @@ rules: - apiGroups: - cluster.x-k8s.io resources: - - machinepools - - machinepools/status + - machines verbs: - get - list @@ -13014,7 +6607,6 @@ rules: - apiGroups: - cluster.x-k8s.io resources: - - machines - machines/status verbs: - get @@ -13023,83 +6615,117 @@ rules: - apiGroups: - controlplane.cluster.x-k8s.io resources: - - awsmanagedcontrolplanes + - kubeadmcontrolplanes verbs: - - delete - get - list - - patch - - update - watch - apiGroups: - - controlplane.cluster.x-k8s.io + - "" resources: - - awsmanagedcontrolplanes - - awsmanagedcontrolplanes/status + - namespaces verbs: - get - list - watch - apiGroups: - - controlplane.cluster.x-k8s.io + - "" resources: - - awsmanagedcontrolplanes/status + - nodes verbs: + - delete - get - - patch - - update + - list - apiGroups: - - controlplane.cluster.x-k8s.io + - "" resources: - - rosacontrolplanes - - rosacontrolplanes/status + - secrets verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - - "" + - infrastructure.cluster.x-k8s.io resources: - - events + - vsphereclusteridentities verbs: - create + - delete - get - list - patch + - update - watch - apiGroups: - infrastructure.cluster.x-k8s.io resources: - - awsclustercontrolleridentities + - vsphereclusteridentities/status + verbs: + - get + - patch + - update +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - vsphereclusters verbs: - create + - delete - get - list + - patch + - update - watch - apiGroups: - infrastructure.cluster.x-k8s.io resources: - - awsclustercontrolleridentities - - awsclusterroleidentities - - awsclusterstaticidentities + - vsphereclusters/status + verbs: + - get + - patch + - update +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - vspheredeploymentzones verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - infrastructure.cluster.x-k8s.io resources: - - awsclusterroleidentities - - awsclusterstaticidentities + - vspheredeploymentzones/status + verbs: + - get + - patch + - update +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - vspherefailuredomains verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - infrastructure.cluster.x-k8s.io resources: - - awsclusters + - vspheremachines verbs: + - create - delete - get - list @@ -13109,7 +6735,7 @@ rules: - apiGroups: - infrastructure.cluster.x-k8s.io resources: - - awsclusters/status + - vspheremachines/status verbs: - get - patch @@ -13117,8 +6743,17 @@ rules: - apiGroups: - infrastructure.cluster.x-k8s.io resources: - - awsfargateprofiles + - vspheremachinetemplates + verbs: + - get + - list + - watch +- apiGroups: + - infrastructure.cluster.x-k8s.io + resources: + - vspherevms verbs: + - create - delete - get - list @@ -13128,44 +6763,74 @@ rules: - apiGroups: - infrastructure.cluster.x-k8s.io resources: - - awsfargateprofiles/status + - vspherevms/status verbs: - get - patch - update - apiGroups: - - infrastructure.cluster.x-k8s.io + - ipam.cluster.x-k8s.io resources: - - awsmachinepools + - ipaddressclaims verbs: - - delete + - create - get - list - patch - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - ipam.cluster.x-k8s.io resources: - - awsmachinepools - - awsmachinepools/status + - ipaddresses verbs: - get - list - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - netoperator.vmware.com + resources: + - networks + verbs: + - get + - list + - watch +- apiGroups: + - rbac.authorization.k8s.io resources: - - awsmachinepools/status + - rolebindings + - roles verbs: + - create + - delete - get + - list - patch - update + - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - topology.tanzu.vmware.com + resources: + - availabilityzones + verbs: + - get + - list + - watch +- apiGroups: + - topology.tanzu.vmware.com resources: - - awsmachines + - availabilityzones/status verbs: + - get + - list + - watch +- apiGroups: + - vmoperator.vmware.com + resources: + - virtualmachineimages + - virtualmachineimages/status + verbs: + - create - delete - get - list @@ -13173,35 +6838,50 @@ rules: - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmoperator.vmware.com resources: - - awsmachines - - awsmachines/status + - virtualmachines verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmoperator.vmware.com resources: - - awsmachines/status + - virtualmachineservices + - virtualmachineservices/status verbs: + - create + - delete - get + - list - patch - update + - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmoperator.vmware.com resources: - - awsmachinetemplates + - virtualmachinesetresourcepolicies + - virtualmachinesetresourcepolicies/status verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmware.com resources: - - awsmanagedclusters + - virtualnetworks + - virtualnetworks/status verbs: + - create - delete - get - list @@ -13209,27 +6889,47 @@ rules: - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmware.infrastructure.cluster.x-k8s.io + resources: + - providerserviceaccounts + verbs: + - get + - list + - watch +- apiGroups: + - vmware.infrastructure.cluster.x-k8s.io + resources: + - providerserviceaccounts/status + verbs: + - get + - patch + - update +- apiGroups: + - vmware.infrastructure.cluster.x-k8s.io resources: - - awsmanagedclusters - - awsmanagedclusters/status + - vsphereclusters verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmware.infrastructure.cluster.x-k8s.io resources: - - awsmanagedclusters/status + - vsphereclusters/status verbs: - get - patch - update - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmware.infrastructure.cluster.x-k8s.io resources: - - awsmanagedmachinepools + - vsphereclustertemplates verbs: + - create - delete - get - list @@ -13237,27 +6937,31 @@ rules: - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmware.infrastructure.cluster.x-k8s.io resources: - - awsmanagedmachinepools - - awsmanagedmachinepools/status + - vspheremachines verbs: + - create + - delete - get - list + - patch + - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmware.infrastructure.cluster.x-k8s.io resources: - - awsmanagedmachinepools/status + - vspheremachines/status verbs: - get - patch - update - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmware.infrastructure.cluster.x-k8s.io resources: - - rosaclusters + - vspheremachinetemplates verbs: + - create - delete - get - list @@ -13265,9 +6969,9 @@ rules: - update - watch - apiGroups: - - infrastructure.cluster.x-k8s.io + - vmware.infrastructure.cluster.x-k8s.io resources: - - rosaclusters/status + - vspheremachinetemplates/status verbs: - get - patch @@ -13277,126 +6981,92 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-leader-elect-rolebinding - namespace: capa-system + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-leader-election-rolebinding + namespace: capv-system roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: capa-leader-elect-role + name: capv-leader-election-role subjects: - kind: ServiceAccount - name: capa-controller-manager - namespace: capa-system + name: default + namespace: capv-system --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-manager-rolebinding + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-manager-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: capa-manager-role + name: capv-aggregated-manager-role subjects: - kind: ServiceAccount - name: capa-controller-manager - namespace: capa-system + name: default + namespace: capv-system --- apiVersion: v1 -data: - credentials: ${AWS_B64ENCODED_CREDENTIALS} kind: Secret metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-manager-bootstrap-credentials - namespace: capa-system + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-manager-bootstrap-credentials + namespace: capv-system +stringData: + credentials.yaml: |- + username: '${VSPHERE_USERNAME}' + password: '${VSPHERE_PASSWORD}' type: Opaque --- apiVersion: v1 kind: Service metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-metrics-service - namespace: capa-system -spec: - ports: - - port: 8080 - protocol: TCP - targetPort: metrics - selector: - cluster.x-k8s.io/provider: infrastructure-aws - type: ClusterIP ---- -apiVersion: v1 -kind: Service -metadata: - labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-webhook-service - namespace: capa-system + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-webhook-service + namespace: capv-system spec: ports: - port: 443 targetPort: webhook-server selector: - cluster.x-k8s.io/provider: infrastructure-aws + cluster.x-k8s.io/provider: infrastructure-vsphere --- apiVersion: apps/v1 kind: Deployment metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - control-plane: capa-controller-manager - name: capa-controller-manager - namespace: capa-system + cluster.x-k8s.io/provider: infrastructure-vsphere + control-plane: controller-manager + name: capv-controller-manager + namespace: capv-system spec: replicas: 1 selector: matchLabels: - cluster.x-k8s.io/provider: infrastructure-aws - control-plane: capa-controller-manager + cluster.x-k8s.io/provider: infrastructure-vsphere + control-plane: controller-manager template: metadata: - annotations: - iam.amazonaws.com/role: ${AWS_CONTROLLER_IAM_ROLE:=""} labels: - cluster.x-k8s.io/provider: infrastructure-aws - control-plane: capa-controller-manager + cluster.x-k8s.io/provider: infrastructure-vsphere + control-plane: controller-manager spec: - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - preference: - matchExpressions: - - key: ${K8S_CP_LABEL:=node-role.kubernetes.io/control-plane} - operator: Exists - weight: 10 - - preference: - matchExpressions: - - key: node-role.kubernetes.io/master - operator: Exists - weight: 10 containers: - args: - --leader-elect - - --feature-gates=EKS=${CAPA_EKS:=true},EKSEnableIAM=${CAPA_EKS_IAM:=false},EKSAllowAddRoles=${CAPA_EKS_ADD_ROLES:=false},EKSFargate=${EXP_EKS_FARGATE:=false},MachinePool=${EXP_MACHINE_POOL:=false},EventBridgeInstanceState=${EVENT_BRIDGE_INSTANCE_STATE:=false},AutoControllerIdentityCreator=${AUTO_CONTROLLER_IDENTITY_CREATOR:=true},BootstrapFormatIgnition=${EXP_BOOTSTRAP_FORMAT_IGNITION:=false},ExternalResourceGC=${EXP_EXTERNAL_RESOURCE_GC:=false},AlternativeGCStrategy=${EXP_ALTERNATIVE_GC_STRATEGY:=false},TagUnmanagedNetworkResources=${TAG_UNMANAGED_NETWORK_RESOURCES:=true} - - --v=${CAPA_LOGLEVEL:=0} - - --metrics-bind-addr=0.0.0.0:8080 - env: - - name: AWS_SHARED_CREDENTIALS_FILE - value: /home/.aws/credentials - image: gcr.io/k8s-staging-cluster-api-aws/cluster-api-aws-controller:v1.4.0 + - --v=4 + - --enable-keep-alive + - --feature-gates=NodeAntiAffinity=${EXP_NODE_ANTI_AFFINITY:=false} + image: registry.k8s.io/cluster-api-vsphere/cluster-api-vsphere-controller:v1.8.7 imagePullPolicy: IfNotPresent livenessProbe: - failureThreshold: 3 httpGet: path: /healthz port: healthz - periodSeconds: 10 name: manager ports: - containerPort: 9443 @@ -13420,14 +7090,13 @@ spec: - mountPath: /tmp/k8s-webhook-server/serving-certs name: cert readOnly: true - - mountPath: /home/.aws - name: credentials + - mountPath: /etc/capv + name: manager-bootstrap-credentials + readOnly: true securityContext: - fsGroup: 1000 runAsNonRoot: true seccompProfile: type: RuntimeDefault - serviceAccountName: capa-controller-manager terminationGracePeriodSeconds: 10 tolerations: - effect: NoSchedule @@ -13438,34 +7107,34 @@ spec: - name: cert secret: defaultMode: 420 - secretName: capa-webhook-service-cert - - name: credentials + secretName: capv-webhook-service-cert + - name: manager-bootstrap-credentials secret: - secretName: capa-manager-bootstrap-credentials + secretName: capv-manager-bootstrap-credentials --- apiVersion: cert-manager.io/v1 kind: Certificate metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-serving-cert - namespace: capa-system + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-serving-cert + namespace: capv-system spec: dnsNames: - - capa-webhook-service.capa-system.svc - - capa-webhook-service.capa-system.svc.cluster.local + - capv-webhook-service.capv-system.svc + - capv-webhook-service.capv-system.svc.cluster.local issuerRef: kind: Issuer - name: capa-selfsigned-issuer - secretName: capa-webhook-service-cert + name: capv-selfsigned-issuer + secretName: capv-webhook-service-cert --- apiVersion: cert-manager.io/v1 kind: Issuer metadata: labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-selfsigned-issuer - namespace: capa-system + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-selfsigned-issuer + namespace: capv-system spec: selfSigned: {} --- @@ -13473,567 +7142,207 @@ apiVersion: admissionregistration.k8s.io/v1 kind: MutatingWebhookConfiguration metadata: annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-mutating-webhook-configuration + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-mutating-webhook-configuration webhooks: - admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awscluster - failurePolicy: Fail - matchPolicy: Equivalent - name: default.awscluster.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclusters - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awsclustercontrolleridentity - failurePolicy: Fail - matchPolicy: Equivalent - name: default.awsclustercontrolleridentity.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclustercontrolleridentities - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awsclusterroleidentity - failurePolicy: Fail - matchPolicy: Equivalent - name: default.awsclusterroleidentity.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclusterroleidentities - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awsclusterstaticidentity - failurePolicy: Fail - matchPolicy: Equivalent - name: default.awsclusterstaticidentity.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclusterstaticidentities - sideEffects: None -- admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awsclustertemplate + name: capv-webhook-service + namespace: capv-system + path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-vspheredeploymentzone failurePolicy: Fail matchPolicy: Equivalent - name: default.awsclustertemplate.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclustertemplates - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awsmachine - failurePolicy: Fail - name: mutation.awsmachine.infrastructure.cluster.x-k8s.io + name: default.vspheredeploymentzone.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsmachines + - vspheredeploymentzones sideEffects: None - admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awsfargateprofile + name: capv-webhook-service + namespace: capv-system + path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-vspherefailuredomain failurePolicy: Fail matchPolicy: Equivalent - name: default.awsfargateprofile.infrastructure.cluster.x-k8s.io + name: default.vspherefailuredomain.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsfargateprofiles + - vspherefailuredomains sideEffects: None - admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awsmachinepool + name: capv-webhook-service + namespace: capv-system + path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-vspheremachine failurePolicy: Fail matchPolicy: Equivalent - name: default.awsmachinepool.infrastructure.cluster.x-k8s.io + name: default.vspheremachine.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsmachinepools + - vspheremachines sideEffects: None - admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-infrastructure-cluster-x-k8s-io-v1beta2-awsmanagedmachinepool + name: capv-webhook-service + namespace: capv-system + path: /mutate-infrastructure-cluster-x-k8s-io-v1beta1-vspherevm failurePolicy: Fail matchPolicy: Equivalent - name: default.awsmanagedmachinepool.infrastructure.cluster.x-k8s.io + name: default.vspherevm.infrastructure.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsmanagedmachinepools - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-bootstrap-cluster-x-k8s-io-v1beta2-eksconfig - failurePolicy: Fail - matchPolicy: Equivalent - name: default.eksconfigs.bootstrap.cluster.x-k8s.io - rules: - - apiGroups: - - bootstrap.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - eksconfig - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-bootstrap-cluster-x-k8s-io-v1beta2-eksconfigtemplate - failurePolicy: Fail - matchPolicy: Equivalent - name: default.eksconfigtemplates.bootstrap.cluster.x-k8s.io - rules: - - apiGroups: - - bootstrap.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - eksconfigtemplate - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /mutate-controlplane-cluster-x-k8s-io-v1beta2-awsmanagedcontrolplane - failurePolicy: Fail - matchPolicy: Equivalent - name: default.awsmanagedcontrolplanes.controlplane.cluster.x-k8s.io - rules: - - apiGroups: - - controlplane.cluster.x-k8s.io - apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsmanagedcontrolplanes + - vspherevms sideEffects: None --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: annotations: - cert-manager.io/inject-ca-from: capa-system/capa-serving-cert + cert-manager.io/inject-ca-from: capv-system/capv-serving-cert labels: - cluster.x-k8s.io/provider: infrastructure-aws - name: capa-validating-webhook-configuration + cluster.x-k8s.io/provider: infrastructure-vsphere + name: capv-validating-webhook-configuration webhooks: - admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awscluster - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.awscluster.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclusters - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsclustercontrolleridentity - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.awsclustercontrolleridentity.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclustercontrolleridentities - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsclusterroleidentity - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.awsclusterroleidentity.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclusterroleidentities - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsclusterstaticidentity - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.awsclusterstaticidentity.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclusterstaticidentities - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsclustertemplate - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.awsclustertemplate.infrastructure.cluster.x-k8s.io - rules: - - apiGroups: - - infrastructure.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsclustertemplates - sideEffects: None -- admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsmachine + name: capv-webhook-service + namespace: capv-system + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-vsphereclustertemplate failurePolicy: Fail matchPolicy: Equivalent - name: validation.awsmachine.infrastructure.cluster.x-k8s.io + name: validation.vsphereclustertemplate.infrastructure.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsmachines + - vsphereclustertemplates sideEffects: None - admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsmachinetemplate + name: capv-webhook-service + namespace: capv-system + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-vspherefailuredomain failurePolicy: Fail matchPolicy: Equivalent - name: validation.awsmachinetemplate.infrastructure.cluster.x-k8s.io + name: validation.vspherefailuredomain.infrastructure.cluster.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsmachinetemplates + - vspherefailuredomains sideEffects: None - admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsfargateprofile + name: capv-webhook-service + namespace: capv-system + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-vspheremachine failurePolicy: Fail matchPolicy: Equivalent - name: validation.awsfargateprofile.infrastructure.cluster.x-k8s.io + name: validation.vspheremachine.infrastructure.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsfargateprofiles + - vspheremachines sideEffects: None - admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsmachinepool + name: capv-webhook-service + namespace: capv-system + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-vspheremachinetemplate failurePolicy: Fail matchPolicy: Equivalent - name: validation.awsmachinepool.infrastructure.cluster.x-k8s.io + name: validation.vspheremachinetemplate.infrastructure.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsmachinepools + - vspheremachinetemplates sideEffects: None - admissionReviewVersions: - - v1 - v1beta1 clientConfig: service: - name: capa-webhook-service - namespace: capa-system - path: /validate-infrastructure-cluster-x-k8s-io-v1beta2-awsmanagedmachinepool + name: capv-webhook-service + namespace: capv-system + path: /validate-infrastructure-cluster-x-k8s-io-v1beta1-vspherevm failurePolicy: Fail matchPolicy: Equivalent - name: validation.awsmanagedmachinepool.infrastructure.cluster.x-k8s.io + name: validation.vspherevm.infrastructure.x-k8s.io rules: - apiGroups: - infrastructure.cluster.x-k8s.io apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - awsmanagedmachinepools - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /validate-bootstrap-cluster-x-k8s-io-v1beta2-eksconfig - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.eksconfigs.bootstrap.cluster.x-k8s.io - rules: - - apiGroups: - - bootstrap.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - eksconfig - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /validate-bootstrap-cluster-x-k8s-io-v1beta2-eksconfigtemplate - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.eksconfigtemplates.bootstrap.cluster.x-k8s.io - rules: - - apiGroups: - - bootstrap.cluster.x-k8s.io - apiVersions: - - v1beta2 - operations: - - CREATE - - UPDATE - resources: - - eksconfigtemplate - sideEffects: None -- admissionReviewVersions: - - v1 - - v1beta1 - clientConfig: - service: - name: capa-webhook-service - namespace: capa-system - path: /validate-controlplane-cluster-x-k8s-io-v1beta2-awsmanagedcontrolplane - failurePolicy: Fail - matchPolicy: Equivalent - name: validation.awsmanagedcontrolplanes.controlplane.cluster.x-k8s.io - rules: - - apiGroups: - - controlplane.cluster.x-k8s.io - apiVersions: - - v1beta2 + - v1beta1 operations: - CREATE - UPDATE resources: - - awsmanagedcontrolplanes + - vspherevms sideEffects: None diff --git a/go.mod b/go.mod index 13e14403c38..4f4c47d7e1a 100644 --- a/go.mod +++ b/go.mod @@ -90,12 +90,12 @@ require ( github.com/thedevsaddam/retry v0.0.0-20200324223450-9769a859cc6d github.com/ulikunitz/xz v0.5.11 github.com/vincent-petithory/dataurl v1.0.0 - github.com/vmware/govmomi v0.30.4 - golang.org/x/crypto v0.14.0 + github.com/vmware/govmomi v0.34.0 + golang.org/x/crypto v0.16.0 golang.org/x/oauth2 v0.10.0 - golang.org/x/sync v0.3.0 - golang.org/x/sys v0.13.0 - golang.org/x/term v0.13.0 + golang.org/x/sync v0.5.0 + golang.org/x/sys v0.15.0 + golang.org/x/term v0.15.0 google.golang.org/api v0.130.0 google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 google.golang.org/grpc v1.58.2 @@ -112,6 +112,7 @@ require ( sigs.k8s.io/cluster-api v1.5.3 sigs.k8s.io/cluster-api-provider-aws/v2 v2.0.0-00010101000000-000000000000 sigs.k8s.io/cluster-api-provider-azure v0.0.0-00010101000000-000000000000 + sigs.k8s.io/cluster-api-provider-vsphere v1.8.7 sigs.k8s.io/controller-runtime v0.16.2 sigs.k8s.io/controller-tools v0.10.0 sigs.k8s.io/yaml v1.3.0 @@ -147,6 +148,7 @@ require ( github.com/coreos/vcontext v0.0.0-20230201181013-d72178a18687 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect + github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02 // indirect github.com/elliotwutingfeng/asciiset v0.0.0-20230602022725-51bbb787efab // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch/v5 v5.7.0 // indirect @@ -189,6 +191,7 @@ require ( github.com/json-iterator/go v1.1.12 // indirect github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/kr/fs v0.1.0 // indirect + github.com/kr/text v0.2.0 // indirect github.com/kylelemons/godebug v1.1.0 // indirect github.com/leodido/go-urn v1.2.3 // indirect github.com/mailru/easyjson v0.7.7 // indirect @@ -229,12 +232,12 @@ require ( go.opentelemetry.io/otel/trace v1.19.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.26.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/mod v0.13.0 // indirect - golang.org/x/net v0.17.0 // indirect - golang.org/x/text v0.13.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.13.0 // indirect + golang.org/x/tools v0.16.0 // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 // indirect @@ -246,7 +249,7 @@ require ( gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect gorm.io/gorm v1.24.5 // indirect - k8s.io/cluster-bootstrap v0.27.2 // indirect + k8s.io/cluster-bootstrap v0.27.4 // indirect k8s.io/component-base v0.28.3 // indirect k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect diff --git a/go.sum b/go.sum index c5aac6a2a26..e9e5ea082d6 100644 --- a/go.sum +++ b/go.sum @@ -243,7 +243,7 @@ github.com/containers/libtrust v0.0.0-20190913040956-14b96171aa3b/go.mod h1:9rfv github.com/containers/ocicrypt v1.0.2/go.mod h1:nsOhbP19flrX6rE7ieGFvBlr7modwmNjsqWarIUce4M= github.com/containers/ocicrypt v1.1.1/go.mod h1:Dm55fwWm1YZAjYRaJ94z2mfZikIyIN4B0oB3dj3jFxY= github.com/containers/storage v1.20.2/go.mod h1:oOB9Ie8OVPojvoaKWEGSEtHbXUAs+tSyr7RO7ZGteMc= -github.com/coredns/caddy v1.1.0 h1:ezvsPrT/tA/7pYDBZxu0cT0VmWk75AfIaf6GSYCNMf0= +github.com/coredns/caddy v1.1.1 h1:2eYKZT7i6yxIfGP3qLJoJ7HAsDJqYB+X68g4NYjSrE0= github.com/coredns/corefile-migration v1.0.21 h1:W/DCETrHDiFo0Wj03EyMkaQ9fwsmSgqTCQDHpceaSsE= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= @@ -321,6 +321,8 @@ github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNE github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= +github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02 h1:tR3jsKPiO/mb6ntzk/dJlHZtm37CPfVp1C9KIo534+4= +github.com/dougm/pretty v0.0.0-20171025230240-2ee9d7453c02/go.mod h1:7NQ3kWOx2cZOSjtcveTa5nqupVr2s6/83sG+rTlI7uA= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= @@ -1185,8 +1187,8 @@ github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1 github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI= -github.com/vmware/govmomi v0.30.4 h1:BCKLoTmiBYRuplv3GxKEMBLtBaJm8PA56vo9bddIpYQ= -github.com/vmware/govmomi v0.30.4/go.mod h1:F7adsVewLNHsW/IIm7ziFURaXDaHEwcc+ym4r3INMdY= +github.com/vmware/govmomi v0.34.0 h1:Aun71BDf1t8r3jNeUWJ3ZM+7kHbIuuNzIuxRVo5LYYU= +github.com/vmware/govmomi v0.34.0/go.mod h1:qWWT6n9mdCr/T9vySsoUqcI04sSEj4CqHXxtk/Y+Los= github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk= github.com/vmware/vmw-ovflib v0.0.0-20170608004843-1f217b9dc714/go.mod h1:jiPk45kn7klhByRvUq5i2vo1RtHKBHj+iWGFpxbXuuI= github.com/xanzy/ssh-agent v0.3.0 h1:wUMzuKtKilRgBAD1sUb8gOwwRr2FGoBVumcjoOACClI= @@ -1259,8 +1261,8 @@ go4.org v0.0.0-20200104003542-c7e774b10ea0/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1 golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -1277,8 +1279,8 @@ golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= -golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1298,8 +1300,9 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1375,13 +1378,15 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1434,8 +1439,8 @@ golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= -golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= -golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.16.0 h1:GO788SKMRunPIBCXiQyo2AaexLstOrVhuAL5YwsckQM= +golang.org/x/tools v0.16.0/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1580,8 +1585,8 @@ k8s.io/apiserver v0.28.3 h1:8Ov47O1cMyeDzTXz0rwcfIIGAP/dP7L8rWbEljRcg5w= k8s.io/cli-runtime v0.19.0/go.mod h1:tun9l0eUklT8IHIM0jors17KmUjcrAxn0myoBYwuNuo= k8s.io/client-go v0.28.3 h1:2OqNb72ZuTZPKCl+4gTKvqao0AMOl9f3o2ijbAj3LI4= k8s.io/client-go v0.28.3/go.mod h1:LTykbBp9gsA7SwqirlCXBWtK0guzfhpoW4qSm7i9dxo= -k8s.io/cluster-bootstrap v0.27.2 h1:OL3onrOwrUD7NQxBUqQwTl1Uu2GQKCkw9BMHpc4PbiA= -k8s.io/cluster-bootstrap v0.27.2/go.mod h1:b++PF0mjUOiTKdPQFlDw7p4V2VquANZ8SfhAwzxZJFM= +k8s.io/cluster-bootstrap v0.27.4 h1:fobmnzmWrv0RcTed71Kdek7ElUWDkQ38zG799o8M8I4= +k8s.io/cluster-bootstrap v0.27.4/go.mod h1:sLvyEcIhRmoG8HhaIDy8htZ9MuaYK6nP+BMKGqqirBs= k8s.io/code-generator v0.18.0/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= @@ -1645,6 +1650,8 @@ sigs.k8s.io/cluster-api-provider-aws/v2 v2.0.0-20231024062453-0bf78b04b305 h1:p3 sigs.k8s.io/cluster-api-provider-aws/v2 v2.0.0-20231024062453-0bf78b04b305/go.mod h1:5WDab1k/zhljuAA6jxijEAuxSFcyCgK670k/5PPebCs= sigs.k8s.io/cluster-api-provider-azure v1.11.1-0.20231026140308-a3f4914170d9 h1:Q6ImZgb9g4tjnCszZ9e/igaOemD5AsNcx/sO/uRteEc= sigs.k8s.io/cluster-api-provider-azure v1.11.1-0.20231026140308-a3f4914170d9/go.mod h1:N9VMyIYoaif6jVMIk9Ptf0GWRXXgZmQ7Wnmo5fUsVVA= +sigs.k8s.io/cluster-api-provider-vsphere v1.8.7 h1:KneNQCQdNZbHhpBG2d5AL/uePtBSO8nMkV8yASo0E7w= +sigs.k8s.io/cluster-api-provider-vsphere v1.8.7/go.mod h1:SaPWEuptuFCGYrWKqblKorQNQZ85hH0MRLapUaFjRU4= sigs.k8s.io/controller-runtime v0.16.1-0.20231024080022-f1c5dd3851ce h1:zQZV2UuXjQgWF4m/fZRgvA/5lm9jqWl7cfxoNMMl4yA= sigs.k8s.io/controller-runtime v0.16.1-0.20231024080022-f1c5dd3851ce/go.mod h1:kDNDxdBG0vwQaukUg2+bsI/3/WMvaZaa3ZxP9VMVqNw= sigs.k8s.io/controller-tools v0.3.1-0.20200617211605-651903477185 h1:wLsmaqTEgs3DIfNzr0u/AfPHSVJbWHj/eevcS4AFvFE= diff --git a/pkg/asset/cluster/cluster.go b/pkg/asset/cluster/cluster.go index af8723b30ee..4bf12a0ffab 100644 --- a/pkg/asset/cluster/cluster.go +++ b/pkg/asset/cluster/cluster.go @@ -5,30 +5,24 @@ import ( "fmt" "path/filepath" "strings" - "time" "github.com/pkg/errors" "github.com/sirupsen/logrus" - "gopkg.in/yaml.v2" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/util/wait" - clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" - utilkubeconfig "sigs.k8s.io/cluster-api/util/kubeconfig" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/manager/signals" "github.com/openshift/installer/pkg/asset" "github.com/openshift/installer/pkg/asset/cluster/aws" "github.com/openshift/installer/pkg/asset/cluster/azure" "github.com/openshift/installer/pkg/asset/cluster/openstack" + "github.com/openshift/installer/pkg/asset/cluster/tfvars" + vcentercontexts "github.com/openshift/installer/pkg/asset/cluster/vsphere" + "github.com/openshift/installer/pkg/asset/ignition/bootstrap" + "github.com/openshift/installer/pkg/asset/ignition/machine" "github.com/openshift/installer/pkg/asset/installconfig" - awsconfig "github.com/openshift/installer/pkg/asset/installconfig/aws" "github.com/openshift/installer/pkg/asset/kubeconfig" - "github.com/openshift/installer/pkg/asset/manifests/capiutils" capimanifests "github.com/openshift/installer/pkg/asset/manifests/clusterapi" "github.com/openshift/installer/pkg/asset/password" "github.com/openshift/installer/pkg/asset/quota" - "github.com/openshift/installer/pkg/clusterapi" + "github.com/openshift/installer/pkg/asset/rhcos" infra "github.com/openshift/installer/pkg/infrastructure/platform" typesaws "github.com/openshift/installer/pkg/types/aws" typesazure "github.com/openshift/installer/pkg/types/azure" @@ -59,18 +53,22 @@ func (c *Cluster) Dependencies() []asset.Asset { return []asset.Asset{ &installconfig.ClusterID{}, &installconfig.InstallConfig{}, - // PlatformCredsCheck, PlatformPermsCheck and PlatformProvisionCheck + // PlatformCredsCheck, PlatformPermsCheck, PlatformProvisionCheck, and VCenterContexts. // perform validations & check perms required to provision infrastructure. // We do not actually use them in this asset directly, hence // they are put in the dependencies but not fetched in Generate. &installconfig.PlatformCredsCheck{}, &installconfig.PlatformPermsCheck{}, &installconfig.PlatformProvisionCheck{}, + &vcentercontexts.VCenterContexts{}, "a.PlatformQuotaCheck{}, - &TerraformVariables{}, + &tfvars.TerraformVariables{}, &password.KubeadminPassword{}, &capimanifests.Cluster{}, &kubeconfig.AdminClient{}, + &bootstrap.Bootstrap{}, + &machine.Master{}, + new(rhcos.Image), } } @@ -82,7 +80,7 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) { clusterID := &installconfig.ClusterID{} installConfig := &installconfig.InstallConfig{} - terraformVariables := &TerraformVariables{} + terraformVariables := &tfvars.TerraformVariables{} parents.Get(clusterID, installConfig, terraformVariables) if fs := installConfig.Config.FeatureSet; strings.HasSuffix(string(fs), "NoUpgrade") { @@ -97,31 +95,14 @@ func (c *Cluster) Generate(parents asset.Parents) (err error) { return errors.New("cluster cannot be created with bootstrapInPlace set") } - // Check if we're using Cluster API. - if capiutils.IsEnabled(installConfig) { - // TODO(vincepri): The context should be passed down from the caller, - // although today the Asset interface doesn't allow it, refactor once it does. - ctx, cancel := context.WithCancel(signals.SetupSignalHandler()) - go func() { - <-ctx.Done() - cancel() - clusterapi.System().Teardown() - }() - - return c.provisionWithClusterAPI(ctx, parents, installConfig, clusterID) - } - - // Otherwise, use the normal path. - return c.provision(installConfig, clusterID, terraformVariables) -} - -func (c *Cluster) provision(installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID, terraformVariables *TerraformVariables) error { platform := installConfig.Config.Platform.Name() if azure := installConfig.Config.Platform.Azure; azure != nil && azure.CloudName == typesazure.StackCloud { platform = typesazure.StackTerraformName } + // TODO(padillon): determine whether CAPI handles tagging shared subnets, in which case we should be able + // to encapsulate these into the terraform package. logrus.Infof("Creating infrastructure resources...") switch platform { case typesaws.Name: @@ -138,16 +119,11 @@ func (c *Cluster) provision(installConfig *installconfig.InstallConfig, clusterI } } - tfvarsFiles := []*asset.File{} - for _, file := range terraformVariables.Files() { - tfvarsFiles = append(tfvarsFiles, file) - } - provider, err := infra.ProviderForPlatform(platform, installConfig.Config.EnabledFeatureGates()) if err != nil { return fmt.Errorf("error getting infrastructure provider: %w", err) } - files, err := provider.Provision(InstallDir, tfvarsFiles) + files, err := provider.Provision(InstallDir, parents) if files != nil { c.FileList = append(c.FileList, files...) // append state files even in case of failure } @@ -158,137 +134,6 @@ func (c *Cluster) provision(installConfig *installconfig.InstallConfig, clusterI return nil } -func (c *Cluster) provisionWithClusterAPI(ctx context.Context, parents asset.Parents, installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID) error { - capiManifests := &capimanifests.Cluster{} - clusterKubeconfigAsset := &kubeconfig.AdminClient{} - parents.Get( - capiManifests, - clusterKubeconfigAsset, - ) - - // Only need the objects--not the files. - manifests := []client.Object{} - for _, m := range capiManifests.RuntimeFiles() { - manifests = append(manifests, m.Object) - } - - // Run the CAPI system. - capiSystem := clusterapi.System() - if err := capiSystem.Run(ctx, installConfig); err != nil { - return fmt.Errorf("failed to run cluster api system: %w", err) - } - - // Grab the client. - cl := capiSystem.Client() - - // Create all the manifests and store them. - for _, m := range manifests { - m.SetNamespace(capiutils.Namespace) - if err := cl.Create(context.Background(), m); err != nil { - return fmt.Errorf("failed to create manifest: %w", err) - } - logrus.Infof("Created manifest %+T, namespace=%s name=%s", m, m.GetNamespace(), m.GetName()) - } - - // Pass cluster kubeconfig and store it in; this is usually the role of a bootstrap provider. - { - key := client.ObjectKey{ - Name: clusterID.InfraID, - Namespace: capiutils.Namespace, - } - cluster := &clusterv1.Cluster{} - if err := cl.Get(context.Background(), key, cluster); err != nil { - return err - } - // Create the secret. - clusterKubeconfig := clusterKubeconfigAsset.Files()[0].Data - secret := utilkubeconfig.GenerateSecret(cluster, clusterKubeconfig) - if err := cl.Create(context.Background(), secret); err != nil { - return err - } - } - - // Wait for the load balancer to be ready by checking the control plane endpoint - // on the cluster object. - var cluster *clusterv1.Cluster - { - if err := wait.ExponentialBackoff(wait.Backoff{ - Duration: time.Second * 10, - Factor: float64(1.5), - Steps: 32, - }, func() (bool, error) { - c := &clusterv1.Cluster{} - if err := cl.Get(context.Background(), client.ObjectKey{ - Name: clusterID.InfraID, - Namespace: capiutils.Namespace, - }, c); err != nil { - if apierrors.IsNotFound(err) { - return false, nil - } - return false, err - } - cluster = c - return cluster.Spec.ControlPlaneEndpoint.IsValid(), nil - }); err != nil { - return err - } - if cluster == nil { - return errors.New("error occurred during load balancer ready check") - } - if cluster.Spec.ControlPlaneEndpoint.Host == "" { - return errors.New("control plane endpoint is not set") - } - } - - // Run the post-provisioning steps for the platform we're on. - // TODO(vincepri): The following should probably be in a separate package with a clear - // interface and multiple hooks at different stages of the cluster lifecycle. - switch installConfig.Config.Platform.Name() { - case typesaws.Name: - ssn, err := installConfig.AWS.Session(context.TODO()) - if err != nil { - return fmt.Errorf("failed to create session: %w", err) - } - client := awsconfig.NewClient(ssn) - r53cfg := awsconfig.GetR53ClientCfg(ssn, "") - err = client.CreateOrUpdateRecord(installConfig.Config, cluster.Spec.ControlPlaneEndpoint.Host, r53cfg) - if err != nil { - return fmt.Errorf("failed to create route53 records: %w", err) - } - logrus.Infof("Created Route53 records to control plane load balancer.") - default: - } - - // For each manifest we created, retrieve it and store it in the asset. - for _, m := range manifests { - key := client.ObjectKey{ - Name: m.GetName(), - Namespace: m.GetNamespace(), - } - if err := cl.Get(context.Background(), key, m); err != nil { - return fmt.Errorf("failed to get manifest: %w", err) - } - - gvk, err := cl.GroupVersionKindFor(m) - if err != nil { - return fmt.Errorf("failed to get GVK for manifest: %w", err) - } - fileName := fmt.Sprintf("%s-%s-%s.yaml", gvk.Kind, m.GetNamespace(), m.GetName()) - objData, err := yaml.Marshal(m) - if err != nil { - errMsg := fmt.Sprintf("failed to create infrastructure manifest %s from InstallConfig", fileName) - return errors.Wrapf(err, errMsg) - } - c.FileList = append(c.FileList, &asset.File{ - Filename: fileName, - Data: objData, - }) - } - - logrus.Infof("Cluster API resources have been created. Waiting for cluster to become ready...") - return nil -} - // Files returns the FileList generated by the asset. func (c *Cluster) Files() []*asset.File { return c.FileList diff --git a/pkg/asset/cluster/metadata.go b/pkg/asset/cluster/metadata.go index a029e10228d..add8843083d 100644 --- a/pkg/asset/cluster/metadata.go +++ b/pkg/asset/cluster/metadata.go @@ -2,8 +2,6 @@ package cluster import ( "encoding/json" - "os" - "path/filepath" "github.com/pkg/errors" @@ -16,6 +14,7 @@ import ( "github.com/openshift/installer/pkg/asset/cluster/gcp" "github.com/openshift/installer/pkg/asset/cluster/ibmcloud" "github.com/openshift/installer/pkg/asset/cluster/libvirt" + clustermetadata "github.com/openshift/installer/pkg/asset/cluster/metadata" "github.com/openshift/installer/pkg/asset/cluster/nutanix" "github.com/openshift/installer/pkg/asset/cluster/openstack" "github.com/openshift/installer/pkg/asset/cluster/ovirt" @@ -41,10 +40,6 @@ import ( vspheretypes "github.com/openshift/installer/pkg/types/vsphere" ) -const ( - metadataFileName = "metadata.json" -) - // Metadata contains information needed to destroy clusters. type Metadata struct { File *asset.File @@ -123,7 +118,7 @@ func (m *Metadata) Generate(parents asset.Parents) (err error) { } m.File = &asset.File{ - Filename: metadataFileName, + Filename: clustermetadata.FileName, Data: data, } @@ -143,19 +138,3 @@ func (m *Metadata) Files() []*asset.File { func (m *Metadata) Load(f asset.FileFetcher) (found bool, err error) { return false, nil } - -// LoadMetadata loads the cluster metadata from an asset directory. -func LoadMetadata(dir string) (*types.ClusterMetadata, error) { - path := filepath.Join(dir, metadataFileName) - raw, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - var metadata *types.ClusterMetadata - if err = json.Unmarshal(raw, &metadata); err != nil { - return nil, errors.Wrapf(err, "failed to Unmarshal data from %q to types.ClusterMetadata", path) - } - - return metadata, err -} diff --git a/pkg/asset/cluster/metadata/metadata.go b/pkg/asset/cluster/metadata/metadata.go new file mode 100644 index 00000000000..9160036f906 --- /dev/null +++ b/pkg/asset/cluster/metadata/metadata.go @@ -0,0 +1,30 @@ +package metadata + +import ( + "encoding/json" + "os" + "path/filepath" + + "github.com/openshift/installer/pkg/types" + "github.com/pkg/errors" +) + +const ( + FileName = "metadata.json" +) + +// LoadMetadata loads the cluster metadata from an asset directory. +func Load(dir string) (*types.ClusterMetadata, error) { + path := filepath.Join(dir, FileName) + raw, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + var metadata *types.ClusterMetadata + if err = json.Unmarshal(raw, &metadata); err != nil { + return nil, errors.Wrapf(err, "failed to Unmarshal data from %q to types.ClusterMetadata", path) + } + + return metadata, err +} diff --git a/pkg/asset/cluster/tfvars.go b/pkg/asset/cluster/tfvars/tfvars.go similarity index 99% rename from pkg/asset/cluster/tfvars.go rename to pkg/asset/cluster/tfvars/tfvars.go index 35ead2ec569..0f278c397ee 100644 --- a/pkg/asset/cluster/tfvars.go +++ b/pkg/asset/cluster/tfvars/tfvars.go @@ -1,4 +1,4 @@ -package cluster +package tfvars import ( "context" @@ -1030,6 +1030,10 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error { if err != nil { return err } + ipAddresses, err := mastersAsset.IPAddresses() + if err != nil { + return err + } controlPlaneConfigs := make([]*machinev1beta1.VSphereMachineProviderSpec, len(controlPlanes)) for i, c := range controlPlanes { var clusterMo mo.ClusterComputeResource @@ -1093,6 +1097,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error { InfraID: clusterID.InfraID, InstallConfig: installConfig, ControlPlaneMachines: controlPlanes, + IPAddresses: ipAddresses, }, ) if err != nil { diff --git a/pkg/asset/cluster/vsphere/context.go b/pkg/asset/cluster/vsphere/context.go new file mode 100644 index 00000000000..09dd08d3ce8 --- /dev/null +++ b/pkg/asset/cluster/vsphere/context.go @@ -0,0 +1,208 @@ +package vsphere + +import ( + "context" + "fmt" + "path" + + "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/installconfig" + "github.com/openshift/installer/pkg/types/vsphere" + vsphereplatform "github.com/openshift/installer/pkg/types/vsphere" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vapi/tags" + "sigs.k8s.io/cluster-api-provider-vsphere/pkg/session" +) + +func (a *VCenterContexts) cacheNetworkNames(ctx context.Context, failureDomain vsphere.FailureDomain, session *session.Session, server string) error { + + finder := session.Finder + clusterPath := failureDomain.Topology.ComputeCluster + + clusterRef, err := finder.ClusterComputeResource(ctx, clusterPath) + if err != nil { + return fmt.Errorf("unable to retrieve compute cluster: %v", err) + } + + pools, err := finder.ResourcePoolList(ctx, clusterRef.InventoryPath) + if err != nil { + return fmt.Errorf("unable to retrieve resource pools relative to compute cluster: %v", err) + } + + for _, network := range failureDomain.Topology.Networks { + clusterMap, present := a.VCenters[server].ClusterNetworkMap[clusterPath] + if !present { + clusterMap = NetworkNameMap{ + Cluster: clusterPath, + NetworkNames: map[string]string{}, + ResourcePools: map[string]*object.ResourcePool{}, + } + for _, pool := range pools { + clusterMap.ResourcePools[path.Clean(pool.InventoryPath)] = pool + } + + a.VCenters[server].ClusterNetworkMap[clusterPath] = clusterMap + } + + networkName := path.Join(clusterRef.InventoryPath, network) + clusterMap.NetworkNames[network] = networkName + + } + + return nil +} + +func (a *VCenterContexts) createClusterTagID(ctx context.Context, session *session.Session, clusterId string, server string) error { + tagManager := session.TagManager + categories, err := tagManager.GetCategories(ctx) + if err != nil { + return fmt.Errorf("unable to get tag categories: %v", err) + } + + var clusterTagCategory *tags.Category + clusterTagCategoryName := fmt.Sprintf("openshift-%s", clusterId) + tagCategoryId := "" + + for _, category := range categories { + if category.Name == clusterTagCategoryName { + clusterTagCategory = &category + tagCategoryId = category.ID + break + } + } + + if clusterTagCategory == nil { + clusterTagCategory = &tags.Category{ + Name: clusterTagCategoryName, + Description: "Added by openshift-install do not remove", + Cardinality: "SINGLE", + AssociableTypes: []string{ + "urn:vim25:VirtualMachine", + "urn:vim25:ResourcePool", + "urn:vim25:Folder", + "urn:vim25:Datastore", + "urn:vim25:StoragePod", + }, + } + tagCategoryId, err = tagManager.CreateCategory(ctx, clusterTagCategory) + if err != nil { + return fmt.Errorf("unable to create tag category: %v", err) + } + } + + var categoryTag *tags.Tag + tagId := "" + + categoryTags, err := tagManager.GetTagsForCategory(ctx, tagCategoryId) + if err != nil { + return fmt.Errorf("unable to get tags for category: %v", err) + } + for _, tag := range categoryTags { + if tag.Name == clusterId { + categoryTag = &tag + tagId = tag.ID + break + } + } + + if categoryTag == nil { + categoryTag = &tags.Tag{ + Description: "Added by openshift-install do not remove", + Name: clusterId, + CategoryID: tagCategoryId, + } + tagId, err = tagManager.CreateTag(ctx, categoryTag) + if err != nil { + return fmt.Errorf("unable to create tag: %v", err) + } + } + + vCenterContext := a.VCenters[server] + vCenterContext.TagID = tagId + a.VCenters[server] = vCenterContext + + return nil +} + +type NetworkNameMap struct { + Cluster string + ResourcePools map[string]*object.ResourcePool + NetworkNames map[string]string +} + +// VCenterContext maintains context of known vCenters to be used in CAPI manifest reconciliation. +type VCenterContext struct { + VCenter string + TagID string + Datacenters []string + ClusterNetworkMap map[string]NetworkNameMap +} + +type VCenterContexts struct { + VCenters map[string]VCenterContext +} + +var ( + _ asset.Asset = (*VCenterContexts)(nil) +) + +func (a *VCenterContexts) Generate(parents asset.Parents) error { + ctx := context.TODO() + + a.VCenters = map[string]VCenterContext{} + + ic := &installconfig.InstallConfig{} + clusterID := &installconfig.ClusterID{} + parents.Get( + ic, + clusterID, + ) + + if ic.Config.Platform.Name() != vsphereplatform.Name { + return nil + } + + installConfig := ic.Config + + for _, vcenter := range installConfig.VSphere.VCenters { + server := vcenter.Server + params := session.NewParams().WithServer(server).WithUserInfo(vcenter.Username, vcenter.Password) + tempConnection, err := session.GetOrCreate(ctx, params) + if err != nil { + return fmt.Errorf("unable to create session: %v", err) + } + + defer tempConnection.CloseIdleConnections() + + a.VCenters[server] = VCenterContext{ + VCenter: server, + Datacenters: vcenter.Datacenters, + ClusterNetworkMap: map[string]NetworkNameMap{}, + } + + if err = a.createClusterTagID(ctx, tempConnection, clusterID.InfraID, server); err != nil { + return fmt.Errorf("unable to create cluster tag ID: %v", err) + } + + for _, failureDomain := range installConfig.VSphere.FailureDomains { + if failureDomain.Server != server { + continue + } + if err = a.cacheNetworkNames(ctx, failureDomain, tempConnection, server); err != nil { + return fmt.Errorf("unable to retrieve network names: %v", err) + } + } + } + return nil +} + +func (a *VCenterContexts) Dependencies() []asset.Asset { + return []asset.Asset{ + &installconfig.InstallConfig{}, + &installconfig.ClusterID{}, + } +} + +func (a *VCenterContexts) Name() string { + return "vCenter Context" +} diff --git a/pkg/asset/machines/clusterapi.go b/pkg/asset/machines/clusterapi.go index 453beae885b..c4f1283f2f3 100644 --- a/pkg/asset/machines/clusterapi.go +++ b/pkg/asset/machines/clusterapi.go @@ -15,13 +15,31 @@ import ( configv1 "github.com/openshift/api/config/v1" "github.com/openshift/installer/pkg/asset" + vcentercontexts "github.com/openshift/installer/pkg/asset/cluster/vsphere" "github.com/openshift/installer/pkg/asset/installconfig" "github.com/openshift/installer/pkg/asset/machines/aws" + vspheremachines "github.com/openshift/installer/pkg/asset/machines/vsphere" "github.com/openshift/installer/pkg/asset/manifests/capiutils" "github.com/openshift/installer/pkg/asset/rhcos" awsdefaults "github.com/openshift/installer/pkg/types/aws/defaults" ) +// GenerateClusterAPIVSphere generates manifests for target cluster. +func GenerateClusterAPIVSphere(ctx context.Context, installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID, rhcosImage *rhcos.Image, vcenterContexts *vcentercontexts.VCenterContexts) (*capiutils.GenerateMachinesOutput, error) { + var err error + result := &capiutils.GenerateMachinesOutput{} + ic := installConfig.Config + pool := *ic.ControlPlane + + vSphereMachines, err := vspheremachines.GenerateMachines(ctx, clusterID.InfraID, ic, &pool, string(*rhcosImage), "master", vcenterContexts) + if err != nil { + return nil, fmt.Errorf("failed to create control plane and bootstrap machine objects: %v", err) + } + result.Manifests = append(result.Manifests, vSphereMachines...) + + return result, nil +} + // GenerateClusterAPI generates manifests for target cluster. func GenerateClusterAPI(ctx context.Context, installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID, rhcosImage *rhcos.Image) (*capiutils.GenerateMachinesOutput, error) { var err error diff --git a/pkg/asset/machines/master.go b/pkg/asset/machines/master.go index 7bd63b713ce..019a3e7fd76 100644 --- a/pkg/asset/machines/master.go +++ b/pkg/asset/machines/master.go @@ -13,6 +13,7 @@ import ( corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/serializer" + ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" "sigs.k8s.io/yaml" configv1 "github.com/openshift/api/config/v1" @@ -72,6 +73,8 @@ type Master struct { MachineConfigFiles []*asset.File MachineFiles []*asset.File ControlPlaneMachineSet *asset.File + IPClaimFiles []*asset.File + IPAddrFiles []*asset.File // SecretFiles is used by the baremetal platform to register the // credential information for communicating with management @@ -111,8 +114,14 @@ const ( // user-data secret. masterUserDataFileName = "99_openshift-cluster-api_master-user-data-secret.yaml" - // masterUserDataFileName is the filename used for the control plane machine sets. + // controlPlaneMachineSetFileName is the filename used for the control plane machine sets. controlPlaneMachineSetFileName = "99_openshift-machine-api_master-control-plane-machine-set.yaml" + + // ipClaimFileName is the filename used for the ip claims list. + ipClaimFileName = "99_openshift-machine-api_claim-%s.yaml" + + // ipAddressFileName is the filename used for the ip addresses list. + ipAddressFileName = "99_openshift-machine-api_address-%s.yaml" ) var ( @@ -120,6 +129,8 @@ var ( networkConfigSecretFileNamePattern = fmt.Sprintf(networkConfigSecretFileName, "*") hostFileNamePattern = fmt.Sprintf(hostFileName, "*") masterMachineFileNamePattern = fmt.Sprintf(masterMachineFileName, "*") + masterIPClaimFileNamePattern = fmt.Sprintf(ipClaimFileName, "*master*") + masterIPAddressFileNamePattern = fmt.Sprintf(ipAddressFileName, "*master*") _ asset.WritableAsset = (*Master)(nil) ) @@ -160,6 +171,8 @@ func (m *Master) Generate(dependencies asset.Parents) error { pool := *ic.ControlPlane var err error machines := []machinev1beta1.Machine{} + var ipClaims []ipamv1.IPAddressClaim + var ipAddrs []ipamv1.IPAddress var controlPlaneMachineSet *machinev1.ControlPlaneMachineSet switch ic.Platform.Name() { case alibabacloudtypes.Name: @@ -473,7 +486,7 @@ func (m *Master) Generate(dependencies asset.Parents) error { pool.Platform.VSphere = &mpool templateName := clusterID.InfraID + "-rhcos" - machines, controlPlaneMachineSet, err = vsphere.Machines(clusterID.InfraID, ic, &pool, templateName, "master", masterUserDataSecretName) + machines, controlPlaneMachineSet, ipClaims, ipAddrs, err = vsphere.Machines(clusterID.InfraID, ic, &pool, templateName, "master", masterUserDataSecretName) if err != nil { return errors.Wrap(err, "failed to create master machine objects") } @@ -597,6 +610,33 @@ func (m *Master) Generate(dependencies asset.Parents) error { Data: data, } } + + m.IPClaimFiles = make([]*asset.File, len(ipClaims)) + for i, claim := range ipClaims { + data, err := yaml.Marshal(claim) + if err != nil { + return errors.Wrapf(err, "unable to marshal ip claim %v", claim.Name) + } + + m.IPClaimFiles[i] = &asset.File{ + Filename: filepath.Join(directory, fmt.Sprintf(ipClaimFileName, claim.Name)), + Data: data, + } + } + + m.IPAddrFiles = make([]*asset.File, len(ipAddrs)) + for i, address := range ipAddrs { + data, err := yaml.Marshal(address) + if err != nil { + return errors.Wrapf(err, "unable to marshal ip claim %v", address.Name) + } + + m.IPAddrFiles[i] = &asset.File{ + Filename: filepath.Join(directory, fmt.Sprintf(ipAddressFileName, address.Name)), + Data: data, + } + } + padFormat := fmt.Sprintf("%%0%dd", len(fmt.Sprintf("%d", len(machines)))) for i, machine := range machines { data, err := yaml.Marshal(machine) @@ -632,6 +672,8 @@ func (m *Master) Files() []*asset.File { if m.ControlPlaneMachineSet != nil { files = append(files, m.ControlPlaneMachineSet) } + files = append(files, m.IPClaimFiles...) + files = append(files, m.IPAddrFiles...) return files } @@ -688,6 +730,20 @@ func (m *Master) Load(f asset.FileFetcher) (found bool, err error) { } m.ControlPlaneMachineSet = file + fileList, err = f.FetchByPattern(filepath.Join(directory, masterIPClaimFileNamePattern)) + if err != nil { + return true, err + } + logrus.Infof("Loaded %v ip claims.", len(fileList)) + m.IPClaimFiles = fileList + + fileList, err = f.FetchByPattern(filepath.Join(directory, masterIPAddressFileNamePattern)) + if err != nil { + return true, err + } + logrus.Infof("Loaded %v ip addresses.", len(fileList)) + m.IPAddrFiles = fileList + return true, nil } @@ -770,6 +826,8 @@ func IsMachineManifest(file *asset.File) bool { {Pattern: hostFileNamePattern, Type: "host"}, {Pattern: masterMachineFileNamePattern, Type: "master machine"}, {Pattern: workerMachineSetFileNamePattern, Type: "worker machineset"}, + {Pattern: masterIPAddressFileNamePattern, Type: "master ip address"}, + {Pattern: masterIPClaimFileNamePattern, Type: "master ip address claim"}, } { if matched, err := filepath.Match(pattern.Pattern, filename); err != nil { panic(fmt.Sprintf("bad format for %s file name pattern", pattern.Type)) @@ -780,6 +838,23 @@ func IsMachineManifest(file *asset.File) bool { return false } +// IPAddresses returns IPAddress manifest structures. +func (m *Master) IPAddresses() ([]ipamv1.IPAddress, error) { + ipAddresses := []ipamv1.IPAddress{} + for i, file := range m.IPAddrFiles { + logrus.Debugf("Attempting to load address %v.", file.Filename) + address := &ipamv1.IPAddress{} + err := yaml.Unmarshal(file.Data, &address) + if err != nil { + return ipAddresses, errors.Wrapf(err, "unable to unmarshal ip address %d", i) + } + + ipAddresses = append(ipAddresses, *address) + } + + return ipAddresses, nil +} + func createSecretAssetFiles(resources []corev1.Secret, fileName string) ([]*asset.File, error) { var objects []interface{} diff --git a/pkg/asset/machines/vsphere/capimachines.go b/pkg/asset/machines/vsphere/capimachines.go new file mode 100644 index 00000000000..5951e776221 --- /dev/null +++ b/pkg/asset/machines/vsphere/capimachines.go @@ -0,0 +1,225 @@ +package vsphere + +import ( + "context" + "encoding/json" + "fmt" + "strings" + + v1 "k8s.io/api/core/v1" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/utils/pointer" + + machinev1 "github.com/openshift/api/machine/v1beta1" + vcentercontexts "github.com/openshift/installer/pkg/asset/cluster/vsphere" + "github.com/openshift/installer/pkg/utils" + + capv "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" + capi "sigs.k8s.io/cluster-api/api/v1beta1" + + "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/manifests/capiutils" + "github.com/openshift/installer/pkg/types" +) + +// ProviderSpecFromRawExtension unmarshals the JSON-encoded spec +func ProviderSpecFromRawExtension(rawExtension *runtime.RawExtension) (*machinev1.VSphereMachineProviderSpec, error) { + if rawExtension == nil { + return &machinev1.VSphereMachineProviderSpec{}, nil + } + + spec := new(machinev1.VSphereMachineProviderSpec) + if err := json.Unmarshal(rawExtension.Raw, &spec); err != nil { + return nil, fmt.Errorf("error unmarshalling providerSpec: %v", err) + } + + return spec, nil +} + +func getNetworkInventoryPath(vcenterContext vcentercontexts.VCenterContext, networkName string, providerSpec *machinev1.VSphereMachineProviderSpec) (string, error) { + // if networkName is a path, we'll assume that a full path was provided by the admin + if strings.Contains(networkName, "/") { + return networkName, nil + } + + // else, we'll dereference the network name to a full path using the resource pool + for _, clusterNetworkMap := range vcenterContext.ClusterNetworkMap { + if _, networkInContext := clusterNetworkMap.NetworkNames[networkName]; !networkInContext { + continue + } + for _, resourcePool := range clusterNetworkMap.ResourcePools { + if resourcePool.InventoryPath == providerSpec.Workspace.ResourcePool { + return clusterNetworkMap.NetworkNames[networkName], nil + } + } + } + return "", fmt.Errorf("unable to find network %s in resource pool %s", networkName, providerSpec.Workspace.ResourcePool) +} + +// Machines returns a list of capi machines. +func GenerateMachines(ctx context.Context, clusterID string, config *types.InstallConfig, pool *types.MachinePool, osImage string, role string, vcenterContexts *vcentercontexts.VCenterContexts) ([]*asset.RuntimeFile, error) { + machines, _, ipAddressClaims, ipAddresses, err := Machines(clusterID, config, pool, osImage, role, "") + if err != nil { + return nil, fmt.Errorf("unable to retrieve machines: %w", err) + } + + capvMachines := []*capv.VSphereMachine{} + + var result []*asset.RuntimeFile + + for _, machine := range machines { + providerSpec := machine.Spec.ProviderSpec.Value.Object.(*machinev1.VSphereMachineProviderSpec) + + vcenterContext := vcenterContexts.VCenters[providerSpec.Workspace.Server] + + resourcePool := providerSpec.Workspace.ResourcePool + + capvNetworkDevices := []capv.NetworkDeviceSpec{} + for _, networkDevice := range providerSpec.Network.Devices { + networkName, err := getNetworkInventoryPath(vcenterContext, networkDevice.NetworkName, providerSpec) + if err != nil { + return nil, fmt.Errorf("unable to get network inventory path: %w", err) + } + capvNetworkDevices = append(capvNetworkDevices, capv.NetworkDeviceSpec{ + NetworkName: networkName, + DHCP4: true, + }) + } + + customVMXKeys := map[string]string{ + "guestinfo.hostname": machine.Name, + } + + if ipAddressClaims != nil { + kargs, err := utils.ConstructNetworkKargsFromMachine(ipAddressClaims, ipAddresses, &machine) + if err != nil { + return nil, fmt.Errorf("unable to construct kargs from machine config: %w", err) + } + customVMXKeys["guestinfo.afterburn.initrd.network-kargs"] = kargs + } + + vsphereMachine := &capv.VSphereMachine{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "VSphereMachine", + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: capiutils.Namespace, + Name: machine.Name, + Labels: map[string]string{ + "cluster.x-k8s.io/control-plane": "", + }, + }, + Spec: capv.VSphereMachineSpec{ + VirtualMachineCloneSpec: capv.VirtualMachineCloneSpec{ + CustomVMXKeys: customVMXKeys, + TagIDs: []string{vcenterContext.TagID}, + Network: capv.NetworkSpec{ + Devices: capvNetworkDevices, + }, + Folder: providerSpec.Workspace.Folder, + Template: providerSpec.Template, + Datacenter: providerSpec.Workspace.Datacenter, + Server: providerSpec.Workspace.Server, + NumCPUs: providerSpec.NumCPUs, + MemoryMiB: providerSpec.MemoryMiB, + DiskGiB: providerSpec.DiskGiB, + Datastore: providerSpec.Workspace.Datastore, + ResourcePool: resourcePool, + }, + }, + } + capvMachines = append(capvMachines, vsphereMachine) + + result = append(result, &asset.RuntimeFile{ + File: asset.File{Filename: fmt.Sprintf("10_inframachine_%s.yaml", vsphereMachine.Name)}, + Object: vsphereMachine, + }) + + machine := &capi.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: capiutils.Namespace, + Name: vsphereMachine.Name, + Labels: map[string]string{ + "cluster.x-k8s.io/control-plane": "", + }, + }, + Spec: capi.MachineSpec{ + ClusterName: clusterID, + Bootstrap: capi.Bootstrap{ + DataSecretName: pointer.String(fmt.Sprintf("%s-%s", clusterID, role)), + }, + InfrastructureRef: v1.ObjectReference{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "VSphereMachine", + Name: vsphereMachine.Name, + }, + }, + } + + result = append(result, &asset.RuntimeFile{ + File: asset.File{Filename: fmt.Sprintf("10_machine_%s.yaml", machine.Name)}, + Object: machine, + }) + } + + // as part of provisioning conrtol plane nodes, we need to create a bootstrap node as well + if role == "master" { + customVMXKeys := map[string]string{} + + if ipAddressClaims != nil { + kargs, err := utils.ConstructKargsForBootstrap(config) + if err != nil { + return nil, fmt.Errorf("unable to construct kargs from machine config: %w", err) + } + customVMXKeys["guestinfo.afterburn.initrd.network-kargs"] = kargs + } + + bootstrapSpec := capvMachines[0].Spec + bootstrapSpec.CustomVMXKeys = customVMXKeys + bootstrapVSphereMachine := &capv.VSphereMachine{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-bootstrap", clusterID), + Labels: map[string]string{ + "cluster.x-k8s.io/control-plane": "", + }, + }, + Spec: bootstrapSpec, + } + + result = append(result, &asset.RuntimeFile{ + File: asset.File{Filename: fmt.Sprintf("10_inframachine_%s.yaml", bootstrapVSphereMachine.Name)}, + Object: bootstrapVSphereMachine, + }) + + bootstrapMachine := &capi.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Name: bootstrapVSphereMachine.Name, + Labels: map[string]string{ + "cluster.x-k8s.io/control-plane": "", + }, + }, + Spec: capi.MachineSpec{ + ClusterName: clusterID, + Bootstrap: capi.Bootstrap{ + DataSecretName: pointer.String(fmt.Sprintf("%s-bootstrap", clusterID)), + }, + InfrastructureRef: v1.ObjectReference{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "VSphereMachine", + Name: bootstrapVSphereMachine.Name, + }, + }, + } + + result = append(result, &asset.RuntimeFile{ + File: asset.File{Filename: fmt.Sprintf("10_machine_%s.yaml", bootstrapVSphereMachine.Name)}, + Object: bootstrapMachine, + }) + + } + + return result, nil +} diff --git a/pkg/asset/machines/vsphere/machines.go b/pkg/asset/machines/vsphere/machines.go index e968f6329f9..e0a4ad9f9e3 100644 --- a/pkg/asset/machines/vsphere/machines.go +++ b/pkg/asset/machines/vsphere/machines.go @@ -3,12 +3,16 @@ package vsphere import ( "fmt" + "path" + "strconv" + "strings" "github.com/pkg/errors" "github.com/sirupsen/logrus" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" v1 "github.com/openshift/api/config/v1" machinev1 "github.com/openshift/api/machine/v1" @@ -18,16 +22,18 @@ import ( ) // Machines returns a list of machines for a machinepool. -func Machines(clusterID string, config *types.InstallConfig, pool *types.MachinePool, osImage, role, userDataSecret string) ([]machineapi.Machine, *machinev1.ControlPlaneMachineSet, error) { +func Machines(clusterID string, config *types.InstallConfig, pool *types.MachinePool, osImage, role, userDataSecret string) ([]machineapi.Machine, *machinev1.ControlPlaneMachineSet, []ipamv1.IPAddressClaim, []ipamv1.IPAddress, error) { if configPlatform := config.Platform.Name(); configPlatform != vsphere.Name { - return nil, nil, fmt.Errorf("non vsphere configuration: %q", configPlatform) + return nil, nil, nil, nil, fmt.Errorf("non vsphere configuration: %q", configPlatform) } if poolPlatform := pool.Platform.Name(); poolPlatform != vsphere.Name { - return nil, nil, fmt.Errorf("non-VSphere machine-pool: %q", poolPlatform) + return nil, nil, nil, nil, fmt.Errorf("non-VSphere machine-pool: %q", poolPlatform) } var failureDomain vsphere.FailureDomain var machines []machineapi.Machine + var ipClaims []ipamv1.IPAddressClaim + var ipAddrs []ipamv1.IPAddress platform := config.Platform.VSphere mpool := pool.Platform.VSphere replicas := int32(1) @@ -36,7 +42,7 @@ func Machines(clusterID string, config *types.InstallConfig, pool *types.Machine zones, err := getDefinedZonesFromTopology(platform) if err != nil { - return machines, nil, err + return machines, nil, ipClaims, ipAddrs, err } if pool.Replicas != nil { @@ -72,7 +78,7 @@ func Machines(clusterID string, config *types.InstallConfig, pool *types.Machine logrus.Debugf("Desired zone: %v", desiredZone) if _, exists := zones[desiredZone]; !exists { - return nil, nil, errors.Errorf("zone [%s] specified by machinepool is not defined", desiredZone) + return nil, nil, nil, nil, errors.Errorf("zone [%s] specified by machinepool is not defined", desiredZone) } failureDomain = zones[desiredZone] @@ -94,16 +100,13 @@ func Machines(clusterID string, config *types.InstallConfig, pool *types.Machine vcenter, err := getVCenterFromServerName(failureDomain.Server, platform) if err != nil { - return nil, nil, errors.Wrap(err, "unable to find vCenter in failure domains") + return nil, nil, nil, nil, errors.Wrap(err, "unable to find vCenter in failure domains") } provider, err := provider(clusterID, vcenter, failureDomain, mpool, osImageForZone, userDataSecret) if err != nil { - return nil, nil, errors.Wrap(err, "failed to create provider") + return nil, nil, nil, nil, errors.Wrap(err, "failed to create provider") } - // Apply static IP if configured - applyNetworkConfig(host, provider) - machine := machineapi.Machine{ TypeMeta: metav1.TypeMeta{ APIVersion: "machine.openshift.io/v1beta1", @@ -121,6 +124,15 @@ func Machines(clusterID string, config *types.InstallConfig, pool *types.Machine // we don't need to set Versions, because we control those via operators. }, } + // Apply static IP if configured + claim, address, err := applyNetworkConfig(host, provider, machine) + if err != nil { + return nil, nil, nil, nil, err + } else if claim != nil && address != nil { + ipClaims = append(ipClaims, claim...) + ipAddrs = append(ipAddrs, address...) + } + machines = append(machines, machine) vsphereMachineProvider = provider.DeepCopy() @@ -189,21 +201,108 @@ func Machines(clusterID string, config *types.InstallConfig, pool *types.Machine }, } - return machines, controlPlaneMachineSet, nil + return machines, controlPlaneMachineSet, ipClaims, ipAddrs, nil } // applyNetworkConfig this function will apply the static ip configuration to the networkDevice // field in the provider spec. The function will use the desired zone to determine which config // to apply and then remove that host config from the hosts array. -func applyNetworkConfig(host *vsphere.Host, provider *machineapi.VSphereMachineProviderSpec) { +func applyNetworkConfig(host *vsphere.Host, provider *machineapi.VSphereMachineProviderSpec, machine machineapi.Machine) ([]ipamv1.IPAddressClaim, []ipamv1.IPAddress, error) { + var ipClaims []ipamv1.IPAddressClaim + var ipAddrs []ipamv1.IPAddress if host != nil { networkDevice := host.NetworkDevice if networkDevice != nil { - provider.Network.Devices[0].IPAddrs = networkDevice.IPAddrs - provider.Network.Devices[0].Nameservers = networkDevice.Nameservers - provider.Network.Devices[0].Gateway = networkDevice.Gateway + for idx, address := range networkDevice.IPAddrs { + provider.Network.Devices[0].Nameservers = networkDevice.Nameservers + provider.Network.Devices[0].AddressesFromPools = append(provider.Network.Devices[0].AddressesFromPools, machineapi.AddressesFromPool{ + Group: "installer.openshift.io", + Name: fmt.Sprintf("default-%d", idx), + Resource: "IPPool", + }, + ) + + // Generate the capi networking objects + slashIndex := strings.Index(address, "/") + ipAddress := address[0:slashIndex] + prefix, err := strconv.Atoi(address[slashIndex+1:]) + if err != nil { + return nil, nil, errors.Wrap(err, "unable to determine address prefix") + } + ipClaim, ipAddr := generateCapiNetwork(&machine, ipAddress, networkDevice.Gateway, prefix, 0, idx) + ipClaims = append(ipClaims, *ipClaim) + ipAddrs = append(ipAddrs, *ipAddr) + } } } + + return ipClaims, ipAddrs, nil +} + +// generateCapiNetwork this function will create IPAddressClaim and IPAddress for the specified information. +func generateCapiNetwork(machine *machineapi.Machine, ipAddress, gateway string, prefix, deviceIndex, ipIndex int) (*ipamv1.IPAddressClaim, *ipamv1.IPAddress) { + machineName := machine.Name + + // Generate PoolRef + apigroup := "installer.openshift.io" + poolRef := corev1.TypedLocalObjectReference{ + APIGroup: &apigroup, + Kind: "IPPool", + Name: fmt.Sprintf("default-%d", ipIndex), + } + + gv := machinev1.SchemeGroupVersion + machineRef := metav1.NewControllerRef(machine, gv.WithKind("Machine")) + + // Generate IPAddressClaim + ipclaim := &ipamv1.IPAddressClaim{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "ipam.cluster.x-k8s.io/v1alpha1", + Kind: "IPAddressClaim", + }, + ObjectMeta: metav1.ObjectMeta{ + Finalizers: []string{ + machineapi.IPClaimProtectionFinalizer, + }, + OwnerReferences: []metav1.OwnerReference{ + *machineRef, + }, + Name: fmt.Sprintf("%s-claim-%d-%d", machineName, deviceIndex, ipIndex), + Namespace: "openshift-machine-api", + }, + Spec: ipamv1.IPAddressClaimSpec{ + PoolRef: poolRef, + }, + } + + // Populate IPAddress info + ipaddr := &ipamv1.IPAddress{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "ipam.cluster.x-k8s.io/v1alpha1", + Kind: "IPAddress", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-claim-%d-%d", machineName, deviceIndex, ipIndex), + Namespace: "openshift-machine-api", + }, + Spec: ipamv1.IPAddressSpec{ + Address: ipAddress, + ClaimRef: corev1.LocalObjectReference{ + Name: ipclaim.Name, + }, + Gateway: gateway, + PoolRef: poolRef, + Prefix: prefix, + }, + } + + ipclaim.Status = ipamv1.IPAddressClaimStatus{ + AddressRef: corev1.LocalObjectReference{ + Name: ipaddr.Name, + }, + } + + return ipclaim, ipaddr } func provider(clusterID string, vcenter *vsphere.VCenter, failureDomain vsphere.FailureDomain, mpool *vsphere.MachinePool, osImage string, userDataSecret string) (*machineapi.VSphereMachineProviderSpec, error) { @@ -223,6 +322,8 @@ func provider(clusterID string, vcenter *vsphere.VCenter, failureDomain vsphere. resourcePool = failureDomain.Topology.ResourcePool } + resourcePool = path.Clean(resourcePool) + for i, network := range failureDomain.Topology.Networks { networkDeviceSpec[i] = machineapi.NetworkDeviceSpec{NetworkName: network} } diff --git a/pkg/asset/machines/vsphere/machines_test.go b/pkg/asset/machines/vsphere/machines_test.go index e9c279fb91b..136c9cc9b46 100644 --- a/pkg/asset/machines/vsphere/machines_test.go +++ b/pkg/asset/machines/vsphere/machines_test.go @@ -378,7 +378,7 @@ func TestConfigMasters(t *testing.T) { for _, tc := range testCases { t.Run(tc.testCase, func(t *testing.T) { - machines, _, err := Machines(clusterID, tc.installConfig, tc.machinePool, "", "", "") + machines, _, _, _, err := Machines(clusterID, tc.installConfig, tc.machinePool, "", "", "") assertOnUnexpectedErrorState(t, tc.expectedError, err) if len(tc.workspaces) > 0 { @@ -449,7 +449,7 @@ func TestHostsToMachines(t *testing.T) { for _, tc := range testCases { t.Run(tc.testCase, func(t *testing.T) { - machines, _, err := Machines(clusterID, tc.installConfig, tc.machinePool, "", tc.role, "") + machines, _, claims, ips, err := Machines(clusterID, tc.installConfig, tc.machinePool, "", tc.role, "") assertOnUnexpectedErrorState(t, tc.expectedError, err) // Check machine counts @@ -457,8 +457,18 @@ func TestHostsToMachines(t *testing.T) { t.Errorf("machine count (%v) did not match expected (%v).", len(machines), tc.machineCount) } + // Check Claim counts + if len(claims) != tc.machineCount { + t.Errorf("ip address claim count (%v) did not match expected (%v).", len(claims), tc.machineCount) + } + + // Check ip address counts + if len(ips) != tc.machineCount { + t.Errorf("ip address count (%v) did not match expected (%v).", len(ips), tc.machineCount) + } + // Verify static IP was set on all machines - for _, machine := range machines { + for index, machine := range machines { provider, success := machine.Spec.ProviderSpec.Value.Object.(*machineapi.VSphereMachineProviderSpec) if !success { t.Errorf("Unable to convert vshere machine provider spec.") @@ -466,8 +476,8 @@ func TestHostsToMachines(t *testing.T) { if len(provider.Network.Devices) == 1 { // Check IP - if provider.Network.Devices[0].IPAddrs == nil || provider.Network.Devices[0].IPAddrs[0] == "" { - t.Errorf("Static ip is not set: %v", machine) + if provider.Network.Devices[0].AddressesFromPools == nil { + t.Errorf("AddressesFromPools is not set: %v", machine) } // Check nameserver @@ -475,7 +485,7 @@ func TestHostsToMachines(t *testing.T) { t.Errorf("Nameserver is not set: %v", machine) } - gateway := provider.Network.Devices[0].Gateway + gateway := ips[index].Spec.Gateway ip, err := netip.ParseAddr(gateway) if err != nil { t.Error(err) diff --git a/pkg/asset/machines/worker.go b/pkg/asset/machines/worker.go index fcdb7b76441..3fa4c49b6ce 100644 --- a/pkg/asset/machines/worker.go +++ b/pkg/asset/machines/worker.go @@ -13,6 +13,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/util/intstr" "k8s.io/utils/pointer" + ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" "sigs.k8s.io/yaml" configv1 "github.com/openshift/api/config/v1" @@ -92,6 +93,8 @@ const ( var ( workerMachineSetFileNamePattern = fmt.Sprintf(workerMachineSetFileName, "*") workerMachineFileNamePattern = fmt.Sprintf(workerMachineFileName, "*") + workerIPClaimFileNamePattern = fmt.Sprintf(ipClaimFileName, "*worker*") + workerIPAddressFileNamePattern = fmt.Sprintf(ipAddressFileName, "*worker*") _ asset.WritableAsset = (*Worker)(nil) ) @@ -226,6 +229,8 @@ type Worker struct { MachineConfigFiles []*asset.File MachineSetFiles []*asset.File MachineFiles []*asset.File + IPClaimFiles []*asset.File + IPAddrFiles []*asset.File } // Name returns a human friendly name for the Worker Asset. @@ -264,6 +269,8 @@ func (w *Worker) Generate(dependencies asset.Parents) error { machines := []machinev1beta1.Machine{} machineConfigs := []*mcfgv1.MachineConfig{} machineSets := []runtime.Object{} + var ipClaims []ipamv1.IPAddressClaim + var ipAddrs []ipamv1.IPAddress var err error ic := installConfig.Config for _, pool := range ic.Compute { @@ -635,7 +642,7 @@ func (w *Worker) Generate(dependencies asset.Parents) error { logrus.Debug("Generating worker machines with static IPs.") templateName := clusterID.InfraID + "-rhcos" - machines, _, err = vsphere.Machines(clusterID.InfraID, ic, &pool, templateName, "worker", workerUserDataSecretName) + machines, _, ipClaims, ipAddrs, err = vsphere.Machines(clusterID.InfraID, ic, &pool, templateName, "worker", workerUserDataSecretName) if err != nil { return errors.Wrap(err, "failed to create worker machine objects") } @@ -724,6 +731,32 @@ func (w *Worker) Generate(dependencies asset.Parents) error { } } + w.IPClaimFiles = make([]*asset.File, len(ipClaims)) + for i, claim := range ipClaims { + data, err := yaml.Marshal(claim) + if err != nil { + return errors.Wrapf(err, "marshal ip claim %v", claim.Name) + } + + w.IPClaimFiles[i] = &asset.File{ + Filename: filepath.Join(directory, fmt.Sprintf(ipClaimFileName, claim.Name)), + Data: data, + } + } + + w.IPAddrFiles = make([]*asset.File, len(ipAddrs)) + for i, address := range ipAddrs { + data, err := yaml.Marshal(address) + if err != nil { + return errors.Wrapf(err, "marshal ip claim %v", address.Name) + } + + w.IPAddrFiles[i] = &asset.File{ + Filename: filepath.Join(directory, fmt.Sprintf(ipAddressFileName, address.Name)), + Data: data, + } + } + w.MachineFiles = make([]*asset.File, len(machines)) for i, machineDef := range machines { data, err := yaml.Marshal(machineDef) @@ -749,6 +782,8 @@ func (w *Worker) Files() []*asset.File { files = append(files, w.MachineConfigFiles...) files = append(files, w.MachineSetFiles...) files = append(files, w.MachineFiles...) + files = append(files, w.IPClaimFiles...) + files = append(files, w.IPAddrFiles...) return files } @@ -781,6 +816,18 @@ func (w *Worker) Load(f asset.FileFetcher) (found bool, err error) { } w.MachineFiles = fileList + fileList, err = f.FetchByPattern(filepath.Join(directory, workerIPClaimFileNamePattern)) + if err != nil { + return true, err + } + w.IPClaimFiles = fileList + + fileList, err = f.FetchByPattern(filepath.Join(directory, workerIPAddressFileNamePattern)) + if err != nil { + return true, err + } + w.IPAddrFiles = fileList + return true, nil } diff --git a/pkg/asset/manifests/clusterapi/cluster.go b/pkg/asset/manifests/clusterapi/cluster.go index ebcd119f835..0d54a714eda 100644 --- a/pkg/asset/manifests/clusterapi/cluster.go +++ b/pkg/asset/manifests/clusterapi/cluster.go @@ -15,17 +15,18 @@ import ( "sigs.k8s.io/yaml" "github.com/openshift/installer/pkg/asset" - "github.com/openshift/installer/pkg/asset/ignition/bootstrap" - "github.com/openshift/installer/pkg/asset/ignition/machine" + vcentercontexts "github.com/openshift/installer/pkg/asset/cluster/vsphere" "github.com/openshift/installer/pkg/asset/installconfig" "github.com/openshift/installer/pkg/asset/machines" "github.com/openshift/installer/pkg/asset/manifests" "github.com/openshift/installer/pkg/asset/manifests/aws" "github.com/openshift/installer/pkg/asset/manifests/azure" "github.com/openshift/installer/pkg/asset/manifests/capiutils" + "github.com/openshift/installer/pkg/asset/manifests/vsphere" "github.com/openshift/installer/pkg/asset/openshiftinstall" "github.com/openshift/installer/pkg/asset/rhcos" "github.com/openshift/installer/pkg/clusterapi" + vsphereplatform "github.com/openshift/installer/pkg/types/vsphere" ) const ( @@ -53,22 +54,21 @@ func (c *Cluster) Dependencies() []asset.Asset { &installconfig.ClusterID{}, &openshiftinstall.Config{}, &manifests.FeatureGate{}, - &bootstrap.Bootstrap{}, - &machine.Master{}, + &vcentercontexts.VCenterContexts{}, new(rhcos.Image), } } // Generate generates the respective operator config.yml files. func (c *Cluster) Generate(dependencies asset.Parents) error { + var err error installConfig := &installconfig.InstallConfig{} clusterID := &installconfig.ClusterID{} openshiftInstall := &openshiftinstall.Config{} featureGate := &manifests.FeatureGate{} - bootstrapIgnAsset := &bootstrap.Bootstrap{} - masterIgnAsset := &machine.Master{} + vcenterContexts := &vcentercontexts.VCenterContexts{} rhcosImage := new(rhcos.Image) - dependencies.Get(installConfig, clusterID, openshiftInstall, bootstrapIgnAsset, masterIgnAsset, featureGate, rhcosImage) + dependencies.Get(installConfig, clusterID, openshiftInstall, featureGate, rhcosImage, vcenterContexts) // If the feature gate is not enabled, do not generate any manifests. if !capiutils.IsEnabled(installConfig) { @@ -97,51 +97,9 @@ func (c *Cluster) Generate(dependencies asset.Parents) error { } c.FileList = append(c.FileList, &asset.RuntimeFile{Object: cluster, File: asset.File{Filename: "01_capi-cluster.yaml"}}) - // Gather the ignition files, and store them in a secret. - { - masterIgn := string(masterIgnAsset.Files()[0].Data) - bootstrapIgn, err := injectInstallInfo(bootstrapIgnAsset.Files()[0].Data) - if err != nil { - return errors.Wrap(err, "unable to inject installation info") - } - c.FileList = append(c.FileList, - &asset.RuntimeFile{ - File: asset.File{Filename: "01_ignition-secret-master.yaml"}, - Object: &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s", clusterID.InfraID, "master"), - Namespace: capiutils.Namespace, - Labels: map[string]string{ - "cluster.x-k8s.io/cluster-name": clusterID.InfraID, - }, - }, - Data: map[string][]byte{ - "format": []byte("ignition"), - "value": []byte(masterIgn), - }, - }, - }, - &asset.RuntimeFile{ - File: asset.File{Filename: "01_ignition-secret-bootstrap.yaml"}, - Object: &corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-%s", clusterID.InfraID, "bootstrap"), - Namespace: capiutils.Namespace, - Labels: map[string]string{ - "cluster.x-k8s.io/cluster-name": clusterID.InfraID, - }, - }, - Data: map[string][]byte{ - "format": []byte("ignition"), - "value": []byte(bootstrapIgn), - }, - }, - }, - ) - } - var out *capiutils.GenerateClusterAssetsOutput - switch platform := installConfig.Config.Platform.Name(); platform { + platform := installConfig.Config.Platform.Name() + switch platform { case "aws": // Move this somewhere else. // if err := aws.PutIAMRoles(clusterID.InfraID, installConfig); err != nil { @@ -156,7 +114,13 @@ func (c *Cluster) Generate(dependencies asset.Parents) error { var err error out, err = azure.GenerateClusterAssets(installConfig, clusterID) if err != nil { - return errors.Wrap(err, "failed to generate AWS manifests") + return errors.Wrap(err, "failed to generate Azure manifests") + } + case vsphereplatform.Name: + var err error + out, err = vsphere.GenerateClusterAssets(installConfig, clusterID) + if err != nil { + return errors.Wrap(err, "failed to generate vSphere manifests") } default: return fmt.Errorf("unsupported platform %q", platform) @@ -171,10 +135,18 @@ func (c *Cluster) Generate(dependencies asset.Parents) error { // Append the infrastructure manifests. c.FileList = append(c.FileList, out.Manifests...) - // Generate the machines for the cluster, and append them to the list of manifests. - mc, err := machines.GenerateClusterAPI(context.TODO(), installConfig, clusterID, rhcosImage) + mc := &capiutils.GenerateMachinesOutput{} + + switch platform { + case vsphereplatform.Name: + mc, err = machines.GenerateClusterAPIVSphere(context.TODO(), installConfig, clusterID, rhcosImage, vcenterContexts) + default: + mc, err = machines.GenerateClusterAPI(context.TODO(), installConfig, clusterID, rhcosImage) + } + if err != nil { return errors.Wrap(err, "failed to generate machines") + } c.FileList = append(c.FileList, mc.Manifests...) diff --git a/pkg/asset/manifests/vsphere/cluster.go b/pkg/asset/manifests/vsphere/cluster.go new file mode 100644 index 00000000000..2b3d8eb1e62 --- /dev/null +++ b/pkg/asset/manifests/vsphere/cluster.go @@ -0,0 +1,68 @@ +package vsphere + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + capv "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" + + "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/installconfig" + "github.com/openshift/installer/pkg/asset/manifests/capiutils" +) + +// GenerateClusterAssets generates the manifests for the cluster-api. +func GenerateClusterAssets(installConfig *installconfig.InstallConfig, clusterID *installconfig.ClusterID) (*capiutils.GenerateClusterAssetsOutput, error) { + manifests := []*asset.RuntimeFile{} + + vcenter := installConfig.Config.VSphere.VCenters[0] + + vsphereCreds := &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: "vsphere-creds", + Namespace: capiutils.Namespace, + }, + Data: make(map[string][]byte), + } + + vsphereCreds.Data["username"] = []byte(vcenter.Username) + vsphereCreds.Data["password"] = []byte(vcenter.Password) + + manifests = append(manifests, &asset.RuntimeFile{ + Object: vsphereCreds, + File: asset.File{Filename: "01_vsphere-creds.yaml"}, + }) + + vsphereCluster := &capv.VSphereCluster{ + ObjectMeta: metav1.ObjectMeta{ + Name: clusterID.InfraID, + Namespace: capiutils.Namespace, + }, + Spec: capv.VSphereClusterSpec{ + Server: fmt.Sprintf("https://%s", vcenter.Server), + ControlPlaneEndpoint: capv.APIEndpoint{ + Host: fmt.Sprintf("api.%s.%s", installConfig.Config.ObjectMeta.Name, installConfig.Config.BaseDomain), + Port: 6443, + }, + IdentityRef: &capv.VSphereIdentityReference{ + Kind: capv.SecretKind, + Name: "vsphere-creds", + }, + }, + } + manifests = append(manifests, &asset.RuntimeFile{ + Object: vsphereCluster, + File: asset.File{Filename: "01_vsphere-cluster.yaml"}, + }) + + return &capiutils.GenerateClusterAssetsOutput{ + Manifests: manifests, + InfrastructureRef: &corev1.ObjectReference{ + APIVersion: "infrastructure.cluster.x-k8s.io/v1beta1", + Kind: "VSphereCluster", + Name: clusterID.InfraID, + Namespace: capiutils.Namespace, + }, + }, nil +} diff --git a/pkg/asset/targets/targets.go b/pkg/asset/targets/targets.go index a4e9e64c588..960d58eb1e6 100644 --- a/pkg/asset/targets/targets.go +++ b/pkg/asset/targets/targets.go @@ -3,6 +3,7 @@ package targets import ( "github.com/openshift/installer/pkg/asset" "github.com/openshift/installer/pkg/asset/cluster" + "github.com/openshift/installer/pkg/asset/cluster/tfvars" "github.com/openshift/installer/pkg/asset/ignition/bootstrap" "github.com/openshift/installer/pkg/asset/ignition/machine" "github.com/openshift/installer/pkg/asset/installconfig" @@ -66,7 +67,7 @@ var ( &cluster.Metadata{}, &machine.MasterIgnitionCustomizations{}, &machine.WorkerIgnitionCustomizations{}, - &cluster.TerraformVariables{}, + &tfvars.TerraformVariables{}, &kubeconfig.AdminClient{}, &password.KubeadminPassword{}, &tls.JournalCertKey{}, diff --git a/pkg/clusterapi/localcontrolplane.go b/pkg/clusterapi/localcontrolplane.go index f069567b716..35b1b55b01e 100644 --- a/pkg/clusterapi/localcontrolplane.go +++ b/pkg/clusterapi/localcontrolplane.go @@ -17,6 +17,7 @@ import ( capav1beta1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta1" capav1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2" capzv1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" + capvv1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" clusterv1alpha3 "sigs.k8s.io/cluster-api/api/v1alpha3" //nolint:staticcheck clusterv1alpha4 "sigs.k8s.io/cluster-api/api/v1alpha4" //nolint:staticcheck clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" @@ -39,6 +40,7 @@ func init() { utilruntime.Must(capav1beta1.AddToScheme(Scheme)) utilruntime.Must(capav1.AddToScheme(Scheme)) utilruntime.Must(capzv1.AddToScheme(Scheme)) + utilruntime.Must(capvv1.AddToScheme(Scheme)) } // localControlPlane creates a local capi control plane diff --git a/pkg/clusterapi/system.go b/pkg/clusterapi/system.go index a1b739e31fc..031a92933d0 100644 --- a/pkg/clusterapi/system.go +++ b/pkg/clusterapi/system.go @@ -178,7 +178,27 @@ func (c *system) Run(ctx context.Context, installConfig *installconfig.InstallCo case nutanix.Name: // TODO case vsphere.Name: - // TODO + vcenters := installConfig.Config.VSphere.VCenters + + controllers = append(controllers, + c.getInfrastructureController( + &VSphere, + []string{ + "-v=2", + "--metrics-bind-addr=0", + "--health-addr={{suggestHealthHostPort}}", + "--webhook-port={{.WebhookPort}}", + "--webhook-cert-dir={{.WebhookCertDir}}", + "--leader-elect=false", + }, + map[string]string{ + "VSPHERE_USERNAME": vcenters[0].Username, + "VSPHERE_PASSWORD": vcenters[0].Password, + "EXP_KUBEADM_BOOTSTRAP_FORMAT_IGNITION": "true", + "EXP_CLUSTER_RESOURCE_SET": "true", + }, + ), + ) default: return fmt.Errorf("unsupported platform %q", platform) } diff --git a/pkg/destroy/bootstrap/bootstrap.go b/pkg/destroy/bootstrap/bootstrap.go index ef94938f2f0..841d7d10d6d 100644 --- a/pkg/destroy/bootstrap/bootstrap.go +++ b/pkg/destroy/bootstrap/bootstrap.go @@ -14,7 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" configv1 "github.com/openshift/api/config/v1" - "github.com/openshift/installer/pkg/asset/cluster" + "github.com/openshift/installer/pkg/asset/cluster/metadata" openstackasset "github.com/openshift/installer/pkg/asset/cluster/openstack" "github.com/openshift/installer/pkg/asset/manifests/capiutils" "github.com/openshift/installer/pkg/clusterapi" @@ -30,7 +30,7 @@ import ( // Destroy uses Terraform to remove bootstrap resources. func Destroy(ctx context.Context, dir string) (err error) { - metadata, err := cluster.LoadMetadata(dir) + metadata, err := metadata.Load(dir) if err != nil { return err } diff --git a/pkg/destroy/destroyer.go b/pkg/destroy/destroyer.go index 88b7e60f6c9..9086f05c7cb 100644 --- a/pkg/destroy/destroyer.go +++ b/pkg/destroy/destroyer.go @@ -4,13 +4,13 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/openshift/installer/pkg/asset/cluster" + "github.com/openshift/installer/pkg/asset/cluster/metadata" "github.com/openshift/installer/pkg/destroy/providers" ) // New returns a Destroyer based on `metadata.json` in `rootDir`. func New(logger logrus.FieldLogger, rootDir string) (providers.Destroyer, error) { - metadata, err := cluster.LoadMetadata(rootDir) + metadata, err := metadata.Load(rootDir) if err != nil { return nil, err } diff --git a/pkg/gather/gather.go b/pkg/gather/gather.go index d4a6000c46f..0cde260a480 100644 --- a/pkg/gather/gather.go +++ b/pkg/gather/gather.go @@ -11,13 +11,13 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" - "github.com/openshift/installer/pkg/asset/cluster" + "github.com/openshift/installer/pkg/asset/cluster/metadata" "github.com/openshift/installer/pkg/gather/providers" ) // New returns a Gather based on `metadata.json` in `rootDir`. func New(logger logrus.FieldLogger, serialLogBundle string, bootstrap string, masters []string, rootDir string) (providers.Gather, error) { - metadata, err := cluster.LoadMetadata(rootDir) + metadata, err := metadata.Load(rootDir) if err != nil { return nil, err } diff --git a/pkg/infrastructure/aws/aws.go b/pkg/infrastructure/aws/aws.go index 6d141814d2a..6d8eb885e7a 100644 --- a/pkg/infrastructure/aws/aws.go +++ b/pkg/infrastructure/aws/aws.go @@ -20,6 +20,7 @@ import ( "k8s.io/apimachinery/pkg/util/sets" "github.com/openshift/installer/pkg/asset" + tfvarsAsset "github.com/openshift/installer/pkg/asset/cluster/tfvars" awssession "github.com/openshift/installer/pkg/asset/installconfig/aws" "github.com/openshift/installer/pkg/infrastructure" "github.com/openshift/installer/pkg/tfvars" @@ -58,17 +59,16 @@ type output struct { PrivateSubnetIDs []string `json:"private_subnet_ids,omitempty"` } -// Provision creates the infrastructure resources for the stage. -// dir: the path of the install dir -// vars: cluster configuration input variables, such as terraform variables files -// returns a slice of File assets, which will be appended to the cluster asset file list. -func (a InfraProvider) Provision(dir string, vars []*asset.File) ([]*asset.File, error) { +// Provision creates cluster infrastructure using AWS SDK calls. +func (a InfraProvider) Provision(dir string, parents asset.Parents) ([]*asset.File, error) { + terraformVariables := &tfvarsAsset.TerraformVariables{} + parents.Get(terraformVariables) // Unmarshall input from tf variables, so we can use it along with // installConfig and other assets as the contractual input regardless of // the implementation. clusterConfig := &tfvars.Config{} clusterAWSConfig := &awstfvars.Config{} - for _, file := range vars { + for _, file := range terraformVariables.Files() { switch file.Filename { case tfVarsFileName: if err := json.Unmarshal(file.Data, clusterConfig); err != nil { diff --git a/pkg/infrastructure/clusterapi/clusterapi.go b/pkg/infrastructure/clusterapi/clusterapi.go new file mode 100644 index 00000000000..5ce2ab5b0b4 --- /dev/null +++ b/pkg/infrastructure/clusterapi/clusterapi.go @@ -0,0 +1,285 @@ +package clusterapi + +import ( + "context" + "fmt" + "time" + + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "gopkg.in/yaml.v2" + 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/util/wait" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" + utilkubeconfig "sigs.k8s.io/cluster-api/util/kubeconfig" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/manager/signals" + + "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/cluster/metadata" + "github.com/openshift/installer/pkg/asset/ignition/bootstrap" + "github.com/openshift/installer/pkg/asset/ignition/machine" + "github.com/openshift/installer/pkg/asset/installconfig" + "github.com/openshift/installer/pkg/asset/kubeconfig" + "github.com/openshift/installer/pkg/asset/manifests/capiutils" + capimanifests "github.com/openshift/installer/pkg/asset/manifests/clusterapi" + "github.com/openshift/installer/pkg/asset/rhcos" + "github.com/openshift/installer/pkg/clusterapi" + "github.com/openshift/installer/pkg/infrastructure" + "github.com/openshift/installer/pkg/types" +) + +// InfraProvider is the base implementation for provisioning cluster +// infrastructure using CAPI. Platforms should embed this struct and +// implement: +// . +type InfraProvider struct { + CAPIInfraHelper +} + +func InitializeProvider(platform CAPIInfraHelper) infrastructure.Provider { + return InfraProvider{platform} +} + +type CAPIInfraHelper interface { + // PreProvision is called before provisioning using CAPI controllers has begun. + // and should be used to create dependencies needed for CAPI provisioning, + // such as IAM roles or policies. + PreProvision(in PreProvisionInput) error + + // ControlPlaneAvailable is called once cluster.Spec.ControlPlaneEndpoint.IsValid() + // returns true, typically after load balancers have been provisioned. It can be used + // to create DNS records. + ControlPlaneAvailable(in ControlPlaneAvailableInput) error +} + +type PreProvisionInput struct { + ClusterID string + InstallConfig *installconfig.InstallConfig + Context context.Context + OsImage *rhcos.Image + Parents asset.Parents +} + +type ControlPlaneAvailableInput struct { + Cluster *clusterv1.Cluster + InstallConfig *installconfig.InstallConfig +} + +// Provision creates cluster resources by applying CAPI manifests to a locally running control plane. +func (c InfraProvider) Provision(dir string, parents asset.Parents) ([]*asset.File, error) { + ctx := context.TODO() + capiManifestsAsset := &capimanifests.Cluster{} + clusterKubeconfigAsset := &kubeconfig.AdminClient{} + clusterID := &installconfig.ClusterID{} + rhcosImage := new(rhcos.Image) + installConfig := &installconfig.InstallConfig{} + bootstrapIgnAsset := &bootstrap.Bootstrap{} + masterIgnAsset := &machine.Master{} + parents.Get( + capiManifestsAsset, + clusterKubeconfigAsset, + clusterID, + installConfig, + bootstrapIgnAsset, + masterIgnAsset, + rhcosImage, + ) + + fileList := []*asset.File{} + manifests := []client.Object{} + for _, m := range capiManifestsAsset.RuntimeFiles() { + manifests = append(manifests, m.Object) + } + + // Gather the ignition files, store them in a secret, and add them to manifests. + { + masterIgn := string(masterIgnAsset.Files()[0].Data) + bootstrapIgn, err := injectInstallInfo(bootstrapIgnAsset.Files()[0].Data) + if err != nil { + return fileList, errors.Wrap(err, "unable to inject installation info") + } + manifests = append(manifests, + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%s", clusterID.InfraID, "master"), + Namespace: capiutils.Namespace, + Labels: map[string]string{ + "cluster.x-k8s.io/cluster-name": clusterID.InfraID, + }, + }, + Data: map[string][]byte{ + "format": []byte("ignition"), + "value": []byte(masterIgn), + }, + }, + &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: fmt.Sprintf("%s-%s", clusterID.InfraID, "bootstrap"), + Namespace: capiutils.Namespace, + Labels: map[string]string{ + "cluster.x-k8s.io/cluster-name": clusterID.InfraID, + }, + }, + Data: map[string][]byte{ + "format": []byte("ignition"), + "value": []byte(bootstrapIgn), + }, + }, + ) + } + + preProvisionInput := PreProvisionInput{ + ClusterID: clusterID.InfraID, + InstallConfig: installConfig, + Context: ctx, + OsImage: rhcosImage, + Parents: parents, + } + if err := c.PreProvision(preProvisionInput); err != nil { + return fileList, fmt.Errorf("failed during pre-provisioning: %w", err) + } + + // TODO(vincepri): The context should be passed down from the caller, + // although today the Asset interface doesn't allow it, refactor once it does. + ctx, cancel := context.WithCancel(signals.SetupSignalHandler()) + go func() { + <-ctx.Done() + cancel() + clusterapi.System().Teardown() + }() + // Run the CAPI system. + capiSystem := clusterapi.System() + if err := capiSystem.Run(ctx, installConfig); err != nil { + return fileList, fmt.Errorf("failed to run cluster api system: %w", err) + } + + // Grab the client. + cl := capiSystem.Client() + + // Create all the manifests and store them. + for _, m := range manifests { + m.SetNamespace(capiutils.Namespace) + if err := cl.Create(context.Background(), m); err != nil { + return fileList, fmt.Errorf("failed to create manifest: %w", err) + } + logrus.Infof("Created manifest %+T, namespace=%s name=%s", m, m.GetNamespace(), m.GetName()) + } + + // Pass cluster kubeconfig and store it in; this is usually the role of a bootstrap provider. + { + key := client.ObjectKey{ + Name: clusterID.InfraID, + Namespace: capiutils.Namespace, + } + cluster := &clusterv1.Cluster{} + if err := cl.Get(context.Background(), key, cluster); err != nil { + // TODO (padillon): from this point forward statuses could be + // collected from the manifests appended to the fileList. + return fileList, err + } + // Create the secret. + clusterKubeconfig := clusterKubeconfigAsset.Files()[0].Data + secret := utilkubeconfig.GenerateSecret(cluster, clusterKubeconfig) + if err := cl.Create(context.Background(), secret); err != nil { + return fileList, err + } + } + + // Wait for the load balancer to be ready by checking the control plane endpoint + // on the cluster object. + var cluster *clusterv1.Cluster + { + if err := wait.ExponentialBackoff(wait.Backoff{ + Duration: time.Second * 10, + Factor: float64(1.5), + Steps: 32, + }, func() (bool, error) { + c := &clusterv1.Cluster{} + if err := cl.Get(context.Background(), client.ObjectKey{ + Name: clusterID.InfraID, + Namespace: capiutils.Namespace, + }, c); err != nil { + if apierrors.IsNotFound(err) { + return false, nil + } + return false, err + } + cluster = c + return cluster.Spec.ControlPlaneEndpoint.IsValid(), nil + }); err != nil { + return fileList, err + } + if cluster == nil { + return fileList, errors.New("error occurred during load balancer ready check") + } + if cluster.Spec.ControlPlaneEndpoint.Host == "" { + return fileList, errors.New("control plane endpoint is not set") + } + } + + controlPlaneAvailableInput := ControlPlaneAvailableInput{ + Cluster: cluster, + InstallConfig: installConfig, + } + if err := c.ControlPlaneAvailable(controlPlaneAvailableInput); err != nil { + return fileList, fmt.Errorf("failed provisioning resources after control plane available: %w", err) + } + + // For each manifest we created, retrieve it and store it in the asset. + for _, m := range manifests { + key := client.ObjectKey{ + Name: m.GetName(), + Namespace: m.GetNamespace(), + } + if err := cl.Get(context.Background(), key, m); err != nil { + return fileList, fmt.Errorf("failed to get manifest: %w", err) + } + + gvk, err := cl.GroupVersionKindFor(m) + if err != nil { + return fileList, fmt.Errorf("failed to get GVK for manifest: %w", err) + } + fileName := fmt.Sprintf("%s-%s-%s.yaml", gvk.Kind, m.GetNamespace(), m.GetName()) + objData, err := yaml.Marshal(m) + if err != nil { + errMsg := fmt.Sprintf("failed to create infrastructure manifest %s from InstallConfig", fileName) + return fileList, errors.Wrapf(err, errMsg) + } + fileList = append(fileList, &asset.File{ + Filename: fileName, + Data: objData, + }) + } + + logrus.Infof("Cluster API resources have been created. Waiting for cluster to become ready...") + return fileList, nil +} + +// DestroyBootstrap destroys the temporary bootstrap resources. +func (c InfraProvider) DestroyBootstrap(dir string) error { + metadata, err := metadata.Load(dir) + if err != nil { + return err + } + + // TODO(padillon): start system if not running + if sys := clusterapi.System(); sys.State() == clusterapi.SystemStateRunning { + if err := sys.Client().Delete(context.TODO(), &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Name: capiutils.GenerateBoostrapMachineName(metadata.InfraID), + Namespace: capiutils.Namespace, + }, + }); client.IgnoreNotFound(err) != nil { + return fmt.Errorf("failed to delete bootstrap machine: %w", err) + } + } + return nil +} + +// ExtractHostAddresses extracts the IPs of the bootstrap and control plane machines. +func (c InfraProvider) ExtractHostAddresses(dir string, config *types.InstallConfig, ha *infrastructure.HostAddresses) error { + return nil +} diff --git a/pkg/asset/manifests/clusterapi/helpers.go b/pkg/infrastructure/clusterapi/helpers.go similarity index 100% rename from pkg/asset/manifests/clusterapi/helpers.go rename to pkg/infrastructure/clusterapi/helpers.go diff --git a/pkg/infrastructure/platform/platform.go b/pkg/infrastructure/platform/platform.go index d28b082ed08..83bb6bc4bae 100644 --- a/pkg/infrastructure/platform/platform.go +++ b/pkg/infrastructure/platform/platform.go @@ -9,6 +9,8 @@ import ( configv1 "github.com/openshift/api/config/v1" "github.com/openshift/installer/pkg/infrastructure" awsinfra "github.com/openshift/installer/pkg/infrastructure/aws" + "github.com/openshift/installer/pkg/infrastructure/clusterapi" + vspherecapi "github.com/openshift/installer/pkg/infrastructure/vsphere/clusterapi" "github.com/openshift/installer/pkg/terraform" "github.com/openshift/installer/pkg/terraform/stages/alibabacloud" "github.com/openshift/installer/pkg/terraform/stages/aws" @@ -70,6 +72,9 @@ func ProviderForPlatform(platform string, fg featuregates.FeatureGate) (infrastr case ovirttypes.Name: return terraform.InitializeProvider(ovirt.PlatformStages), nil case vspheretypes.Name: + if fg.Enabled(configv1.FeatureGateClusterAPIInstall) { + return clusterapi.InitializeProvider(vspherecapi.InfraHelper{}), nil + } return terraform.InitializeProvider(vsphere.PlatformStages), nil case nonetypes.Name: // terraform is not used when the platform is "none" diff --git a/pkg/infrastructure/provider.go b/pkg/infrastructure/provider.go index a0f1d7e5443..135807d554f 100644 --- a/pkg/infrastructure/provider.go +++ b/pkg/infrastructure/provider.go @@ -10,9 +10,9 @@ import ( type Provider interface { // Provision creates the infrastructure resources for the stage. // dir: the path of the install dir - // vars: cluster configuration input variables, such as terraform variables files + // parents: the parent assets, which can be used to obtain any cluser asset dependencies // returns a slice of File assets, which will be appended to the cluster asset file list. - Provision(dir string, vars []*asset.File) ([]*asset.File, error) + Provision(dir string, parents asset.Parents) ([]*asset.File, error) // DestroyBootstrap destroys the temporary bootstrap resources. DestroyBootstrap(dir string) error diff --git a/pkg/infrastructure/vsphere/clusterapi/clusterapi.go b/pkg/infrastructure/vsphere/clusterapi/clusterapi.go new file mode 100644 index 00000000000..e08f62b46f5 --- /dev/null +++ b/pkg/infrastructure/vsphere/clusterapi/clusterapi.go @@ -0,0 +1,335 @@ +package clusterapi + +import ( + "context" + "fmt" + "io" + "os" + "path" + "strings" + + "crypto/sha256" + + vcentercontexts "github.com/openshift/installer/pkg/asset/cluster/vsphere" + "github.com/openshift/installer/pkg/asset/installconfig" + "github.com/openshift/installer/pkg/asset/rhcos" + "github.com/openshift/installer/pkg/infrastructure/clusterapi" + "github.com/openshift/installer/pkg/rhcos/cache" + "github.com/openshift/installer/pkg/types/vsphere" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "github.com/vmware/govmomi/find" + "github.com/vmware/govmomi/govc/importx" + "github.com/vmware/govmomi/nfc" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/ovf" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" + "sigs.k8s.io/cluster-api-provider-vsphere/pkg/session" +) + +type InfraHelper struct { + clusterapi.CAPIInfraHelper +} + +func attachTag(ctx context.Context, session *session.Session, vmMoRefValue, tagId string) error { + tagManager := session.TagManager + + moRef := types.ManagedObjectReference{ + Value: vmMoRefValue, + Type: "VirtualMachine", + } + + err := tagManager.AttachTag(ctx, tagId, moRef) + + if err != nil { + return fmt.Errorf("unable to attach tag: %s", err) + } + return nil +} + +func findAvailableHostSystems(ctx context.Context, session *session.Session, clusterHostSystems []*object.HostSystem) (*object.HostSystem, error) { + var hostSystemManagedObject mo.HostSystem + for _, hostObj := range clusterHostSystems { + err := hostObj.Properties(ctx, hostObj.Reference(), []string{"config.product", "network", "datastore", "runtime"}, &hostSystemManagedObject) + if err != nil { + return nil, err + } + if hostSystemManagedObject.Runtime.InMaintenanceMode { + continue + } + return hostObj, nil + } + return nil, errors.New("all hosts unavailable") +} + +// Used govc/importx/ovf.go as an example to implement +// resourceVspherePrivateImportOvaCreate and upload functions +// See: https://github.com/vmware/govmomi/blob/cc10a0758d5b4d4873388bcea417251d1ad03e42/govc/importx/ovf.go#L196-L324 +func upload(ctx context.Context, archive *importx.ArchiveFlag, lease *nfc.Lease, item nfc.FileItem) error { + file := item.Path + + f, size, err := archive.Open(file) + if err != nil { + return err + } + defer f.Close() + + opts := soap.Upload{ + ContentLength: size, + } + + return lease.Upload(ctx, item, f, opts) +} + +func importRhcosOva(ctx context.Context, session *session.Session, folder *object.Folder, cachedImage, clusterId, tagId, diskProvisioningType string, failureDomain vsphere.FailureDomain) error { + name := fmt.Sprintf("%s-rhcos-%s-%s", clusterId, failureDomain.Region, failureDomain.Zone) + + archive := &importx.ArchiveFlag{Archive: &importx.TapeArchive{Path: cachedImage}} + + ovfDescriptor, err := archive.ReadOvf("*.ovf") + if err != nil { + // Open the corrupt OVA file + f, ferr := os.Open(cachedImage) + if ferr != nil { + err = fmt.Errorf("%s, %w", err.Error(), ferr) + } + defer f.Close() + + // Get a sha256 on the corrupt OVA file + // and the size of the file + h := sha256.New() + written, cerr := io.Copy(h, f) + if cerr != nil { + err = fmt.Errorf("%s, %w", err.Error(), cerr) + } + + return fmt.Errorf("ova %s has a sha256 of %x and a size of %d bytes, failed to read the ovf descriptor %s", cachedImage, h.Sum(nil), written, err) + } + + ovfEnvelope, err := archive.ReadEnvelope(ovfDescriptor) + if err != nil { + return fmt.Errorf("failed to parse ovf: %s", err) + } + + // The RHCOS OVA only has one network defined by default + // The OVF envelope defines this. We need a 1:1 mapping + // between networks with the OVF and the host + if len(ovfEnvelope.Network.Networks) != 1 { + return fmt.Errorf("expected the OVA to only have a single network adapter") + } + + cluster, err := session.Finder.ClusterComputeResource(ctx, failureDomain.Topology.ComputeCluster) + if err != nil { + return fmt.Errorf("failed to find compute cluster: %s", err) + } + + clusterHostSystems, err := cluster.Hosts(ctx) + + if err != nil { + return fmt.Errorf("failed to get cluster hosts: %s", err) + } + resourcePool, err := session.Finder.ResourcePool(ctx, failureDomain.Topology.ResourcePool) + if err != nil { + return fmt.Errorf("failed to find resource pool: %s", err) + } + + networkPath := path.Join(cluster.InventoryPath, failureDomain.Topology.Networks[0]) + + networkRef, err := session.Finder.Network(ctx, networkPath) + if err != nil { + return fmt.Errorf("failed to find network: %s", err) + + } + datastore, err := session.Finder.Datastore(ctx, failureDomain.Topology.Datastore) + if err != nil { + return fmt.Errorf("failed to find datastore: %s", err) + } + + // Create mapping between OVF and the network object + // found by Name + networkMappings := []types.OvfNetworkMapping{{ + Name: ovfEnvelope.Network.Networks[0].Name, + Network: networkRef.Reference(), + }} + + // This is a very minimal spec for importing an OVF. + cisp := types.OvfCreateImportSpecParams{ + EntityName: name, + NetworkMapping: networkMappings, + } + + m := ovf.NewManager(session.Client.Client) + spec, err := m.CreateImportSpec(ctx, + string(ovfDescriptor), + resourcePool.Reference(), + datastore.Reference(), + cisp) + + if err != nil { + return fmt.Errorf("failed to create import spec: %s", err) + } + if spec.Error != nil { + return errors.New(spec.Error[0].LocalizedMessage) + } + + hostSystem, err := findAvailableHostSystems(ctx, session, clusterHostSystems) + if err != nil { + return fmt.Errorf("failed to find available host system: %s", err) + } + + lease, err := resourcePool.ImportVApp(ctx, spec.ImportSpec, folder, hostSystem) + + if err != nil { + return fmt.Errorf("failed to import vapp: %s", err) + } + + info, err := lease.Wait(ctx, spec.FileItem) + if err != nil { + return fmt.Errorf("failed to lease wait: %s", err) + } + + u := lease.StartUpdater(ctx, info) + defer u.Done() + + for _, i := range info.Items { + // upload the vmdk to which ever host that was first + // available with the required network and datastore. + err = upload(ctx, archive, lease, i) + if err != nil { + return fmt.Errorf("failed to upload: %s", err) + } + } + + err = lease.Complete(ctx) + if err != nil { + return fmt.Errorf("failed to lease complete: %s", err) + } + + vm := object.NewVirtualMachine(session.Client.Client, info.Entity) + if vm == nil { + return fmt.Errorf("error VirtualMachine not found, managed object id: %s", info.Entity.Value) + } + + err = vm.MarkAsTemplate(ctx) + if err != nil { + return fmt.Errorf("failed to mark vm as template: %s", err) + } + err = attachTag(ctx, session, vm.Reference().Value, tagId) + if err != nil { + return fmt.Errorf("failed to attach tag: %s", err) + } + + return nil +} + +func createFolder(ctx context.Context, fullpath string, session *session.Session) (*object.Folder, error) { + dir := path.Dir(fullpath) + base := path.Base(fullpath) + finder := session.Finder + + folder, err := finder.Folder(ctx, fullpath) + + if folder == nil { + folder, err = finder.Folder(ctx, dir) + + var notFoundError *find.NotFoundError + if errors.As(err, ¬FoundError) { + folder, err = createFolder(ctx, dir, session) + if err != nil { + return folder, err + } + } + + if folder != nil { + folder, err = folder.CreateFolder(ctx, base) + if err != nil { + return folder, err + } + } + } + return folder, err +} + +func initializeFoldersAndTemplates(ctx context.Context, rhcosImage *rhcos.Image, installConfig *installconfig.InstallConfig, session *session.Session, clusterId, server string, vcenterContexts *vcentercontexts.VCenterContexts) error { + finder := session.Finder + + platform := installConfig.Config.VSphere + failureDomains := platform.FailureDomains + + for _, failureDomain := range failureDomains { + dc, err := finder.Datacenter(ctx, failureDomain.Topology.Datacenter) + if err != nil { + return err + } + dcFolders, err := dc.Folders(ctx) + if err != nil { + return fmt.Errorf("unable to get datacenter folder: %v", err) + } + + folderPath := path.Join(dcFolders.VmFolder.InventoryPath, clusterId) + + // we must set the Folder to the infraId somewhere, we will need to remove that. + // if we are overwriting folderPath it needs to have a slash (path) + folder := failureDomain.Topology.Folder + if strings.Contains(folder, "/") { + folderPath = folder + } + + folderMo, err := createFolder(ctx, folderPath, session) + if err != nil { + return fmt.Errorf("unable to create folder: %v", err) + } + + cachedImage, err := cache.DownloadImageFile(string(*rhcosImage), cache.InstallerApplicationName) + if err != nil { + return fmt.Errorf("failed to use cached vsphere image: %v", err) + } + + // if the template is empty, the ova must be imported + if len(failureDomain.Topology.Template) == 0 { + if err = importRhcosOva(ctx, session, folderMo, + cachedImage, clusterId, vcenterContexts.VCenters[server].TagID, string(platform.DiskType), failureDomain); err != nil { + return fmt.Errorf("failed to import ova: %v", err) + } + } + } + return nil +} + +func (a InfraHelper) PreProvision(in clusterapi.PreProvisionInput) error { + ctx := in.Context + + installConfig := in.InstallConfig.Config + vcenterContexts := &vcentercontexts.VCenterContexts{} + + in.Parents.Get(vcenterContexts) + + for _, vcenter := range installConfig.VSphere.VCenters { + server := vcenter.Server + params := session.NewParams().WithServer(server).WithUserInfo(vcenter.Username, vcenter.Password) + tempConnection, err := session.GetOrCreate(ctx, params) + if err != nil { + return fmt.Errorf("unable to create session: %v", err) + } + + defer tempConnection.CloseIdleConnections() + + for _, failureDomain := range installConfig.VSphere.FailureDomains { + if failureDomain.Server != server { + continue + } + if err = initializeFoldersAndTemplates(ctx, in.OsImage, in.InstallConfig, tempConnection, in.ClusterID, server, vcenterContexts); err != nil { + return fmt.Errorf("unable to initialize folders and templates: %v", err) + } + } + } + + return nil +} + +func (a InfraHelper) ControlPlaneAvailable(in clusterapi.ControlPlaneAvailableInput) error { + logrus.Infoln("Calling vSphere ControlPlaneAvailable") + return nil +} diff --git a/pkg/terraform/terraform.go b/pkg/terraform/terraform.go index 536779e053b..f2f6f0589e2 100644 --- a/pkg/terraform/terraform.go +++ b/pkg/terraform/terraform.go @@ -12,6 +12,7 @@ import ( "github.com/sirupsen/logrus" "github.com/openshift/installer/pkg/asset" + "github.com/openshift/installer/pkg/asset/cluster/tfvars" "github.com/openshift/installer/pkg/infrastructure" "github.com/openshift/installer/pkg/lineprinter" "github.com/openshift/installer/pkg/metrics/timer" @@ -35,7 +36,11 @@ func InitializeProvider(stages []Stage) infrastructure.Provider { // Provision implements pkg/infrastructure/provider.Provision. Provision iterates // through each of the stages and applies the Terraform config for the stage. -func (p *Provider) Provision(dir string, vars []*asset.File) ([]*asset.File, error) { +func (p *Provider) Provision(dir string, parents asset.Parents) ([]*asset.File, error) { + tfVars := &tfvars.TerraformVariables{} + parents.Get(tfVars) + vars := tfVars.Files() + fileList := []*asset.File{} terraformDir := filepath.Join(dir, "terraform") if err := os.Mkdir(terraformDir, 0777); err != nil { diff --git a/pkg/tfvars/vsphere/vsphere.go b/pkg/tfvars/vsphere/vsphere.go index 347eba3835f..617b5ed05c1 100644 --- a/pkg/tfvars/vsphere/vsphere.go +++ b/pkg/tfvars/vsphere/vsphere.go @@ -1,20 +1,18 @@ package vsphere import ( - "encoding/hex" "encoding/json" "fmt" - "net" - "net/netip" - "strings" "github.com/pkg/errors" "github.com/sirupsen/logrus" + ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" machineapi "github.com/openshift/api/machine/v1beta1" "github.com/openshift/installer/pkg/asset/installconfig" "github.com/openshift/installer/pkg/rhcos/cache" vtypes "github.com/openshift/installer/pkg/types/vsphere" + "github.com/openshift/installer/pkg/utils" ) type folder struct { @@ -45,6 +43,7 @@ type TFVarsSources struct { InstallConfig *installconfig.InstallConfig InfraID string ControlPlaneMachines []machineapi.Machine + IPAddresses []ipamv1.IPAddress } // TFVars generate vSphere-specific Terraform variables @@ -146,78 +145,6 @@ func convertVCentersToMap(values []vtypes.VCenter) map[string]vtypes.VCenter { return vcenterMap } -func getSubnetMask(prefix netip.Prefix) (string, error) { - prefixLength := net.IPv4len * 8 - if prefix.Addr().Is6() { - prefixLength = net.IPv6len * 8 - } - ipMask := net.CIDRMask(prefix.Masked().Bits(), prefixLength) - maskBytes, err := hex.DecodeString(ipMask.String()) - if err != nil { - return "", err - } - ip := net.IP(maskBytes) - maskStr := ip.To16().String() - return maskStr, nil -} - -func constructKargsFromNetworkConfig(ipAddrs []string, nameservers []string, gateway string) (string, error) { - outKargs := "" - - var gatewayIP netip.Addr - if len(gateway) > 0 { - ip, err := netip.ParseAddr(gateway) - if err != nil { - return "", err - } - if ip.Is6() { - gateway = fmt.Sprintf("[%s]", gateway) - } - gatewayIP = ip - } - - for _, address := range ipAddrs { - prefix, err := netip.ParsePrefix(address) - if err != nil { - return "", err - } - var ipStr, gatewayStr, maskStr string - addr := prefix.Addr() - switch { - case addr.Is6(): - maskStr = fmt.Sprintf("%d", prefix.Bits()) - ipStr = fmt.Sprintf("[%s]", addr.String()) - if len(gateway) > 0 && gatewayIP.Is6() { - gatewayStr = gateway - } - case addr.Is4(): - maskStr, err = getSubnetMask(prefix) - if err != nil { - return "", err - } - if len(gateway) > 0 && gatewayIP.Is4() { - gatewayStr = gateway - } - ipStr = addr.String() - default: - return "", errors.New("IP address must adhere to IPv4 or IPv6 format") - } - outKargs += fmt.Sprintf("ip=%s::%s:%s:::none ", ipStr, gatewayStr, maskStr) - } - - for _, nameserver := range nameservers { - ip := net.ParseIP(nameserver) - if ip.To4() == nil { - nameserver = fmt.Sprintf("[%s]", nameserver) - } - outKargs += fmt.Sprintf("nameserver=%s ", nameserver) - } - - outKargs = strings.Trim(outKargs, " ") - logrus.Debugf("Generated karg: [%v].", outKargs) - return outKargs, nil -} - // processGuestNetworkConfiguration takes the config and sources data and generates the kernel arguments (kargs) // needed to boot RHCOS with static IP configurations. func processGuestNetworkConfiguration(cfg *config, sources TFVarsSources) error { @@ -228,7 +155,12 @@ func processGuestNetworkConfiguration(cfg *config, sources TFVarsSources) error if host.Role == vtypes.BootstrapRole { logrus.Debugf("Generating kargs for bootstrap") network := host.NetworkDevice - kargs, err := constructKargsFromNetworkConfig(network.IPAddrs, network.Nameservers, network.Gateway) + // Copy the one gateway into array so construct method can determine where to use it. + gateways := make([]string, len(network.IPAddrs)) + for i := 0; i < len(gateways); i++ { + gateways[i] = network.Gateway + } + kargs, err := utils.ConstructKargsFromNetworkConfig(network.IPAddrs, network.Nameservers, gateways) if err != nil { return err } @@ -237,13 +169,42 @@ func processGuestNetworkConfiguration(cfg *config, sources TFVarsSources) error } } - // Generate control plane kargs using info from machine network config - for _, machine := range sources.ControlPlaneConfigs { - logrus.Debugf("Generating kargs for control plane %v", machine.GenerateName) - network := machine.Network.Devices[0] - kargs, err := constructKargsFromNetworkConfig(network.IPAddrs, network.Nameservers, network.Gateway) - if err != nil { - return err + // Current logic assumes only 1 network defined per machine + for index, machine := range sources.ControlPlaneMachines { + logrus.Infof("Generating kargs for control plane %v.", machine.Name) + network := sources.ControlPlaneConfigs[index].Network.Devices[0] + var kargs string + var err error + + // Check to see if AddressFromPool is in use. If so, we'll grab IPAddress w/ the same name. + // If no AddressesFromPools, check for static IP defined. + if network.AddressesFromPools != nil { + var ipAddresses []string + var gateways []string + for idx := range network.AddressesFromPools { + for _, address := range sources.IPAddresses { + logrus.Debugf("Checking IPAdress %v. Does it match? %v", address.Name, fmt.Sprintf("%s-claim-%d-%d", machine.Name, 0, idx)) + if address.Name == fmt.Sprintf("%s-claim-%d-%d", machine.Name, 0, idx) { + ipAddresses = append(ipAddresses, fmt.Sprintf("%v/%v", address.Spec.Address, address.Spec.Prefix)) + gateways = append(gateways, address.Spec.Gateway) + break + } + } + } + kargs, err = utils.ConstructKargsFromNetworkConfig(ipAddresses, network.Nameservers, gateways) + if err != nil { + return err + } + } else { + // Copy the one gateway into array so construct method can determine where to use it. + gateways := make([]string, len(network.IPAddrs)) + for i := 0; i < len(gateways); i++ { + gateways[i] = network.Gateway + } + kargs, err = utils.ConstructKargsFromNetworkConfig(network.IPAddrs, network.Nameservers, gateways) + if err != nil { + return err + } } cfg.ControlPlaneNetworkKargs = append(cfg.ControlPlaneNetworkKargs, kargs) } diff --git a/pkg/tfvars/vsphere/vsphere_test.go b/pkg/tfvars/vsphere/vsphere_test.go index bfb11fbbe12..4c037a73133 100644 --- a/pkg/tfvars/vsphere/vsphere_test.go +++ b/pkg/tfvars/vsphere/vsphere_test.go @@ -3,9 +3,12 @@ package vsphere import ( "fmt" "regexp" + "strconv" + "strings" "testing" "github.com/stretchr/testify/assert" + ipamv1 "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" "github.com/openshift/api/machine/v1beta1" "github.com/openshift/installer/pkg/asset/installconfig" @@ -23,7 +26,7 @@ const ( ipv6 = 0x02 ) -func createTFVarsSources(createHosts bool, ipTypes int64, cpc []*v1beta1.VSphereMachineProviderSpec) TFVarsSources { +func createTFVarsSources(createHosts bool, ipTypes int64) TFVarsSources { tvs := TFVarsSources{ InstallConfig: &installconfig.InstallConfig{ AssetBase: installconfig.AssetBase{ @@ -34,11 +37,14 @@ func createTFVarsSources(createHosts bool, ipTypes int64, cpc []*v1beta1.VSphere }, }, }, - ControlPlaneConfigs: cpc, } if createHosts { tvs.InstallConfig.Config.VSphere.Hosts = createValidHosts(ipTypes) + machines, cpc, ips := createControlPlaneConfigs(ipTypes) + tvs.ControlPlaneMachines = machines + tvs.ControlPlaneConfigs = cpc + tvs.IPAddresses = ips } return tvs @@ -69,11 +75,15 @@ func createValidHosts(ipTypes int64) []*vsphere.Host { return hosts } -func createControlPlaneConfigs(ipTypes int64) []*v1beta1.VSphereMachineProviderSpec { - var machines []*v1beta1.VSphereMachineProviderSpec +func createControlPlaneConfigs(ipTypes int64) ([]v1beta1.Machine, []*v1beta1.VSphereMachineProviderSpec, []ipamv1.IPAddress) { + var machines []v1beta1.Machine + var specs []*v1beta1.VSphereMachineProviderSpec + var ips []ipamv1.IPAddress for i := 1; i <= 3; i++ { - machine := &v1beta1.VSphereMachineProviderSpec{ + machine := v1beta1.Machine{} + machine.Name = fmt.Sprintf("master-%d", i-1) + spec := &v1beta1.VSphereMachineProviderSpec{ Network: v1beta1.NetworkSpec{ Devices: []v1beta1.NetworkDeviceSpec{ { @@ -83,24 +93,64 @@ func createControlPlaneConfigs(ipTypes int64) []*v1beta1.VSphereMachineProviderS }, } + var gateway string if ipTypes&ipv4 != 0 { - machine.Network.Devices[0].Gateway = ipv4Gateway - machine.Network.Devices[0].Nameservers = append(machine.Network.Devices[0].Nameservers, "8.8.8.8") + gateway = ipv4Gateway + spec.Network.Devices[0].Nameservers = append(spec.Network.Devices[0].Nameservers, "8.8.8.8") } else if ipTypes&ipv6 != 0 { - machine.Network.Devices[0].Gateway = ipv6Gateway - machine.Network.Devices[0].Nameservers = append(machine.Network.Devices[0].Nameservers, "2001::100") + gateway = ipv6Gateway + spec.Network.Devices[0].Nameservers = append(spec.Network.Devices[0].Nameservers, "2001::100") } + idx := 0 if ipTypes&ipv4 != 0 { - machine.Network.Devices[0].IPAddrs = append(machine.Network.Devices[0].IPAddrs, fmt.Sprintf(ipv4Template, i)) + ipAddress := ipamv1.IPAddress{} + ipAddress.Name = fmt.Sprintf("%s-claim-%d-%d", machine.Name, 0, idx) + pool := v1beta1.AddressesFromPool{ + Group: "installer.openshift.io", + Resource: "IPPool", + Name: fmt.Sprintf("default-%d", idx), + } + spec.Network.Devices[0].AddressesFromPools = append(spec.Network.Devices[0].AddressesFromPools, pool) + ip := fmt.Sprintf(ipv4Template, i) + separatorIndex := strings.Index(ip, "/") + if separatorIndex > 0 { + ipAddress.Spec.Address = ip[:separatorIndex] + prefix, err := strconv.Atoi(ip[strings.Index(ip, "/")+1:]) + if err == nil { + ipAddress.Spec.Prefix = prefix + } + } + ipAddress.Spec.Gateway = gateway + ips = append(ips, ipAddress) + idx++ } if ipTypes&ipv6 != 0 { - machine.Network.Devices[0].IPAddrs = append(machine.Network.Devices[0].IPAddrs, fmt.Sprintf(ipv6Template, i)) + ipAddress := ipamv1.IPAddress{} + ipAddress.Name = fmt.Sprintf("%s-claim-%d-%d", machine.Name, 0, idx) + pool := v1beta1.AddressesFromPool{ + Group: "installer.openshift.io", + Resource: "IPPool", + Name: fmt.Sprintf("default-%d", idx), + } + spec.Network.Devices[0].AddressesFromPools = append(spec.Network.Devices[0].AddressesFromPools, pool) + ip := fmt.Sprintf(ipv6Template, i) + separatorIndex := strings.Index(ip, "/") + if separatorIndex > 0 { + ipAddress.Spec.Address = ip[:separatorIndex] + prefix, err := strconv.Atoi(ip[strings.Index(ip, "/")+1:]) + if err == nil { + ipAddress.Spec.Prefix = prefix + } + } + ipAddress.Spec.Gateway = gateway + ips = append(ips, ipAddress) } + specs = append(specs, spec) machines = append(machines, machine) } - return machines + return machines, specs, ips } func createVsphereConfig() *config { @@ -119,14 +169,14 @@ func TestProcessGuestNetworkConfiguration(t *testing.T) { { name: "No Hosts", config: createVsphereConfig(), - source: createTFVarsSources(false, 0, nil), + source: createTFVarsSources(false, 0), expectedBootKargs: "", expectedControlKargs: []string(nil), }, { name: "Hosts - Single IPV4", config: createVsphereConfig(), - source: createTFVarsSources(true, ipv4, createControlPlaneConfigs(ipv4)), + source: createTFVarsSources(true, ipv4), expectedBootKargs: "ip=192.168.101.240::192.168.101.200:255.255.255.0:::none nameserver=8.8.8.8", expectedControlKargs: []string{ "ip=192.168.101.241::192.168.101.200:255.255.255.0:::none nameserver=8.8.8.8", @@ -137,7 +187,7 @@ func TestProcessGuestNetworkConfiguration(t *testing.T) { { name: "Hosts - Single IPV6", config: createVsphereConfig(), - source: createTFVarsSources(true, ipv6, createControlPlaneConfigs(ipv6)), + source: createTFVarsSources(true, ipv6), expectedBootKargs: "ip=[2001::240]::[2001::200]:64:::none nameserver=[2001::100]", expectedControlKargs: []string{ "ip=[2001::241]::[2001::200]:64:::none nameserver=[2001::100]", @@ -148,7 +198,7 @@ func TestProcessGuestNetworkConfiguration(t *testing.T) { { name: "Hosts - Dual Stack", config: createVsphereConfig(), - source: createTFVarsSources(true, ipv4|ipv6, createControlPlaneConfigs(ipv4|ipv6)), + source: createTFVarsSources(true, ipv4|ipv6), expectedBootKargs: "ip=192.168.101.240::192.168.101.200:255.255.255.0:::none ip=[2001::240]:::64:::none nameserver=8.8.8.8", expectedControlKargs: []string{ "ip=192.168.101.241::192.168.101.200:255.255.255.0:::none ip=[2001::241]:::64:::none nameserver=8.8.8.8", diff --git a/pkg/utils/vmware.go b/pkg/utils/vmware.go new file mode 100644 index 00000000000..a30b67794a4 --- /dev/null +++ b/pkg/utils/vmware.go @@ -0,0 +1,137 @@ +package utils + +import ( + "encoding/hex" + "errors" + "fmt" + "net" + "net/netip" + "strings" + + machinev1beta1 "github.com/openshift/api/machine/v1beta1" + "github.com/openshift/installer/pkg/types" + "github.com/sirupsen/logrus" + "sigs.k8s.io/cluster-api/exp/ipam/api/v1alpha1" +) + +func getIpAddressForClaim(claim v1alpha1.IPAddressClaim, addresses []v1alpha1.IPAddress) (*v1alpha1.IPAddress, error) { + for _, address := range addresses { + if address.Name == claim.Status.AddressRef.Name { + return &address, nil + } + } + return nil, fmt.Errorf("unable to find address for claim %s", claim.Name) +} + +func ConstructNetworkKargsFromMachine(claims []v1alpha1.IPAddressClaim, addresses []v1alpha1.IPAddress, machine *machinev1beta1.Machine) (string, error) { + addressList := []string{} + gatewayList := []string{} + nameserverList := []string{} + + for _, claim := range claims { + for _, ownerReference := range claim.OwnerReferences { + if ownerReference.Name != machine.Name { + continue + } + address, err := getIpAddressForClaim(claim, addresses) + if err != nil { + return "", fmt.Errorf("unable to get address for claim %s: %w", claim.Name, err) + } + + addressList = append(addressList, fmt.Sprintf("%s/%d", address.Spec.Address, address.Spec.Prefix)) + gatewayList = append(gatewayList, address.Spec.Gateway) + for _, networkDevices := range machine.Spec.ProviderSpec.Value.Object.(*machinev1beta1.VSphereMachineProviderSpec).Network.Devices { + if networkDevices.Nameservers == nil { + continue + } + nameserverList = append(nameserverList, networkDevices.Nameservers...) + } + } + } + return ConstructKargsFromNetworkConfig(addressList, nameserverList, gatewayList) +} + +func getSubnetMask(prefix netip.Prefix) (string, error) { + prefixLength := net.IPv4len * 8 + if prefix.Addr().Is6() { + prefixLength = net.IPv6len * 8 + } + ipMask := net.CIDRMask(prefix.Masked().Bits(), prefixLength) + maskBytes, err := hex.DecodeString(ipMask.String()) + if err != nil { + return "", err + } + ip := net.IP(maskBytes) + maskStr := ip.To16().String() + return maskStr, nil +} + +// ConstructKargsForBootstrap constructs the kargs string for a bootstrap node +func ConstructKargsForBootstrap(installConfig *types.InstallConfig) (string, error) { + for _, host := range installConfig.VSphere.Hosts { + if host.Role != "bootstrap" { + continue + } + return ConstructKargsFromNetworkConfig(host.NetworkDevice.IPAddrs, host.NetworkDevice.Nameservers, []string{host.NetworkDevice.Gateway}) + } + return "", errors.New("unable to find host with bootstrap role") +} + +// ConstructKargsFromNetworkConfig constructs the kargs string from the network configuration +func ConstructKargsFromNetworkConfig(ipAddrs []string, nameservers []string, gateways []string) (string, error) { + outKargs := "" + + for index, address := range ipAddrs { + var gatewayIP netip.Addr + gateway := gateways[index] + if len(gateway) > 0 { + ip, err := netip.ParseAddr(gateway) + if err != nil { + return "", err + } + if ip.Is6() { + gateway = fmt.Sprintf("[%s]", gateway) + } + gatewayIP = ip + } + + prefix, err := netip.ParsePrefix(address) + if err != nil { + return "", err + } + var ipStr, gatewayStr, maskStr string + addr := prefix.Addr() + switch { + case addr.Is6(): + maskStr = fmt.Sprintf("%d", prefix.Bits()) + ipStr = fmt.Sprintf("[%s]", addr.String()) + if len(gateway) > 0 && gatewayIP.Is6() { + gatewayStr = gateway + } + case addr.Is4(): + maskStr, err = getSubnetMask(prefix) + if err != nil { + return "", err + } + if len(gateway) > 0 && gatewayIP.Is4() { + gatewayStr = gateway + } + ipStr = addr.String() + default: + return "", errors.New("IP address must adhere to IPv4 or IPv6 format") + } + outKargs += fmt.Sprintf("ip=%s::%s:%s:::none ", ipStr, gatewayStr, maskStr) + } + + for _, nameserver := range nameservers { + ip := net.ParseIP(nameserver) + if ip.To4() == nil { + nameserver = fmt.Sprintf("[%s]", nameserver) + } + outKargs += fmt.Sprintf("nameserver=%s ", nameserver) + } + + outKargs = strings.Trim(outKargs, " ") + logrus.Debugf("Generated karg: [%v].", outKargs) + return outKargs, nil +} diff --git a/vendor/github.com/dougm/pretty/.gitignore b/vendor/github.com/dougm/pretty/.gitignore new file mode 100644 index 00000000000..1f0a99f2f2b --- /dev/null +++ b/vendor/github.com/dougm/pretty/.gitignore @@ -0,0 +1,4 @@ +[568].out +_go* +_test* +_obj diff --git a/vendor/github.com/dougm/pretty/License b/vendor/github.com/dougm/pretty/License new file mode 100644 index 00000000000..05c783ccf68 --- /dev/null +++ b/vendor/github.com/dougm/pretty/License @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright 2012 Keith Rarick + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/dougm/pretty/Readme b/vendor/github.com/dougm/pretty/Readme new file mode 100644 index 00000000000..c589fc622b3 --- /dev/null +++ b/vendor/github.com/dougm/pretty/Readme @@ -0,0 +1,9 @@ +package pretty + + import "github.com/kr/pretty" + + Package pretty provides pretty-printing for Go values. + +Documentation + + http://godoc.org/github.com/kr/pretty diff --git a/vendor/github.com/dougm/pretty/diff.go b/vendor/github.com/dougm/pretty/diff.go new file mode 100644 index 00000000000..6aa7f743a28 --- /dev/null +++ b/vendor/github.com/dougm/pretty/diff.go @@ -0,0 +1,265 @@ +package pretty + +import ( + "fmt" + "io" + "reflect" +) + +type sbuf []string + +func (p *sbuf) Printf(format string, a ...interface{}) { + s := fmt.Sprintf(format, a...) + *p = append(*p, s) +} + +// Diff returns a slice where each element describes +// a difference between a and b. +func Diff(a, b interface{}) (desc []string) { + Pdiff((*sbuf)(&desc), a, b) + return desc +} + +// wprintfer calls Fprintf on w for each Printf call +// with a trailing newline. +type wprintfer struct{ w io.Writer } + +func (p *wprintfer) Printf(format string, a ...interface{}) { + fmt.Fprintf(p.w, format+"\n", a...) +} + +// Fdiff writes to w a description of the differences between a and b. +func Fdiff(w io.Writer, a, b interface{}) { + Pdiff(&wprintfer{w}, a, b) +} + +type Printfer interface { + Printf(format string, a ...interface{}) +} + +// Pdiff prints to p a description of the differences between a and b. +// It calls Printf once for each difference, with no trailing newline. +// The standard library log.Logger is a Printfer. +func Pdiff(p Printfer, a, b interface{}) { + diffPrinter{w: p}.diff(reflect.ValueOf(a), reflect.ValueOf(b)) +} + +type Logfer interface { + Logf(format string, a ...interface{}) +} + +// logprintfer calls Fprintf on w for each Printf call +// with a trailing newline. +type logprintfer struct{ l Logfer } + +func (p *logprintfer) Printf(format string, a ...interface{}) { + p.l.Logf(format, a...) +} + +// Ldiff prints to l a description of the differences between a and b. +// It calls Logf once for each difference, with no trailing newline. +// The standard library testing.T and testing.B are Logfers. +func Ldiff(l Logfer, a, b interface{}) { + Pdiff(&logprintfer{l}, a, b) +} + +type diffPrinter struct { + w Printfer + l string // label +} + +func (w diffPrinter) printf(f string, a ...interface{}) { + var l string + if w.l != "" { + l = w.l + ": " + } + w.w.Printf(l+f, a...) +} + +func (w diffPrinter) diff(av, bv reflect.Value) { + if !av.IsValid() && bv.IsValid() { + w.printf("nil != %# v", formatter{v: bv, quote: true}) + return + } + if av.IsValid() && !bv.IsValid() { + w.printf("%# v != nil", formatter{v: av, quote: true}) + return + } + if !av.IsValid() && !bv.IsValid() { + return + } + + at := av.Type() + bt := bv.Type() + if at != bt { + w.printf("%v != %v", at, bt) + return + } + + switch kind := at.Kind(); kind { + case reflect.Bool: + if a, b := av.Bool(), bv.Bool(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if a, b := av.Int(), bv.Int(); a != b { + w.printf("%d != %d", a, b) + } + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + if a, b := av.Uint(), bv.Uint(); a != b { + w.printf("%d != %d", a, b) + } + case reflect.Float32, reflect.Float64: + if a, b := av.Float(), bv.Float(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Complex64, reflect.Complex128: + if a, b := av.Complex(), bv.Complex(); a != b { + w.printf("%v != %v", a, b) + } + case reflect.Array: + n := av.Len() + for i := 0; i < n; i++ { + w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i)) + } + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + if a, b := av.Pointer(), bv.Pointer(); a != b { + w.printf("%#x != %#x", a, b) + } + case reflect.Interface: + w.diff(av.Elem(), bv.Elem()) + case reflect.Map: + ak, both, bk := keyDiff(av.MapKeys(), bv.MapKeys()) + for _, k := range ak { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.printf("%q != (missing)", av.MapIndex(k)) + } + for _, k := range both { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.diff(av.MapIndex(k), bv.MapIndex(k)) + } + for _, k := range bk { + w := w.relabel(fmt.Sprintf("[%#v]", k)) + w.printf("(missing) != %q", bv.MapIndex(k)) + } + case reflect.Ptr: + switch { + case av.IsNil() && !bv.IsNil(): + w.printf("nil != %# v", formatter{v: bv, quote: true}) + case !av.IsNil() && bv.IsNil(): + w.printf("%# v != nil", formatter{v: av, quote: true}) + case !av.IsNil() && !bv.IsNil(): + w.diff(av.Elem(), bv.Elem()) + } + case reflect.Slice: + lenA := av.Len() + lenB := bv.Len() + if lenA != lenB { + w.printf("%s[%d] != %s[%d]", av.Type(), lenA, bv.Type(), lenB) + break + } + for i := 0; i < lenA; i++ { + w.relabel(fmt.Sprintf("[%d]", i)).diff(av.Index(i), bv.Index(i)) + } + case reflect.String: + if a, b := av.String(), bv.String(); a != b { + w.printf("%q != %q", a, b) + } + case reflect.Struct: + for i := 0; i < av.NumField(); i++ { + w.relabel(at.Field(i).Name).diff(av.Field(i), bv.Field(i)) + } + default: + panic("unknown reflect Kind: " + kind.String()) + } +} + +func (d diffPrinter) relabel(name string) (d1 diffPrinter) { + d1 = d + if d.l != "" && name[0] != '[' { + d1.l += "." + } + d1.l += name + return d1 +} + +// keyEqual compares a and b for equality. +// Both a and b must be valid map keys. +func keyEqual(av, bv reflect.Value) bool { + if !av.IsValid() && !bv.IsValid() { + return true + } + if !av.IsValid() || !bv.IsValid() || av.Type() != bv.Type() { + return false + } + switch kind := av.Kind(); kind { + case reflect.Bool: + a, b := av.Bool(), bv.Bool() + return a == b + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + a, b := av.Int(), bv.Int() + return a == b + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + a, b := av.Uint(), bv.Uint() + return a == b + case reflect.Float32, reflect.Float64: + a, b := av.Float(), bv.Float() + return a == b + case reflect.Complex64, reflect.Complex128: + a, b := av.Complex(), bv.Complex() + return a == b + case reflect.Array: + for i := 0; i < av.Len(); i++ { + if !keyEqual(av.Index(i), bv.Index(i)) { + return false + } + } + return true + case reflect.Chan, reflect.UnsafePointer, reflect.Ptr: + a, b := av.Pointer(), bv.Pointer() + return a == b + case reflect.Interface: + return keyEqual(av.Elem(), bv.Elem()) + case reflect.String: + a, b := av.String(), bv.String() + return a == b + case reflect.Struct: + for i := 0; i < av.NumField(); i++ { + if !keyEqual(av.Field(i), bv.Field(i)) { + return false + } + } + return true + default: + panic("invalid map key type " + av.Type().String()) + } +} + +func keyDiff(a, b []reflect.Value) (ak, both, bk []reflect.Value) { + for _, av := range a { + inBoth := false + for _, bv := range b { + if keyEqual(av, bv) { + inBoth = true + both = append(both, av) + break + } + } + if !inBoth { + ak = append(ak, av) + } + } + for _, bv := range b { + inBoth := false + for _, av := range a { + if keyEqual(av, bv) { + inBoth = true + break + } + } + if !inBoth { + bk = append(bk, bv) + } + } + return +} diff --git a/vendor/github.com/dougm/pretty/formatter.go b/vendor/github.com/dougm/pretty/formatter.go new file mode 100644 index 00000000000..4941b0cf431 --- /dev/null +++ b/vendor/github.com/dougm/pretty/formatter.go @@ -0,0 +1,358 @@ +package pretty + +import ( + "fmt" + "io" + "reflect" + "strconv" + "text/tabwriter" + "time" + + "github.com/kr/text" +) + +var ( + timeType = reflect.TypeOf(time.Time{}) +) + +type formatter struct { + v reflect.Value + force bool + quote bool +} + +// Formatter makes a wrapper, f, that will format x as go source with line +// breaks and tabs. Object f responds to the "%v" formatting verb when both the +// "#" and " " (space) flags are set, for example: +// +// fmt.Sprintf("%# v", Formatter(x)) +// +// If one of these two flags is not set, or any other verb is used, f will +// format x according to the usual rules of package fmt. +// In particular, if x satisfies fmt.Formatter, then x.Format will be called. +func Formatter(x interface{}) (f fmt.Formatter) { + return formatter{v: reflect.ValueOf(x), quote: true} +} + +func (fo formatter) String() string { + return fmt.Sprint(fo.v.Interface()) // unwrap it +} + +func (fo formatter) passThrough(f fmt.State, c rune) { + s := "%" + for i := 0; i < 128; i++ { + if f.Flag(i) { + s += string(i) + } + } + if w, ok := f.Width(); ok { + s += fmt.Sprintf("%d", w) + } + if p, ok := f.Precision(); ok { + s += fmt.Sprintf(".%d", p) + } + s += string(c) + fmt.Fprintf(f, s, fo.v.Interface()) +} + +func (fo formatter) Format(f fmt.State, c rune) { + if fo.force || c == 'v' && f.Flag('#') && f.Flag(' ') { + w := tabwriter.NewWriter(f, 4, 4, 1, ' ', 0) + p := &printer{tw: w, Writer: w, visited: make(map[visit]int)} + p.printValue(fo.v, true, fo.quote) + w.Flush() + return + } + fo.passThrough(f, c) +} + +type printer struct { + io.Writer + tw *tabwriter.Writer + visited map[visit]int + depth int +} + +func (p *printer) indent() *printer { + q := *p + q.tw = tabwriter.NewWriter(p.Writer, 4, 4, 1, ' ', 0) + q.Writer = text.NewIndentWriter(q.tw, []byte{'\t'}) + return &q +} + +func (p *printer) printInline(v reflect.Value, x interface{}, showType bool) { + if showType { + io.WriteString(p, v.Type().String()) + fmt.Fprintf(p, "(%#v)", x) + } else { + fmt.Fprintf(p, "%#v", x) + } +} + +// printValue must keep track of already-printed pointer values to avoid +// infinite recursion. +type visit struct { + v uintptr + typ reflect.Type +} + +func (p *printer) printValue(v reflect.Value, showType, quote bool) { + if p.depth > 10 { + io.WriteString(p, "!%v(DEPTH EXCEEDED)") + return + } + + switch v.Kind() { + case reflect.Bool: + p.printInline(v, v.Bool(), showType) + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + p.printInline(v, v.Int(), showType) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + p.printInline(v, v.Uint(), showType) + case reflect.Float32, reflect.Float64: + p.printInline(v, v.Float(), showType) + case reflect.Complex64, reflect.Complex128: + fmt.Fprintf(p, "%#v", v.Complex()) + case reflect.String: + p.fmtString(v.String(), quote) + case reflect.Map: + t := v.Type() + if showType { + io.WriteString(p, t.String()) + } + writeByte(p, '{') + if nonzero(v) { + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + keys := v.MapKeys() + for i := 0; i < v.Len(); i++ { + showTypeInStruct := true + k := keys[i] + mv := v.MapIndex(k) + pp.printValue(k, false, true) + writeByte(pp, ':') + if expand { + writeByte(pp, '\t') + } + showTypeInStruct = t.Elem().Kind() == reflect.Interface + pp.printValue(mv, showTypeInStruct, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.Len()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + } + writeByte(p, '}') + case reflect.Struct: + t := v.Type() + if t == timeType { + io.WriteString(p, "time.Now()") + break + } + + if v.CanAddr() { + addr := v.UnsafeAddr() + vis := visit{addr, t} + if vd, ok := p.visited[vis]; ok && vd < p.depth { + p.fmtString(t.String()+"{(CYCLIC REFERENCE)}", false) + break // don't print v again + } + p.visited[vis] = p.depth + } + + if showType { + io.WriteString(p, t.String()) + } + writeByte(p, '{') + if nonzero(v) { + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + for i := 0; i < v.NumField(); i++ { + showTypeInStruct := true + if f := t.Field(i); f.Name != "" { + if f.Name == "DynamicData" { + continue + } + io.WriteString(pp, f.Name) + writeByte(pp, ':') + if expand { + writeByte(pp, '\t') + } + showTypeInStruct = labelType(f.Type) + } + pp.printValue(getField(v, i), showTypeInStruct, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.NumField()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + } + writeByte(p, '}') + case reflect.Interface: + switch e := v.Elem(); { + case e.Kind() == reflect.Invalid: + io.WriteString(p, "nil") + case e.IsValid(): + pp := *p + pp.depth++ + pp.printValue(e, showType, true) + default: + io.WriteString(p, v.Type().String()) + io.WriteString(p, "(nil)") + } + case reflect.Array, reflect.Slice: + t := v.Type() + if showType { + io.WriteString(p, t.String()) + } + if v.Kind() == reflect.Slice && v.IsNil() && showType { + io.WriteString(p, "(nil)") + break + } + if v.Kind() == reflect.Slice && v.IsNil() { + io.WriteString(p, "nil") + break + } + if !showType { + // we always want the type for slices + io.WriteString(p, t.String()) + } + writeByte(p, '{') + expand := !canInline(v.Type()) + pp := p + if expand { + writeByte(p, '\n') + pp = p.indent() + } + for i := 0; i < v.Len(); i++ { + showTypeInSlice := t.Elem().Kind() == reflect.Interface + pp.printValue(v.Index(i), showTypeInSlice, true) + if expand { + io.WriteString(pp, ",\n") + } else if i < v.Len()-1 { + io.WriteString(pp, ", ") + } + } + if expand { + pp.tw.Flush() + } + writeByte(p, '}') + case reflect.Ptr: + e := v.Elem() + if !e.IsValid() { + writeByte(p, '(') + io.WriteString(p, v.Type().String()) + io.WriteString(p, ")(nil)") + } else { + switch e.Kind() { + case reflect.Bool: + io.WriteString(p, fmt.Sprintf("types.NewBool(%v)", e.Bool())) + case reflect.Int32: + io.WriteString(p, fmt.Sprintf("types.NewInt32(%v)", e.Int())) + case reflect.Int64: + io.WriteString(p, fmt.Sprintf("types.NewInt64(%v)", e.Int())) + default: + if e.Kind() == reflect.Struct && e.Type() == timeType { + io.WriteString(p, "types.NewTime(time.Now())") + } else { + pp := *p + pp.depth++ + writeByte(pp, '&') + pp.printValue(e, true, true) + } + } + } + case reflect.Chan: + x := v.Pointer() + if showType { + writeByte(p, '(') + io.WriteString(p, v.Type().String()) + fmt.Fprintf(p, ")(%#v)", x) + } else { + fmt.Fprintf(p, "%#v", x) + } + case reflect.Func: + io.WriteString(p, v.Type().String()) + io.WriteString(p, " {...}") + case reflect.UnsafePointer: + p.printInline(v, v.Pointer(), showType) + case reflect.Invalid: + io.WriteString(p, "nil") + } +} + +func canInline(t reflect.Type) bool { + switch t.Kind() { + case reflect.Map: + return !canExpand(t.Elem()) + case reflect.Struct: + for i := 0; i < t.NumField(); i++ { + if canExpand(t.Field(i).Type) { + return false + } + } + return true + case reflect.Interface: + return false + case reflect.Array, reflect.Slice: + return !canExpand(t.Elem()) + case reflect.Ptr: + return false + case reflect.Chan, reflect.Func, reflect.UnsafePointer: + return false + } + return true +} + +func canExpand(t reflect.Type) bool { + switch t.Kind() { + case reflect.Map, reflect.Struct, + reflect.Interface, reflect.Array, reflect.Slice, + reflect.Ptr: + return true + } + return false +} + +func labelType(t reflect.Type) bool { + switch t.Kind() { + case reflect.Interface, reflect.Struct: + return true + } + return false +} + +func (p *printer) fmtString(s string, quote bool) { + if quote { + s = strconv.Quote(s) + } + io.WriteString(p, s) +} + +func writeByte(w io.Writer, b byte) { + w.Write([]byte{b}) +} + +func getField(v reflect.Value, i int) reflect.Value { + val := v.Field(i) + if val.Kind() == reflect.Interface && !val.IsNil() { + val = val.Elem() + } + return val +} diff --git a/vendor/github.com/dougm/pretty/pretty.go b/vendor/github.com/dougm/pretty/pretty.go new file mode 100644 index 00000000000..49423ec7f54 --- /dev/null +++ b/vendor/github.com/dougm/pretty/pretty.go @@ -0,0 +1,108 @@ +// Package pretty provides pretty-printing for Go values. This is +// useful during debugging, to avoid wrapping long output lines in +// the terminal. +// +// It provides a function, Formatter, that can be used with any +// function that accepts a format string. It also provides +// convenience wrappers for functions in packages fmt and log. +package pretty + +import ( + "fmt" + "io" + "log" + "reflect" +) + +// Errorf is a convenience wrapper for fmt.Errorf. +// +// Calling Errorf(f, x, y) is equivalent to +// fmt.Errorf(f, Formatter(x), Formatter(y)). +func Errorf(format string, a ...interface{}) error { + return fmt.Errorf(format, wrap(a, false)...) +} + +// Fprintf is a convenience wrapper for fmt.Fprintf. +// +// Calling Fprintf(w, f, x, y) is equivalent to +// fmt.Fprintf(w, f, Formatter(x), Formatter(y)). +func Fprintf(w io.Writer, format string, a ...interface{}) (n int, error error) { + return fmt.Fprintf(w, format, wrap(a, false)...) +} + +// Log is a convenience wrapper for log.Printf. +// +// Calling Log(x, y) is equivalent to +// log.Print(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Log(a ...interface{}) { + log.Print(wrap(a, true)...) +} + +// Logf is a convenience wrapper for log.Printf. +// +// Calling Logf(f, x, y) is equivalent to +// log.Printf(f, Formatter(x), Formatter(y)). +func Logf(format string, a ...interface{}) { + log.Printf(format, wrap(a, false)...) +} + +// Logln is a convenience wrapper for log.Printf. +// +// Calling Logln(x, y) is equivalent to +// log.Println(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Logln(a ...interface{}) { + log.Println(wrap(a, true)...) +} + +// Print pretty-prints its operands and writes to standard output. +// +// Calling Print(x, y) is equivalent to +// fmt.Print(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Print(a ...interface{}) (n int, errno error) { + return fmt.Print(wrap(a, true)...) +} + +// Printf is a convenience wrapper for fmt.Printf. +// +// Calling Printf(f, x, y) is equivalent to +// fmt.Printf(f, Formatter(x), Formatter(y)). +func Printf(format string, a ...interface{}) (n int, errno error) { + return fmt.Printf(format, wrap(a, false)...) +} + +// Println pretty-prints its operands and writes to standard output. +// +// Calling Print(x, y) is equivalent to +// fmt.Println(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Println(a ...interface{}) (n int, errno error) { + return fmt.Println(wrap(a, true)...) +} + +// Sprint is a convenience wrapper for fmt.Sprintf. +// +// Calling Sprint(x, y) is equivalent to +// fmt.Sprint(Formatter(x), Formatter(y)), but each operand is +// formatted with "%# v". +func Sprint(a ...interface{}) string { + return fmt.Sprint(wrap(a, true)...) +} + +// Sprintf is a convenience wrapper for fmt.Sprintf. +// +// Calling Sprintf(f, x, y) is equivalent to +// fmt.Sprintf(f, Formatter(x), Formatter(y)). +func Sprintf(format string, a ...interface{}) string { + return fmt.Sprintf(format, wrap(a, false)...) +} + +func wrap(a []interface{}, force bool) []interface{} { + w := make([]interface{}, len(a)) + for i, x := range a { + w[i] = formatter{v: reflect.ValueOf(x), force: force} + } + return w +} diff --git a/vendor/github.com/dougm/pretty/zero.go b/vendor/github.com/dougm/pretty/zero.go new file mode 100644 index 00000000000..abb5b6fc14c --- /dev/null +++ b/vendor/github.com/dougm/pretty/zero.go @@ -0,0 +1,41 @@ +package pretty + +import ( + "reflect" +) + +func nonzero(v reflect.Value) bool { + switch v.Kind() { + case reflect.Bool: + return v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() != 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() != 0 + case reflect.Float32, reflect.Float64: + return v.Float() != 0 + case reflect.Complex64, reflect.Complex128: + return v.Complex() != complex(0, 0) + case reflect.String: + return v.String() != "" + case reflect.Struct: + for i := 0; i < v.NumField(); i++ { + if nonzero(getField(v, i)) { + return true + } + } + return false + case reflect.Array: + for i := 0; i < v.Len(); i++ { + if nonzero(v.Index(i)) { + return true + } + } + return false + case reflect.Map, reflect.Interface, reflect.Slice, reflect.Ptr, reflect.Chan, reflect.Func: + return !v.IsNil() + case reflect.UnsafePointer: + return v.Pointer() != 0 + } + return true +} diff --git a/vendor/github.com/kr/text/License b/vendor/github.com/kr/text/License new file mode 100644 index 00000000000..480a3280599 --- /dev/null +++ b/vendor/github.com/kr/text/License @@ -0,0 +1,19 @@ +Copyright 2012 Keith Rarick + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/kr/text/Readme b/vendor/github.com/kr/text/Readme new file mode 100644 index 00000000000..7e6e7c0687b --- /dev/null +++ b/vendor/github.com/kr/text/Readme @@ -0,0 +1,3 @@ +This is a Go package for manipulating paragraphs of text. + +See http://go.pkgdoc.org/github.com/kr/text for full documentation. diff --git a/vendor/github.com/kr/text/doc.go b/vendor/github.com/kr/text/doc.go new file mode 100644 index 00000000000..cf4c198f955 --- /dev/null +++ b/vendor/github.com/kr/text/doc.go @@ -0,0 +1,3 @@ +// Package text provides rudimentary functions for manipulating text in +// paragraphs. +package text diff --git a/vendor/github.com/kr/text/indent.go b/vendor/github.com/kr/text/indent.go new file mode 100644 index 00000000000..4ebac45c092 --- /dev/null +++ b/vendor/github.com/kr/text/indent.go @@ -0,0 +1,74 @@ +package text + +import ( + "io" +) + +// Indent inserts prefix at the beginning of each non-empty line of s. The +// end-of-line marker is NL. +func Indent(s, prefix string) string { + return string(IndentBytes([]byte(s), []byte(prefix))) +} + +// IndentBytes inserts prefix at the beginning of each non-empty line of b. +// The end-of-line marker is NL. +func IndentBytes(b, prefix []byte) []byte { + var res []byte + bol := true + for _, c := range b { + if bol && c != '\n' { + res = append(res, prefix...) + } + res = append(res, c) + bol = c == '\n' + } + return res +} + +// Writer indents each line of its input. +type indentWriter struct { + w io.Writer + bol bool + pre [][]byte + sel int + off int +} + +// NewIndentWriter makes a new write filter that indents the input +// lines. Each line is prefixed in order with the corresponding +// element of pre. If there are more lines than elements, the last +// element of pre is repeated for each subsequent line. +func NewIndentWriter(w io.Writer, pre ...[]byte) io.Writer { + return &indentWriter{ + w: w, + pre: pre, + bol: true, + } +} + +// The only errors returned are from the underlying indentWriter. +func (w *indentWriter) Write(p []byte) (n int, err error) { + for _, c := range p { + if w.bol { + var i int + i, err = w.w.Write(w.pre[w.sel][w.off:]) + w.off += i + if err != nil { + return n, err + } + } + _, err = w.w.Write([]byte{c}) + if err != nil { + return n, err + } + n++ + w.bol = c == '\n' + if w.bol { + w.off = 0 + if w.sel < len(w.pre)-1 { + w.sel++ + } + } + } + return n, nil +} diff --git a/vendor/github.com/kr/text/wrap.go b/vendor/github.com/kr/text/wrap.go new file mode 100644 index 00000000000..b09bb03736d --- /dev/null +++ b/vendor/github.com/kr/text/wrap.go @@ -0,0 +1,86 @@ +package text + +import ( + "bytes" + "math" +) + +var ( + nl = []byte{'\n'} + sp = []byte{' '} +) + +const defaultPenalty = 1e5 + +// Wrap wraps s into a paragraph of lines of length lim, with minimal +// raggedness. +func Wrap(s string, lim int) string { + return string(WrapBytes([]byte(s), lim)) +} + +// WrapBytes wraps b into a paragraph of lines of length lim, with minimal +// raggedness. +func WrapBytes(b []byte, lim int) []byte { + words := bytes.Split(bytes.Replace(bytes.TrimSpace(b), nl, sp, -1), sp) + var lines [][]byte + for _, line := range WrapWords(words, 1, lim, defaultPenalty) { + lines = append(lines, bytes.Join(line, sp)) + } + return bytes.Join(lines, nl) +} + +// WrapWords is the low-level line-breaking algorithm, useful if you need more +// control over the details of the text wrapping process. For most uses, either +// Wrap or WrapBytes will be sufficient and more convenient. +// +// WrapWords splits a list of words into lines with minimal "raggedness", +// treating each byte as one unit, accounting for spc units between adjacent +// words on each line, and attempting to limit lines to lim units. Raggedness +// is the total error over all lines, where error is the square of the +// difference of the length of the line and lim. Too-long lines (which only +// happen when a single word is longer than lim units) have pen penalty units +// added to the error. +func WrapWords(words [][]byte, spc, lim, pen int) [][][]byte { + n := len(words) + + length := make([][]int, n) + for i := 0; i < n; i++ { + length[i] = make([]int, n) + length[i][i] = len(words[i]) + for j := i + 1; j < n; j++ { + length[i][j] = length[i][j-1] + spc + len(words[j]) + } + } + + nbrk := make([]int, n) + cost := make([]int, n) + for i := range cost { + cost[i] = math.MaxInt32 + } + for i := n - 1; i >= 0; i-- { + if length[i][n-1] <= lim || i == n-1 { + cost[i] = 0 + nbrk[i] = n + } else { + for j := i + 1; j < n; j++ { + d := lim - length[i][j-1] + c := d*d + cost[j] + if length[i][j-1] > lim { + c += pen // too-long lines get a worse penalty + } + if c < cost[i] { + cost[i] = c + nbrk[i] = j + } + } + } + } + + var lines [][][]byte + i := 0 + for i < n { + lines = append(lines, words[i:nbrk[i]]) + i = nbrk[i] + } + return lines +} diff --git a/vendor/github.com/vmware/govmomi/.golangci.yml b/vendor/github.com/vmware/govmomi/.golangci.yml index d6392fb9489..25242dcaf52 100644 --- a/vendor/github.com/vmware/govmomi/.golangci.yml +++ b/vendor/github.com/vmware/govmomi/.golangci.yml @@ -14,5 +14,6 @@ linters-settings: run: timeout: 6m skip-dirs: + - vim25/json - vim25/xml - cns/types diff --git a/vendor/github.com/vmware/govmomi/.goreleaser.yml b/vendor/github.com/vmware/govmomi/.goreleaser.yml index 69b80be383c..5da5cd64ef2 100644 --- a/vendor/github.com/vmware/govmomi/.goreleaser.yml +++ b/vendor/github.com/vmware/govmomi/.goreleaser.yml @@ -34,13 +34,12 @@ archives: - id: govcbuild builds: - govc - name_template: "govc_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - replacements: &replacements - darwin: Darwin - linux: Linux - windows: Windows - freebsd: FreeBSD - amd64: x86_64 + name_template: >- + govc_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} format_overrides: &overrides - goos: windows format: zip @@ -52,8 +51,12 @@ archives: - id: vcsimbuild builds: - vcsim - name_template: "vcsim_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}" - replacements: *replacements + name_template: >- + vcsim_ + {{- title .Os }}_ + {{- if eq .Arch "amd64" }}x86_64 + {{- else if eq .Arch "386" }}i386 + {{- else }}{{ .Arch }}{{ end }} format_overrides: *overrides files: *extrafiles @@ -77,7 +80,7 @@ brews: - name: govc ids: - govcbuild - tap: + repository: owner: govmomi name: homebrew-tap # TODO: create token in specified tap repo, add as secret to govmomi repo and reference in release workflow @@ -88,7 +91,7 @@ brews: name: Alfred the Narwhal email: cna-alfred@vmware.com folder: Formula - homepage: "https://github.com/vmware/govmomi/blob/master/govc/README.md" + homepage: "https://github.com/vmware/govmomi/blob/main/govc/README.md" description: "govc is a vSphere CLI built on top of govmomi." test: | system "#{bin}/govc version" @@ -97,7 +100,7 @@ brews: - name: vcsim ids: - vcsimbuild - tap: + repository: owner: govmomi name: homebrew-tap # TODO: create token in specified tap repo, add as secret to govmomi repo and reference in release workflow @@ -108,7 +111,7 @@ brews: name: Alfred the Narwhal email: cna-alfred@vmware.com folder: Formula - homepage: "https://github.com/vmware/govmomi/blob/master/vcsim/README.md" + homepage: "https://github.com/vmware/govmomi/blob/main/vcsim/README.md" description: "vcsim is a vSphere API simulator built on top of govmomi." test: | system "#{bin}/vcsim -h" diff --git a/vendor/github.com/vmware/govmomi/CHANGELOG.md b/vendor/github.com/vmware/govmomi/CHANGELOG.md index 974881f9892..f0e5da70d44 100644 --- a/vendor/github.com/vmware/govmomi/CHANGELOG.md +++ b/vendor/github.com/vmware/govmomi/CHANGELOG.md @@ -1,4 +1,112 @@ + +## [Release v0.30.0](https://github.com/vmware/govmomi/compare/v0.29.0...v0.30.0) + +> Release Date: 2022-12-12 + +### 🐞 Fix + +- [1ad33d48] Heal the broken Namespace API +- [22c48147] Update $mktemp to support macOS +- [05b0b08c] DialTLSContext / Go 1.18+ CertificateVerify support + +### 💫 API Changes + +- [58f4112b] Update types to vSphere 8.0 GA +- [ba206c5b] add Content Library security compliance support +- [4c24f821] Add SRIOV device names +- [642156dd] Adds vSphere 7.0u1-u3 support to namespace-management (Tanzu) + +### 💫 `govc` (CLI) + +- [60a18c56] about.cert was not respecting -k +- [15d1181d] bash completion improvements +- [0dbf717b] Add sso.lpp.info and sso.lpp.update commands +- [fe87cff9] host.info: use writer instead of os.stdout +- [a7196e41] host.info: use writer instead of os.stdout +- [3d6de9da] fix host.esxcli runtime error occurred when no arguments specified +- [8c7ba5ef] Add feature in sso.group.ls to list groups using FindGroupsInGroup method +- [dc3e1d79] Add feature sso.group.lsgroups using FindGroupsInGroup method +- [bf991e6e] add event key for json and plain text output +- [2017e846] Support creating content libraries with security policies + +### 💫 `vcsim` (Simulator) + +- [86f9d42a] Update test keys to be RSA 2048 +- [cedf695b] Fix duplicated name check in CloneVM_Task +- [8f4da558] add QueryNetworkHint support for LLDP and CDP details +- [1cab3254] Fix RetrieveProperties path validation to avoid panic +- [7f42a1d2] use node id for ServiceContent.InstanceUuid +- [03319493] Fix snapshot tasks to update rootSnapshot +- [b6ebcb6b] Fix disk capacity validation in ConfigureDevices +- [61032a23] Fix StorageIOAllocationInfo of VirtualDisk +- [cbfe0c93] support disconnect/reconnect host +- [b44828a4] Fix datastore freespace changed by ReconfigVM_Task + +### 📃 Documentation + +- [813a5d88] update `README.md` + +### 🧹 Chore + +- [eabc29ba] Update version.go for v0.30.0 + +### ⚠️ BREAKING + +### 📖 Commits + +- [eabc29ba] chore: Update version.go for v0.30.0 +- [1c919824] Update CONTRIBUTORS for release +- [1ad33d48] fix: Heal the broken Namespace API +- [22c48147] fix: Update $mktemp to support macOS +- [05b0b08c] fix: DialTLSContext / Go 1.18+ CertificateVerify support +- [86f9d42a] vcsim: Update test keys to be RSA 2048 +- [60a18c56] govc: about.cert was not respecting -k +- [58f4112b] api: Update types to vSphere 8.0 GA +- [15d1181d] govc: bash completion improvements +- [c018f078] perms on template files +- [813a5d88] docs: update `README.md` +- [0dbf717b] govc: Add sso.lpp.info and sso.lpp.update commands +- [fe87cff9] govc: host.info: use writer instead of os.stdout +- [a7196e41] govc: host.info: use writer instead of os.stdout +- [ba206c5b] api: add Content Library security compliance support +- [cedf695b] vcsim: Fix duplicated name check in CloneVM_Task +- [8f4da558] vcsim: add QueryNetworkHint support for LLDP and CDP details +- [3b2816ac] Add optional recommRequired PlaceVmsXCluster req arguments +- [f975908a] build(deps): bump andstor/file-existence-action from 1 to 2 +- [1373b80f] build(deps): bump chuhlomin/render-template from 1.5 to 1.6 +- [dc55a27e] build(deps): bump nokogiri from 1.13.6 to 1.13.9 in /gen +- [63980ff2] Fix: use latestPages in task HistoryCollector +- [3d6de9da] govc: fix host.esxcli runtime error occurred when no arguments specified +- [1e9eed94] Update list of projects using govmomi +- [7f4d115c] fixup! api: Add SRIOV device names +- [8f1dc575] Add API cnsreconfigpolicy bindings and static check fixes to cns/client_test.go +- [bf68e8f0] fixup! api: Add SRIOV device names +- [4c24f821] api: Add SRIOV device names +- [c1bb56db] Updated USAGE.md +- [aca677ad] build(deps): bump actions/stale from 5 to 6 +- [1cab3254] vcsim: Fix RetrieveProperties path validation to avoid panic +- [65a6f6bc] Address review comments +- [99d12605] correct new lines in group.ls +- [4d9f6e01] correct new lines in USAGE.md +- [e5bee862] move FindUsersInGroup to users.ls +- [8c7ba5ef] govc: Add feature in sso.group.ls to list groups using FindGroupsInGroup method +- [ee332ae7] Add new query selection parameters to be used for QueryAllVolume/QueryVolumeAsync API +- [dc3e1d79] govc: Add feature sso.group.lsgroups using FindGroupsInGroup method +- [201ae28f] Add common stub for hgfs for non-linux env +- [7f42a1d2] vcsim: use node id for ServiceContent.InstanceUuid +- [76e99b00] Boilerplate check requires a date range in the license. +- [bf991e6e] govc: add event key for json and plain text output +- [4a29caee] add OpenBSD build constraint +- [81bc76bc] toolbbox: add hgfs OpenBSD stub +- [03319493] vcsim: Fix snapshot tasks to update rootSnapshot +- [b6ebcb6b] vcsim: Fix disk capacity validation in ConfigureDevices +- [2017e846] govc: Support creating content libraries with security policies +- [642156dd] api: Adds vSphere 7.0u1-u3 support to namespace-management (Tanzu) +- [61032a23] vcsim: Fix StorageIOAllocationInfo of VirtualDisk +- [cbfe0c93] vcsim: support disconnect/reconnect host +- [b44828a4] vcsim: Fix datastore freespace changed by ReconfigVM_Task + ## [Release v0.29.0](https://github.com/vmware/govmomi/compare/v0.28.0...v0.29.0) diff --git a/vendor/github.com/vmware/govmomi/CONTRIBUTING.md b/vendor/github.com/vmware/govmomi/CONTRIBUTING.md index c6d69e54675..038e5321b76 100644 --- a/vendor/github.com/vmware/govmomi/CONTRIBUTING.md +++ b/vendor/github.com/vmware/govmomi/CONTRIBUTING.md @@ -41,7 +41,7 @@ and **supported prefixes**, e.g. `govc: `. ### Example 1 - Fix a Bug in `govmomi` ```bash -git checkout -b issue- vmware/master +git checkout -b issue- main git add git commit -m "fix: ..." -m "Closes: #" git push $USER issue- @@ -50,7 +50,7 @@ git push $USER issue- ### Example 2 - Add a new (non-breaking) API to `govmomi` ```bash -git checkout -b issue- vmware/master +git checkout -b issue- main git add git commit -m "Add API ..." -m "Closes: #" git push $USER issue- @@ -59,7 +59,7 @@ git push $USER issue- ### Example 3 - Add a Feature to `govc` ```bash -git checkout -b issue- vmware/master +git checkout -b issue- main git add git commit -m "govc: Add feature ..." -m "Closes: #" git push $USER issue- @@ -70,7 +70,7 @@ To register the new `govc` command package, add a blank `_` import to `govmomi/g ### Example 4 - Fix a Bug in `vcsim` ```bash -git checkout -b issue- vmware/master +git checkout -b issue- main git add git commit -m "vcsim: Fix ..." -m "Closes: #" git push $USER issue- @@ -87,7 +87,7 @@ Thus these details should be stated at the body of the commit message. Multi-line strings are supported. ```bash -git checkout -b issue- vmware/master +git checkout -b issue- main git add cat << EOF | git commit -F - Add ctx to funcXYZ @@ -103,13 +103,13 @@ git push $USER issue- ### Stay in sync with Upstream -When your branch gets out of sync with the vmware/master branch, use the +When your branch gets out of sync with the main branch, use the following to update (rebase): ```bash git checkout issue- git fetch -a -git rebase vmware/master +git rebase main git push --force-with-lease $USER issue- ``` @@ -139,7 +139,7 @@ Once the review is complete, squash and push your final commit(s): ```bash # squash all commits into one # --autosquash will automatically detect and merge fixup commits -git rebase -i --autosquash vmware/master +git rebase -i --autosquash main git push --force-with-lease $USER issue- ``` diff --git a/vendor/github.com/vmware/govmomi/CONTRIBUTORS b/vendor/github.com/vmware/govmomi/CONTRIBUTORS index ef8c56de8b2..406173b84cd 100644 --- a/vendor/github.com/vmware/govmomi/CONTRIBUTORS +++ b/vendor/github.com/vmware/govmomi/CONTRIBUTORS @@ -9,6 +9,7 @@ Adam Chalkley Adam Fowler Adam Shannon Akanksha Panse +akutz Al Biheiri Alessandro Cortiana Alex @@ -52,7 +53,6 @@ Brian Rak brian57860 Bruce Downs Bryan Venteicher -Cédric Blomart Cheng Cheng Chethan Venkatesh Choudhury Sarada Prasanna Nanda @@ -61,6 +61,7 @@ Christian Höltje Clint Greenwood cpiment CuiHaozhi +Cédric Blomart Dan Ilan Dan Norris Daniel Frederick Crisman @@ -104,6 +105,7 @@ Gavrie Philipson George Hicken Gerrit Renker gthombare +Hakan Halil HakanSunay Hasan Mahmood Haydon Ryan @@ -123,9 +125,9 @@ Jeremy Canady jeremy-clerc Jiatong Wang jingyizPensando -João Pereira Jonas Ausevicius Jorge Sevilla +João Pereira Julien PILLON Justin J. Novack kayrus @@ -140,6 +142,7 @@ Louie Jiang Luther Monson Madanagopal Arunachalam makelarisjr <8687447+makelarisjr@users.noreply.github.com> +Manuel Grandeit maplain Marc Carmier Marcus Tan @@ -164,6 +167,7 @@ Mike Schinkel Mincho Tonev mingwei Nicolas Lamirault +nikhaild <84156354+nikhaild@users.noreply.github.com> Nikhil Kathare Nikhil R Deshpande Nikolas Grottendieck @@ -226,6 +230,7 @@ Tjeu Kayim <15987676+TjeuKayim@users.noreply.github.com> Toomas Pelberg Trevor Dawe tshihad +Ueli Banholzer Uwe Bessle Vadim Egorov Vikram Krishnamurthy @@ -245,6 +250,7 @@ Yi Jiang yiyingy ykakarap Yogesh Sobale <6104071+ysobale@users.noreply.github.com> +Your Name Yue Yin Yun Zhou Yuya Kusakabe diff --git a/vendor/github.com/vmware/govmomi/Makefile b/vendor/github.com/vmware/govmomi/Makefile index 1a89322a324..0f31649af8b 100644 --- a/vendor/github.com/vmware/govmomi/Makefile +++ b/vendor/github.com/vmware/govmomi/Makefile @@ -58,7 +58,7 @@ lint-go: $(GOLANGCI_LINT) ## Lint codebase $(GOLANGCI_LINT) run -v $(GOLANGCI_LINT_FLAGS) .PHONY: lint-go-full -lint-go-full: GOLANGCI_LINT_FLAGS = --fast=false +lint-go-full: GOLANGCI_LINT_FLAGS = --fast=false --max-same-issues=200 lint-go-full: lint-go ## Run slower linters to detect possible issues .PHONY: fix @@ -107,6 +107,10 @@ doc: install doc: ## Generates govc USAGE.md ./govc/usage.sh > ./govc/USAGE.md +.PHONY: generate-types +generate-types: ## Generate the types + $(MAKE) -C ./gen/ $@ + ## -------------------------------------- ## Tests @@ -132,7 +136,7 @@ endif .PHONY: go-test go-test: ## Runs go unit tests with race detector enabled - GORACE=$(GORACE) $(GO) test \ + GORACE=$(GORACE) CGO_ENABLED=1 $(GO) test \ -count $(TEST_COUNT) \ -race \ -timeout $(TEST_TIMEOUT) \ @@ -143,16 +147,7 @@ go-test: ## Runs go unit tests with race detector enabled govc-test: install govc-test: ## Runs govc bats tests ./govc/test/images/update.sh - (cd govc/test && ./vendor/github.com/sstephenson/bats/libexec/bats -t .) - -.PHONY: govc-test-sso -govc-test-sso: install - ./govc/test/images/update.sh - (cd govc/test && SSO_BATS=1 ./vendor/github.com/sstephenson/bats/libexec/bats -t sso.bats) - -.PHONY: govc-test-sso-assert-cert -govc-test-sso-assert-cert: - SSO_BATS_ASSERT_CERT=1 $(MAKE) govc-test-sso + (cd govc/test && ./vendor/github.com/bats-core/bats-core/bin/bats -t .) .PHONY: test test: go-test govc-test ## Runs go-test and govc-test diff --git a/vendor/github.com/vmware/govmomi/README.md b/vendor/github.com/vmware/govmomi/README.md index 60a18d6e127..73975150c83 100644 --- a/vendor/github.com/vmware/govmomi/README.md +++ b/vendor/github.com/vmware/govmomi/README.md @@ -65,6 +65,7 @@ Refer to the [CHANGELOG][govmomi-changelog] for version to version changes. * [Kubernetes vSphere Cloud Provider][project-k8s-cloud-provider] * [Kubernetes Cluster API][project-k8s-cluster-api] * [OPS][project-nanovms-ops] +* [OpenTelemetry Collector Contrib][opentelemetry-collector-contrib] * [Packer Plugin for VMware vSphere][project-hashicorp-packer-plugin-vsphere] * [Rancher][project-rancher] * [Terraform Provider for VMware vSphere][project-hashicorp-terraform-provider-vsphere] @@ -102,6 +103,7 @@ Follows pyvmomi and rbvmomi: language prefix + the vSphere acronym "VM Object Ma [go-reference]: https://pkg.go.dev/github.com/vmware/govmomi [go-report-card]: https://goreportcard.com/report/github.com/vmware/govmomi [go-version]: https://github.com/vmware/govmomi +[opentelemetry-collector-contrib]: https://github.com/open-telemetry/opentelemetry-collector-contrib [project-docker-linuxKit]: https://github.com/linuxkit/linuxkit/tree/master/src/cmd/linuxkit [project-elastic-agent]: https://github.com/elastic/integrations/tree/main/packages/vsphere [project-gru]: https://github.com/dnaeon/gru diff --git a/vendor/github.com/vmware/govmomi/RELEASE.md b/vendor/github.com/vmware/govmomi/RELEASE.md index 1a12c0640bd..3c0965a8316 100644 --- a/vendor/github.com/vmware/govmomi/RELEASE.md +++ b/vendor/github.com/vmware/govmomi/RELEASE.md @@ -18,7 +18,7 @@ uses [`goreleaser`](http://goreleaser.com/) and automatically creates/pushes: - Docker images for `vmware/govc` and `vmware/vcsim` to Docker Hub - Source code -Starting with release tag `v0.29.0`, releases are not tagged on the `master` +Starting with release tag `v0.29.0`, releases are not tagged on the `main` branch anymore but a dedicated release branch, for example `release-0.29`. This process has already been followed for patch releases and back-ports. @@ -37,15 +37,15 @@ which can be done through the Github UI or `git` CLI. This guide describes the CLI process. -### Verify `master` branch is up to date with the remote +### Verify `main` branch is up to date with the remote ```console -git checkout master +git checkout main git fetch -avp -git diff master origin/master +git diff main origin/main # if your local and remote branches diverge run -git pull origin/master +git pull origin/main ``` > **Warning** @@ -57,7 +57,7 @@ git pull origin/master ### Create a release branch For new releases, create a release branch from the most recent commit in -`master`, e.g. `release-0.30`. +`main`, e.g. `release-0.30`. ```console export RELEASE_BRANCH=release-0.30 @@ -106,7 +106,7 @@ navigate to `Actions -> Workflows -> Release`. Click `Run Workflow` which opens a dropdown list. -Select the new/updated branch, e.g. `release-0.30`, i.e. **not** the `master` +Select the new/updated branch, e.g. `release-0.30`, i.e. **not** the `main` branch. Specify a semantic `tag` to associate with the release, e.g. `v0.30.0`. @@ -124,7 +124,7 @@ Click `Run Workflow` to kick off the workflow. After successful completion and if the newly created `tag` is the **latest** (semantic version sorted) tag in the repository, a PR is automatically opened -against the `master` branch to update the `CHANGELOG`. Please review and merge +against the `main` branch to update the `CHANGELOG`. Please review and merge accordingly. ## Creating a release before Version `v0.29.0` @@ -133,15 +133,15 @@ The release process before `v0.29.0` differs since it's based on manually creating and pushing tags. Here, on every new tag matching `v*` pushed to the repository a Github Action Release Workflow is executed. -### Verify `master` branch is up to date with the remote +### Verify `main` branch is up to date with the remote ```console -git checkout master +git checkout main git fetch -avp -git diff master origin/master +git diff main origin/main # if your local and remote branches diverge run -git pull origin/master +git pull origin/main ``` > **Warning** diff --git a/vendor/github.com/vmware/govmomi/USAGE.md b/vendor/github.com/vmware/govmomi/USAGE.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/vendor/github.com/vmware/govmomi/client.go b/vendor/github.com/vmware/govmomi/client.go index ad49fe6bf7d..5becedd489f 100644 --- a/vendor/github.com/vmware/govmomi/client.go +++ b/vendor/github.com/vmware/govmomi/client.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. +Copyright (c) 2014-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -19,7 +19,7 @@ This package is the root package of the govmomi library. The library is structured as follows: -Package vim25 +# Package vim25 The minimal usable functionality is available through the vim25 package. It contains subpackages that contain generated types, managed objects, and all @@ -30,25 +30,25 @@ The vim25 package itself contains a client structure that is passed around throughout the entire library. It abstracts a session and its immutable state. See the vim25 package for more information. -Package session +# Package session The session package contains an abstraction for the session manager that allows a user to login and logout. It also provides access to the current session (i.e. to determine if the user is in fact logged in) -Package object +# Package object The object package contains wrappers for a selection of managed objects. The constructors of these objects all take a *vim25.Client, which they pass along to derived objects, if applicable. -Package govc +# Package govc The govc package contains the govc CLI. The code in this tree is not intended to be used as a library. Any functionality that govc contains that _could_ be used as a library function but isn't, _should_ live in a root level package. -Other packages +# Other packages Other packages, such as "event", "guest", or "license", provide wrappers for the respective subsystems. They are typically not needed in normal workflows so diff --git a/vendor/github.com/vmware/govmomi/cns/.gitignore b/vendor/github.com/vmware/govmomi/cns/.gitignore new file mode 100644 index 00000000000..dc43ac9d6e2 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/cns/.gitignore @@ -0,0 +1 @@ +.soap/ \ No newline at end of file diff --git a/vendor/github.com/vmware/govmomi/cns/client.go b/vendor/github.com/vmware/govmomi/cns/client.go new file mode 100644 index 00000000000..a526ff46f93 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/cns/client.go @@ -0,0 +1,305 @@ +/* +Copyright (c) 2019 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cns + +import ( + "context" + + "github.com/vmware/govmomi/cns/methods" + cnstypes "github.com/vmware/govmomi/cns/types" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" + vimtypes "github.com/vmware/govmomi/vim25/types" +) + +// Namespace and Path constants +const ( + Namespace = "vsan" + Path = "/vsanHealth" +) + +const ( + ReleaseVSAN67u3 = "vSAN 6.7U3" + ReleaseVSAN70 = "7.0" + ReleaseVSAN70u1 = "vSAN 7.0U1" +) + +var ( + CnsVolumeManagerInstance = vimtypes.ManagedObjectReference{ + Type: "CnsVolumeManager", + Value: "cns-volume-manager", + } + CnsDebugManagerInstance = vimtypes.ManagedObjectReference{ + Type: "CnsDebugManager", + Value: "cns-debug-manager", + } +) + +type Client struct { + *soap.Client + + RoundTripper soap.RoundTripper + + vim25Client *vim25.Client +} + +// NewClient creates a new CNS client +func NewClient(ctx context.Context, c *vim25.Client) (*Client, error) { + sc := c.Client.NewServiceClient(Path, Namespace) + sc.Namespace = c.Namespace + sc.Version = c.Version + return &Client{sc, sc, c}, nil +} + +// RoundTrip dispatches to the RoundTripper field. +func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error { + return c.RoundTripper.RoundTrip(ctx, req, res) +} + +// CreateVolume calls the CNS create API. +func (c *Client) CreateVolume(ctx context.Context, createSpecList []cnstypes.CnsVolumeCreateSpec) (*object.Task, error) { + createSpecList = dropUnknownCreateSpecElements(c, createSpecList) + req := cnstypes.CnsCreateVolume{ + This: CnsVolumeManagerInstance, + CreateSpecs: createSpecList, + } + res, err := methods.CnsCreateVolume(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// UpdateVolumeMetadata calls the CNS CnsUpdateVolumeMetadata API with UpdateSpecs specified in the argument +func (c *Client) UpdateVolumeMetadata(ctx context.Context, updateSpecList []cnstypes.CnsVolumeMetadataUpdateSpec) (*object.Task, error) { + updateSpecList = dropUnknownVolumeMetadataUpdateSpecElements(c, updateSpecList) + req := cnstypes.CnsUpdateVolumeMetadata{ + This: CnsVolumeManagerInstance, + UpdateSpecs: updateSpecList, + } + res, err := methods.CnsUpdateVolumeMetadata(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// DeleteVolume calls the CNS delete API. +func (c *Client) DeleteVolume(ctx context.Context, volumeIDList []cnstypes.CnsVolumeId, deleteDisk bool) (*object.Task, error) { + req := cnstypes.CnsDeleteVolume{ + This: CnsVolumeManagerInstance, + VolumeIds: volumeIDList, + DeleteDisk: deleteDisk, + } + res, err := methods.CnsDeleteVolume(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// ExtendVolume calls the CNS Extend API. +func (c *Client) ExtendVolume(ctx context.Context, extendSpecList []cnstypes.CnsVolumeExtendSpec) (*object.Task, error) { + req := cnstypes.CnsExtendVolume{ + This: CnsVolumeManagerInstance, + ExtendSpecs: extendSpecList, + } + res, err := methods.CnsExtendVolume(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// AttachVolume calls the CNS Attach API. +func (c *Client) AttachVolume(ctx context.Context, attachSpecList []cnstypes.CnsVolumeAttachDetachSpec) (*object.Task, error) { + req := cnstypes.CnsAttachVolume{ + This: CnsVolumeManagerInstance, + AttachSpecs: attachSpecList, + } + res, err := methods.CnsAttachVolume(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// DetachVolume calls the CNS Detach API. +func (c *Client) DetachVolume(ctx context.Context, detachSpecList []cnstypes.CnsVolumeAttachDetachSpec) (*object.Task, error) { + req := cnstypes.CnsDetachVolume{ + This: CnsVolumeManagerInstance, + DetachSpecs: detachSpecList, + } + res, err := methods.CnsDetachVolume(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// QueryVolume calls the CNS QueryVolume API. +func (c *Client) QueryVolume(ctx context.Context, queryFilter cnstypes.CnsQueryFilter) (*cnstypes.CnsQueryResult, error) { + req := cnstypes.CnsQueryVolume{ + This: CnsVolumeManagerInstance, + Filter: queryFilter, + } + res, err := methods.CnsQueryVolume(ctx, c, &req) + if err != nil { + return nil, err + } + return &res.Returnval, nil +} + +// QueryVolumeInfo calls the CNS QueryVolumeInfo API and return a task, from which we can extract VolumeInfo +// containing VStorageObject +func (c *Client) QueryVolumeInfo(ctx context.Context, volumeIDList []cnstypes.CnsVolumeId) (*object.Task, error) { + req := cnstypes.CnsQueryVolumeInfo{ + This: CnsVolumeManagerInstance, + VolumeIds: volumeIDList, + } + res, err := methods.CnsQueryVolumeInfo(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// QueryAllVolume calls the CNS QueryAllVolume API. +func (c *Client) QueryAllVolume(ctx context.Context, queryFilter cnstypes.CnsQueryFilter, querySelection cnstypes.CnsQuerySelection) (*cnstypes.CnsQueryResult, error) { + req := cnstypes.CnsQueryAllVolume{ + This: CnsVolumeManagerInstance, + Filter: queryFilter, + Selection: querySelection, + } + res, err := methods.CnsQueryAllVolume(ctx, c, &req) + if err != nil { + return nil, err + } + return &res.Returnval, nil +} + +// QueryVolumeAsync calls the CNS QueryAsync API and return a task, from which we can extract CnsQueryResult +func (c *Client) QueryVolumeAsync(ctx context.Context, queryFilter cnstypes.CnsQueryFilter, querySelection *cnstypes.CnsQuerySelection) (*object.Task, error) { + req := cnstypes.CnsQueryAsync{ + This: CnsVolumeManagerInstance, + Filter: queryFilter, + Selection: querySelection, + } + res, err := methods.CnsQueryAsync(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// RelocateVolume calls the CNS Relocate API. +func (c *Client) RelocateVolume(ctx context.Context, relocateSpecs ...cnstypes.BaseCnsVolumeRelocateSpec) (*object.Task, error) { + req := cnstypes.CnsRelocateVolume{ + This: CnsVolumeManagerInstance, + RelocateSpecs: relocateSpecs, + } + res, err := methods.CnsRelocateVolume(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// ConfigureVolumeACLs calls the CNS Configure ACL API. +func (c *Client) ConfigureVolumeACLs(ctx context.Context, aclConfigSpecs ...cnstypes.CnsVolumeACLConfigureSpec) (*object.Task, error) { + req := cnstypes.CnsConfigureVolumeACLs{ + This: CnsVolumeManagerInstance, + ACLConfigSpecs: aclConfigSpecs, + } + res, err := methods.CnsConfigureVolumeACLs(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// CreateSnapshots calls the CNS CreateSnapshots API + +func (c *Client) CreateSnapshots(ctx context.Context, snapshotCreateSpecList []cnstypes.CnsSnapshotCreateSpec) (*object.Task, error) { + req := cnstypes.CnsCreateSnapshots{ + This: CnsVolumeManagerInstance, + SnapshotSpecs: snapshotCreateSpecList, + } + res, err := methods.CnsCreateSnapshots(ctx, c, &req) + if err != nil { + return nil, err + } + + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// DeleteSnapshots calls the CNS DeleteSnapshots API +func (c *Client) DeleteSnapshots(ctx context.Context, snapshotDeleteSpecList []cnstypes.CnsSnapshotDeleteSpec) (*object.Task, error) { + req := cnstypes.CnsDeleteSnapshots{ + This: CnsVolumeManagerInstance, + SnapshotDeleteSpecs: snapshotDeleteSpecList, + } + res, err := methods.CnsDeleteSnapshots(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// QuerySnapshots calls the CNS QuerySnapshots API +func (c *Client) QuerySnapshots(ctx context.Context, snapshotQueryFilter cnstypes.CnsSnapshotQueryFilter) (*object.Task, error) { + req := cnstypes.CnsQuerySnapshots{ + This: CnsVolumeManagerInstance, + SnapshotQueryFilter: snapshotQueryFilter, + } + res, err := methods.CnsQuerySnapshots(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// ReconfigVolumePolicy calls the CnsReconfigVolumePolicy API +func (c *Client) ReconfigVolumePolicy(ctx context.Context, PolicyReconfigSpecs []cnstypes.CnsVolumePolicyReconfigSpec) (*object.Task, error) { + req := cnstypes.CnsReconfigVolumePolicy{ + This: CnsVolumeManagerInstance, + VolumePolicyReconfigSpecs: PolicyReconfigSpecs, + } + res, err := methods.CnsReconfigVolumePolicy(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} + +// SyncDatastore calls the CnsSyncDatastore API +// Note: To be used only by VMware's internal support tools. +// This API triggers a manual sync of internal CNS and FCD DBs which otherwise happens periodially, +// with fullsync it forces synchronization of complete tables. +func (c *Client) SyncDatastore(ctx context.Context, dsURL string, fullSync bool) (*object.Task, error) { + req := cnstypes.CnsSyncDatastore{ + This: CnsDebugManagerInstance, + DatastoreUrl: dsURL, + FullSync: &fullSync, + } + res, err := methods.CnsSyncDatastore(ctx, c, &req) + if err != nil { + return nil, err + } + return object.NewTask(c.vim25Client, res.Returnval), nil +} diff --git a/vendor/github.com/vmware/govmomi/cns/cns_util.go b/vendor/github.com/vmware/govmomi/cns/cns_util.go new file mode 100644 index 00000000000..d8d8b09df21 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/cns/cns_util.go @@ -0,0 +1,180 @@ +/* +Copyright (c) 2019 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cns + +import ( + "context" + "errors" + + cnstypes "github.com/vmware/govmomi/cns/types" + "github.com/vmware/govmomi/object" + vim25types "github.com/vmware/govmomi/vim25/types" +) + +// GetTaskInfo gets the task info given a task +func GetTaskInfo(ctx context.Context, task *object.Task) (*vim25types.TaskInfo, error) { + taskInfo, err := task.WaitForResult(ctx, nil) + if err != nil { + return nil, err + } + return taskInfo, nil +} + +// GetQuerySnapshotsTaskResult gets the task result of QuerySnapshots given a task info +func GetQuerySnapshotsTaskResult(ctx context.Context, taskInfo *vim25types.TaskInfo) (*cnstypes.CnsSnapshotQueryResult, error) { + if taskInfo == nil { + return nil, errors.New("TaskInfo is empty") + } + if taskInfo.Result != nil { + snapshotQueryResult := taskInfo.Result.(cnstypes.CnsSnapshotQueryResult) + if &snapshotQueryResult == nil { + return nil, errors.New("Cannot get SnapshotQueryResult") + } + return &snapshotQueryResult, nil + } + return nil, errors.New("TaskInfo result is empty") +} + +// GetTaskResult gets the task result given a task info +func GetTaskResult(ctx context.Context, taskInfo *vim25types.TaskInfo) (cnstypes.BaseCnsVolumeOperationResult, error) { + if taskInfo == nil { + return nil, errors.New("TaskInfo is empty") + } + if taskInfo.Result != nil { + volumeOperationBatchResult := taskInfo.Result.(cnstypes.CnsVolumeOperationBatchResult) + if &volumeOperationBatchResult == nil || + volumeOperationBatchResult.VolumeResults == nil || + len(volumeOperationBatchResult.VolumeResults) == 0 { + return nil, errors.New("Cannot get VolumeOperationResult") + } + return volumeOperationBatchResult.VolumeResults[0], nil + } + return nil, errors.New("TaskInfo result is empty") +} + +// GetTaskResultArray gets the task result array for a specified task info +func GetTaskResultArray(ctx context.Context, taskInfo *vim25types.TaskInfo) ([]cnstypes.BaseCnsVolumeOperationResult, error) { + if taskInfo == nil { + return nil, errors.New("TaskInfo is empty") + } + if taskInfo.Result != nil { + volumeOperationBatchResult := taskInfo.Result.(cnstypes.CnsVolumeOperationBatchResult) + if &volumeOperationBatchResult == nil || + volumeOperationBatchResult.VolumeResults == nil || + len(volumeOperationBatchResult.VolumeResults) == 0 { + return nil, errors.New("Cannot get VolumeOperationResult") + } + return volumeOperationBatchResult.VolumeResults, nil + } + return nil, errors.New("TaskInfo result is empty") +} + +// dropUnknownCreateSpecElements helps drop newly added elements in the CnsVolumeCreateSpec, which are not known to the prior vSphere releases +func dropUnknownCreateSpecElements(c *Client, createSpecList []cnstypes.CnsVolumeCreateSpec) []cnstypes.CnsVolumeCreateSpec { + updatedcreateSpecList := make([]cnstypes.CnsVolumeCreateSpec, 0, len(createSpecList)) + switch c.Version { + case ReleaseVSAN67u3: + // Dropping optional fields not known to vSAN 6.7U3 + for _, createSpec := range createSpecList { + createSpec.Metadata.ContainerCluster.ClusterFlavor = "" + createSpec.Metadata.ContainerCluster.ClusterDistribution = "" + createSpec.Metadata.ContainerClusterArray = nil + var updatedEntityMetadata []cnstypes.BaseCnsEntityMetadata + for _, entityMetadata := range createSpec.Metadata.EntityMetadata { + k8sEntityMetadata := interface{}(entityMetadata).(*cnstypes.CnsKubernetesEntityMetadata) + k8sEntityMetadata.ClusterID = "" + k8sEntityMetadata.ReferredEntity = nil + updatedEntityMetadata = append(updatedEntityMetadata, cnstypes.BaseCnsEntityMetadata(k8sEntityMetadata)) + } + createSpec.Metadata.EntityMetadata = updatedEntityMetadata + _, ok := createSpec.BackingObjectDetails.(*cnstypes.CnsBlockBackingDetails) + if ok { + createSpec.BackingObjectDetails.(*cnstypes.CnsBlockBackingDetails).BackingDiskUrlPath = "" + } + updatedcreateSpecList = append(updatedcreateSpecList, createSpec) + } + createSpecList = updatedcreateSpecList + case ReleaseVSAN70: + // Dropping optional fields not known to vSAN 7.0 + for _, createSpec := range createSpecList { + createSpec.Metadata.ContainerCluster.ClusterDistribution = "" + var updatedContainerClusterArray []cnstypes.CnsContainerCluster + for _, containerCluster := range createSpec.Metadata.ContainerClusterArray { + containerCluster.ClusterDistribution = "" + updatedContainerClusterArray = append(updatedContainerClusterArray, containerCluster) + } + createSpec.Metadata.ContainerClusterArray = updatedContainerClusterArray + _, ok := createSpec.BackingObjectDetails.(*cnstypes.CnsBlockBackingDetails) + if ok { + createSpec.BackingObjectDetails.(*cnstypes.CnsBlockBackingDetails).BackingDiskUrlPath = "" + } + updatedcreateSpecList = append(updatedcreateSpecList, createSpec) + } + createSpecList = updatedcreateSpecList + case ReleaseVSAN70u1: + // Dropping optional fields not known to vSAN 7.0U1 + for _, createSpec := range createSpecList { + createSpec.Metadata.ContainerCluster.ClusterDistribution = "" + var updatedContainerClusterArray []cnstypes.CnsContainerCluster + for _, containerCluster := range createSpec.Metadata.ContainerClusterArray { + containerCluster.ClusterDistribution = "" + updatedContainerClusterArray = append(updatedContainerClusterArray, containerCluster) + } + createSpec.Metadata.ContainerClusterArray = updatedContainerClusterArray + updatedcreateSpecList = append(updatedcreateSpecList, createSpec) + } + createSpecList = updatedcreateSpecList + } + return createSpecList +} + +// dropUnknownVolumeMetadataUpdateSpecElements helps drop newly added elements in the CnsVolumeMetadataUpdateSpec, which are not known to the prior vSphere releases +func dropUnknownVolumeMetadataUpdateSpecElements(c *Client, updateSpecList []cnstypes.CnsVolumeMetadataUpdateSpec) []cnstypes.CnsVolumeMetadataUpdateSpec { + // Dropping optional fields not known to vSAN 6.7U3 + if c.Version == ReleaseVSAN67u3 { + updatedUpdateSpecList := make([]cnstypes.CnsVolumeMetadataUpdateSpec, 0, len(updateSpecList)) + for _, updateSpec := range updateSpecList { + updateSpec.Metadata.ContainerCluster.ClusterFlavor = "" + updateSpec.Metadata.ContainerCluster.ClusterDistribution = "" + var updatedEntityMetadata []cnstypes.BaseCnsEntityMetadata + for _, entityMetadata := range updateSpec.Metadata.EntityMetadata { + k8sEntityMetadata := interface{}(entityMetadata).(*cnstypes.CnsKubernetesEntityMetadata) + k8sEntityMetadata.ClusterID = "" + k8sEntityMetadata.ReferredEntity = nil + updatedEntityMetadata = append(updatedEntityMetadata, cnstypes.BaseCnsEntityMetadata(k8sEntityMetadata)) + } + updateSpec.Metadata.ContainerClusterArray = nil + updateSpec.Metadata.EntityMetadata = updatedEntityMetadata + updatedUpdateSpecList = append(updatedUpdateSpecList, updateSpec) + } + updateSpecList = updatedUpdateSpecList + } else if c.Version == ReleaseVSAN70 || c.Version == ReleaseVSAN70u1 { + updatedUpdateSpecList := make([]cnstypes.CnsVolumeMetadataUpdateSpec, 0, len(updateSpecList)) + for _, updateSpec := range updateSpecList { + updateSpec.Metadata.ContainerCluster.ClusterDistribution = "" + var updatedContainerClusterArray []cnstypes.CnsContainerCluster + for _, containerCluster := range updateSpec.Metadata.ContainerClusterArray { + containerCluster.ClusterDistribution = "" + updatedContainerClusterArray = append(updatedContainerClusterArray, containerCluster) + } + updateSpec.Metadata.ContainerClusterArray = updatedContainerClusterArray + updatedUpdateSpecList = append(updatedUpdateSpecList, updateSpec) + } + updateSpecList = updatedUpdateSpecList + } + return updateSpecList +} diff --git a/vendor/github.com/vmware/govmomi/cns/methods/methods.go b/vendor/github.com/vmware/govmomi/cns/methods/methods.go new file mode 100644 index 00000000000..da9318cac09 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/cns/methods/methods.go @@ -0,0 +1,369 @@ +/* +Copyright (c) 2019 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package methods + +import ( + "context" + + "github.com/vmware/govmomi/cns/types" + "github.com/vmware/govmomi/vim25/soap" +) + +type CnsCreateVolumeBody struct { + Req *types.CnsCreateVolume `xml:"urn:vsan CnsCreateVolume,omitempty"` + Res *types.CnsCreateVolumeResponse `xml:"urn:vsan CnsCreateVolumeResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsCreateVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsCreateVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsCreateVolume) (*types.CnsCreateVolumeResponse, error) { + var reqBody, resBody CnsCreateVolumeBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsUpdateVolumeBody struct { + Req *types.CnsUpdateVolumeMetadata `xml:"urn:vsan CnsUpdateVolumeMetadata,omitempty"` + Res *types.CnsUpdateVolumeMetadataResponse `xml:"urn:vsan CnsUpdateVolumeMetadataResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsUpdateVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsUpdateVolumeMetadata(ctx context.Context, r soap.RoundTripper, req *types.CnsUpdateVolumeMetadata) (*types.CnsUpdateVolumeMetadataResponse, error) { + var reqBody, resBody CnsUpdateVolumeBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsDeleteVolumeBody struct { + Req *types.CnsDeleteVolume `xml:"urn:vsan CnsDeleteVolume,omitempty"` + Res *types.CnsDeleteVolumeResponse `xml:"urn:vsan CnsDeleteVolumeResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsDeleteVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsDeleteVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsDeleteVolume) (*types.CnsDeleteVolumeResponse, error) { + var reqBody, resBody CnsDeleteVolumeBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsExtendVolumeBody struct { + Req *types.CnsExtendVolume `xml:"urn:vsan CnsExtendVolume,omitempty"` + Res *types.CnsExtendVolumeResponse `xml:"urn:vsan CnsExtendVolumeResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsExtendVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsExtendVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsExtendVolume) (*types.CnsExtendVolumeResponse, error) { + var reqBody, resBody CnsExtendVolumeBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsAttachVolumeBody struct { + Req *types.CnsAttachVolume `xml:"urn:vsan CnsAttachVolume,omitempty"` + Res *types.CnsAttachVolumeResponse `xml:"urn:vsan CnsAttachVolumeResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsAttachVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsAttachVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsAttachVolume) (*types.CnsAttachVolumeResponse, error) { + var reqBody, resBody CnsAttachVolumeBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsDetachVolumeBody struct { + Req *types.CnsDetachVolume `xml:"urn:vsan CnsDetachVolume,omitempty"` + Res *types.CnsDetachVolumeResponse `xml:"urn:vsan CnsDetachVolumeResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsDetachVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsDetachVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsDetachVolume) (*types.CnsDetachVolumeResponse, error) { + var reqBody, resBody CnsDetachVolumeBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsQueryVolumeBody struct { + Req *types.CnsQueryVolume `xml:"urn:vsan CnsQueryVolume,omitempty"` + Res *types.CnsQueryVolumeResponse `xml:"urn:vsan CnsQueryVolumeResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsQueryVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsQueryVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsQueryVolume) (*types.CnsQueryVolumeResponse, error) { + var reqBody, resBody CnsQueryVolumeBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsQueryVolumeInfoBody struct { + Req *types.CnsQueryVolumeInfo `xml:"urn:vsan CnsQueryVolumeInfo,omitempty"` + Res *types.CnsQueryVolumeInfoResponse `xml:"urn:vsan CnsQueryVolumeInfoResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsQueryVolumeInfoBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsQueryVolumeInfo(ctx context.Context, r soap.RoundTripper, req *types.CnsQueryVolumeInfo) (*types.CnsQueryVolumeInfoResponse, error) { + var reqBody, resBody CnsQueryVolumeInfoBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsQueryAllVolumeBody struct { + Req *types.CnsQueryAllVolume `xml:"urn:vsan CnsQueryAllVolume,omitempty"` + Res *types.CnsQueryAllVolumeResponse `xml:"urn:vsan CnsQueryAllVolumeResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsQueryAllVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsQueryAllVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsQueryAllVolume) (*types.CnsQueryAllVolumeResponse, error) { + var reqBody, resBody CnsQueryAllVolumeBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsRelocateVolumeBody struct { + Req *types.CnsRelocateVolume `xml:"urn:vsan CnsRelocateVolume,omitempty"` + Res *types.CnsRelocateVolumeResponse `xml:"urn:vsan CnsRelocateVolumeResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsRelocateVolumeBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsRelocateVolume(ctx context.Context, r soap.RoundTripper, req *types.CnsRelocateVolume) (*types.CnsRelocateVolumeResponse, error) { + var reqBody, resBody CnsRelocateVolumeBody + reqBody.Req = req + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsConfigureVolumeACLsBody struct { + Req *types.CnsConfigureVolumeACLs `xml:"urn:vsan CnsConfigureVolumeACLs,omitempty"` + Res *types.CnsConfigureVolumeACLsResponse `xml:"urn:vsan CnsConfigureVolumeACLsResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsConfigureVolumeACLsBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsConfigureVolumeACLs(ctx context.Context, r soap.RoundTripper, req *types.CnsConfigureVolumeACLs) (*types.CnsConfigureVolumeACLsResponse, error) { + var reqBody, resBody CnsConfigureVolumeACLsBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsQueryAsyncBody struct { + Req *types.CnsQueryAsync `xml:"urn:vsan CnsQueryAsync,omitempty"` + Res *types.CnsQueryAsyncResponse `xml:"urn:vsan CnsQueryAsyncResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsQueryAsyncBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsQueryAsync(ctx context.Context, r soap.RoundTripper, req *types.CnsQueryAsync) (*types.CnsQueryAsyncResponse, error) { + var reqBody, resBody CnsQueryAsyncBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +// CNS CreateSnapshots API + +type CnsCreateSnapshotsBody struct { + Req *types.CnsCreateSnapshots `xml:"urn:vsan CnsCreateSnapshots,omitempty"` + Res *types.CnsCreateSnapshotsResponse `xml:"urn:vsan CnsCreateSnapshotsResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsCreateSnapshotsBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsCreateSnapshots(ctx context.Context, r soap.RoundTripper, req *types.CnsCreateSnapshots) (*types.CnsCreateSnapshotsResponse, error) { + var reqBody, resBody CnsCreateSnapshotsBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +// CNS DeleteSnapshot API + +type CnsDeleteSnapshotBody struct { + Req *types.CnsDeleteSnapshots `xml:"urn:vsan CnsDeleteSnapshots,omitempty"` + Res *types.CnsDeleteSnapshotsResponse `xml:"urn:vsan CnsDeleteSnapshotsResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsDeleteSnapshotBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsDeleteSnapshots(ctx context.Context, r soap.RoundTripper, req *types.CnsDeleteSnapshots) (*types.CnsDeleteSnapshotsResponse, error) { + var reqBody, resBody CnsDeleteSnapshotBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +// CNS QuerySnapshots API + +type CnsQuerySnapshotsBody struct { + Req *types.CnsQuerySnapshots `xml:"urn:vsan CnsQuerySnapshots,omitempty"` + Res *types.CnsQuerySnapshotsResponse `xml:"urn:vsan CnsQuerySnapshotsResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsQuerySnapshotsBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsQuerySnapshots(ctx context.Context, r soap.RoundTripper, req *types.CnsQuerySnapshots) (*types.CnsQuerySnapshotsResponse, error) { + var reqBody, resBody CnsQuerySnapshotsBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsReconfigVolumePolicyBody struct { + Req *types.CnsReconfigVolumePolicy `xml:"urn:vsan CnsReconfigVolumePolicy,omitempty"` + Res *types.CnsReconfigVolumePolicyResponse `xml:"urn:vsan CnsReconfigVolumePolicyResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsReconfigVolumePolicyBody) Fault() *soap.Fault { return b.Fault_ } + +func CnsReconfigVolumePolicy(ctx context.Context, r soap.RoundTripper, req *types.CnsReconfigVolumePolicy) (*types.CnsReconfigVolumePolicyResponse, error) { + var reqBody, resBody CnsReconfigVolumePolicyBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} + +type CnsSyncDatastoreBody struct { + Req *types.CnsSyncDatastore `xml:"urn:vsan CnsSyncDatastore,omitempty"` + Res *types.CnsSyncDatastoreResponse `xml:"urn:vsan CnsSyncDatastoreResponse,omitempty"` + Fault_ *soap.Fault `xml:"http://schemas.xmlsoap.org/soap/envelope/ Fault,omitempty"` +} + +func (b *CnsSyncDatastoreBody) Fault() *soap.Fault { return b.Fault_ } + +// Note: To be used only by VMware's internal support tools. +func CnsSyncDatastore(ctx context.Context, r soap.RoundTripper, req *types.CnsSyncDatastore) (*types.CnsSyncDatastoreResponse, error) { + var reqBody, resBody CnsSyncDatastoreBody + + reqBody.Req = req + + if err := r.RoundTrip(ctx, &reqBody, &resBody); err != nil { + return nil, err + } + + return resBody.Res, nil +} diff --git a/vendor/github.com/vmware/govmomi/cns/types/enum.go b/vendor/github.com/vmware/govmomi/cns/types/enum.go new file mode 100644 index 00000000000..09186eea495 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/cns/types/enum.go @@ -0,0 +1,99 @@ +/* +Copyright (c) 2019 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +import ( + "reflect" + + "github.com/vmware/govmomi/vim25/types" +) + +type CnsVolumeType string + +const ( + CnsVolumeTypeBlock = CnsVolumeType("BLOCK") + CnsVolumeTypeFile = CnsVolumeType("FILE") +) + +func init() { + types.Add("CnsVolumeType", reflect.TypeOf((*CnsVolumeType)(nil)).Elem()) +} + +type CnsClusterFlavor string + +const ( + CnsClusterFlavorVanilla = CnsClusterFlavor("VANILLA") + CnsClusterFlavorWorkload = CnsClusterFlavor("WORKLOAD") + CnsClusterFlavorGuest = CnsClusterFlavor("GUEST_CLUSTER") + CnsClusterFlavorUnknown = CnsClusterFlavor("ClusterFlavor_Unknown") +) + +func init() { + types.Add("CnsClusterFlavor", reflect.TypeOf((*CnsClusterFlavor)(nil)).Elem()) +} + +type QuerySelectionNameType string + +const ( + QuerySelectionNameTypeVolumeType = QuerySelectionNameType("VOLUME_TYPE") + QuerySelectionNameTypeVolumeName = QuerySelectionNameType("VOLUME_NAME") + QuerySelectionNameTypeBackingObjectDetails = QuerySelectionNameType("BACKING_OBJECT_DETAILS") + QuerySelectionNameTypeComplianceStatus = QuerySelectionNameType("COMPLIANCE_STATUS") + QuerySelectionNameTypeDataStoreAccessibility = QuerySelectionNameType("DATASTORE_ACCESSIBILITY_STATUS") + QuerySelectionNameTypeHealthStatus = QuerySelectionNameType("HEALTH_STATUS") + QuerySelectionNameTypeDataStoreUrl = QuerySelectionNameType("DATASTORE_URL") + QuerySelectionNameTypePolicyId = QuerySelectionNameType("POLICY_ID") +) + +func init() { + types.Add("QuerySelectionNameType", reflect.TypeOf((*QuerySelectionNameType)(nil)).Elem()) +} + +type CnsClusterType string + +const ( + CnsClusterTypeKubernetes = CnsClusterType("KUBERNETES") +) + +func init() { + types.Add("CnsClusterType", reflect.TypeOf((*CnsClusterType)(nil)).Elem()) +} + +type CnsKubernetesEntityType string + +const ( + CnsKubernetesEntityTypePVC = CnsKubernetesEntityType("PERSISTENT_VOLUME_CLAIM") + CnsKubernetesEntityTypePV = CnsKubernetesEntityType("PERSISTENT_VOLUME") + CnsKubernetesEntityTypePOD = CnsKubernetesEntityType("POD") +) + +type CnsQuerySelectionNameType string + +const ( + CnsQuerySelectionName_VOLUME_NAME = CnsQuerySelectionNameType("VOLUME_NAME") + CnsQuerySelectionName_VOLUME_TYPE = CnsQuerySelectionNameType("VOLUME_TYPE") + CnsQuerySelectionName_BACKING_OBJECT_DETAILS = CnsQuerySelectionNameType("BACKING_OBJECT_DETAILS") + CnsQuerySelectionName_COMPLIANCE_STATUS = CnsQuerySelectionNameType("COMPLIANCE_STATUS") + CnsQuerySelectionName_DATASTORE_ACCESSIBILITY_STATUS = CnsQuerySelectionNameType("DATASTORE_ACCESSIBILITY_STATUS") + CnsQuerySelectionName_HEALTH_STATUS = CnsQuerySelectionNameType("HEALTH_STATUS") + CnsQuerySelectionName_DATASTORE_URL = CnsQuerySelectionNameType("DATASTORE_URL") + CnsQuerySelectionName_POLICY_ID = CnsQuerySelectionNameType("POLICY_ID") +) + +func init() { + types.Add("CnsKubernetesEntityType", reflect.TypeOf((*CnsKubernetesEntityType)(nil)).Elem()) +} diff --git a/vendor/github.com/vmware/govmomi/cns/types/if.go b/vendor/github.com/vmware/govmomi/cns/types/if.go new file mode 100644 index 00000000000..42a70ec73f3 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/cns/types/if.go @@ -0,0 +1,117 @@ +/* +Copyright (c) 2019 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +import ( + "reflect" + + "github.com/vmware/govmomi/vim25/types" +) + +func (b *CnsFault) GetCnsFault() *CnsFault { + return b +} + +type BaseCnsFault interface { + GetCnsFault() *CnsFault +} + +func init() { + types.Add("BaseCnsFault", reflect.TypeOf((*CnsFault)(nil)).Elem()) +} + +func (b *CnsAlreadyRegisteredFault) GetCnsAlreadyRegisteredFault() *CnsAlreadyRegisteredFault { + return b +} + +type BaseCnsAlreadyRegisteredFault interface { + GetCnsAlreadyRegisteredFault() *CnsAlreadyRegisteredFault +} + +func init() { + types.Add("BaseCnsAlreadyRegisteredFault", reflect.TypeOf((*CnsAlreadyRegisteredFault)(nil)).Elem()) +} + +func (b *CnsBackingObjectDetails) GetCnsBackingObjectDetails() *CnsBackingObjectDetails { return b } + +type BaseCnsBackingObjectDetails interface { + GetCnsBackingObjectDetails() *CnsBackingObjectDetails +} + +func init() { + types.Add("BaseCnsBackingObjectDetails", reflect.TypeOf((*CnsBackingObjectDetails)(nil)).Elem()) +} + +func (b *CnsBaseCreateSpec) GetCnsBaseCreateSpec() *CnsBaseCreateSpec { return b } + +type BaseCnsBaseCreateSpec interface { + GetCnsBaseCreateSpec() *CnsBaseCreateSpec +} + +func init() { + types.Add("BaseCnsBaseCreateSpec", reflect.TypeOf((*CnsBaseCreateSpec)(nil)).Elem()) +} + +type BaseCnsVolumeRelocateSpec interface { + GetCnsVolumeRelocateSpec() CnsVolumeRelocateSpec +} + +func (s CnsVolumeRelocateSpec) GetCnsVolumeRelocateSpec() CnsVolumeRelocateSpec { return s } + +func init() { + types.Add("BaseCnsVolumeRelocateSpec", reflect.TypeOf((*CnsVolumeRelocateSpec)(nil)).Elem()) +} + +func (b *CnsEntityMetadata) GetCnsEntityMetadata() *CnsEntityMetadata { return b } + +type BaseCnsEntityMetadata interface { + GetCnsEntityMetadata() *CnsEntityMetadata +} + +func init() { + types.Add("BaseCnsEntityMetadata", reflect.TypeOf((*CnsEntityMetadata)(nil)).Elem()) +} + +func (b *CnsVolumeInfo) GetCnsVolumeInfo() *CnsVolumeInfo { return b } + +type BaseCnsVolumeInfo interface { + GetCnsVolumeInfo() *CnsVolumeInfo +} + +func init() { + types.Add("BaseCnsVolumeInfo", reflect.TypeOf((*CnsVolumeInfo)(nil)).Elem()) +} + +func (b *CnsVolumeOperationResult) GetCnsVolumeOperationResult() *CnsVolumeOperationResult { return b } + +type BaseCnsVolumeOperationResult interface { + GetCnsVolumeOperationResult() *CnsVolumeOperationResult +} + +func init() { + types.Add("BaseCnsVolumeOperationResult", reflect.TypeOf((*CnsVolumeOperationResult)(nil)).Elem()) +} + +func (b *CnsVolumeSource) GetCnsVolumeSource() *CnsVolumeSource { return b } + +type BaseCnsVolumeSource interface { + GetCnsVolumeSource() *CnsVolumeSource +} + +func init() { + types.Add("BaseCnsVolumeSource", reflect.TypeOf((*CnsVolumeSource)(nil)).Elem()) +} diff --git a/vendor/github.com/vmware/govmomi/cns/types/types.go b/vendor/github.com/vmware/govmomi/cns/types/types.go new file mode 100644 index 00000000000..d493e99c599 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/cns/types/types.go @@ -0,0 +1,931 @@ +/* +Copyright (c) 2019 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package types + +import ( + "reflect" + "time" + + "github.com/vmware/govmomi/vim25/types" + vsanfstypes "github.com/vmware/govmomi/vsan/vsanfs/types" +) + +type CnsCreateVolumeRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + CreateSpecs []CnsVolumeCreateSpec `xml:"createSpecs,omitempty"` +} + +func init() { + types.Add("CnsCreateVolumeRequestType", reflect.TypeOf((*CnsCreateVolumeRequestType)(nil)).Elem()) +} + +type CnsCreateVolume CnsCreateVolumeRequestType + +func init() { + types.Add("CnsCreateVolume", reflect.TypeOf((*CnsCreateVolume)(nil)).Elem()) +} + +type CnsCreateVolumeResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsEntityMetadata struct { + types.DynamicData + + EntityName string `xml:"entityName"` + Labels []types.KeyValue `xml:"labels,omitempty"` + Delete bool `xml:"delete,omitempty"` + ClusterID string `xml:"clusterId,omitempty"` +} + +func init() { + types.Add("CnsEntityMetadata", reflect.TypeOf((*CnsEntityMetadata)(nil)).Elem()) +} + +type CnsKubernetesEntityReference struct { + EntityType string `xml:"entityType"` + EntityName string `xml:"entityName"` + Namespace string `xml:"namespace,omitempty"` + ClusterID string `xml:"clusterId,omitempty"` +} + +type CnsKubernetesEntityMetadata struct { + CnsEntityMetadata + + EntityType string `xml:"entityType"` + Namespace string `xml:"namespace,omitempty"` + ReferredEntity []CnsKubernetesEntityReference `xml:"referredEntity,omitempty"` +} + +func init() { + types.Add("CnsKubernetesEntityMetadata", reflect.TypeOf((*CnsKubernetesEntityMetadata)(nil)).Elem()) +} + +type CnsVolumeMetadata struct { + types.DynamicData + + ContainerCluster CnsContainerCluster `xml:"containerCluster"` + EntityMetadata []BaseCnsEntityMetadata `xml:"entityMetadata,typeattr,omitempty"` + ContainerClusterArray []CnsContainerCluster `xml:"containerClusterArray,omitempty"` +} + +func init() { + types.Add("CnsVolumeMetadata", reflect.TypeOf((*CnsVolumeMetadata)(nil)).Elem()) +} + +type CnsVolumeCreateSpec struct { + types.DynamicData + Name string `xml:"name"` + VolumeType string `xml:"volumeType"` + Datastores []types.ManagedObjectReference `xml:"datastores,omitempty"` + Metadata CnsVolumeMetadata `xml:"metadata,omitempty"` + BackingObjectDetails BaseCnsBackingObjectDetails `xml:"backingObjectDetails,typeattr"` + Profile []types.BaseVirtualMachineProfileSpec `xml:"profile,omitempty,typeattr"` + CreateSpec BaseCnsBaseCreateSpec `xml:"createSpec,omitempty,typeattr"` + VolumeSource BaseCnsVolumeSource `xml:"volumeSource,omitempty,typeattr"` +} + +func init() { + types.Add("CnsVolumeCreateSpec", reflect.TypeOf((*CnsVolumeCreateSpec)(nil)).Elem()) +} + +type CnsUpdateVolumeMetadataRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + UpdateSpecs []CnsVolumeMetadataUpdateSpec `xml:"updateSpecs,omitempty"` +} + +func init() { + types.Add("CnsUpdateVolumeMetadataRequestType", reflect.TypeOf((*CnsUpdateVolumeMetadataRequestType)(nil)).Elem()) +} + +type CnsUpdateVolumeMetadata CnsUpdateVolumeMetadataRequestType + +func init() { + types.Add("CnsUpdateVolumeMetadata", reflect.TypeOf((*CnsUpdateVolumeMetadata)(nil)).Elem()) +} + +type CnsUpdateVolumeMetadataResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsVolumeMetadataUpdateSpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + Metadata CnsVolumeMetadata `xml:"metadata,omitempty"` +} + +func init() { + types.Add("CnsVolumeMetadataUpdateSpec", reflect.TypeOf((*CnsVolumeMetadataUpdateSpec)(nil)).Elem()) +} + +type CnsDeleteVolumeRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + VolumeIds []CnsVolumeId `xml:"volumeIds"` + DeleteDisk bool `xml:"deleteDisk"` +} + +func init() { + types.Add("CnsDeleteVolumeRequestType", reflect.TypeOf((*CnsDeleteVolumeRequestType)(nil)).Elem()) +} + +type CnsDeleteVolume CnsDeleteVolumeRequestType + +func init() { + types.Add("CnsDeleteVolume", reflect.TypeOf((*CnsDeleteVolume)(nil)).Elem()) +} + +type CnsDeleteVolumeResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsExtendVolumeRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + ExtendSpecs []CnsVolumeExtendSpec `xml:"extendSpecs,omitempty"` +} + +func init() { + types.Add("CnsExtendVolumeRequestType", reflect.TypeOf((*CnsExtendVolumeRequestType)(nil)).Elem()) +} + +type CnsExtendVolume CnsExtendVolumeRequestType + +func init() { + types.Add("CnsExtendVolume", reflect.TypeOf((*CnsExtendVolume)(nil)).Elem()) +} + +type CnsExtendVolumeResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsVolumeExtendSpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + CapacityInMb int64 `xml:"capacityInMb"` +} + +func init() { + types.Add("CnsVolumeExtendSpec", reflect.TypeOf((*CnsVolumeExtendSpec)(nil)).Elem()) +} + +type CnsAttachVolumeRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + AttachSpecs []CnsVolumeAttachDetachSpec `xml:"attachSpecs,omitempty"` +} + +func init() { + types.Add("CnsAttachVolumeRequestType", reflect.TypeOf((*CnsAttachVolumeRequestType)(nil)).Elem()) +} + +type CnsAttachVolume CnsAttachVolumeRequestType + +func init() { + types.Add("CnsAttachVolume", reflect.TypeOf((*CnsAttachVolume)(nil)).Elem()) +} + +type CnsAttachVolumeResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsDetachVolumeRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + DetachSpecs []CnsVolumeAttachDetachSpec `xml:"detachSpecs,omitempty"` +} + +func init() { + types.Add("CnsDetachVolumeRequestType", reflect.TypeOf((*CnsDetachVolumeRequestType)(nil)).Elem()) +} + +type CnsDetachVolume CnsDetachVolumeRequestType + +func init() { + types.Add("CnsDetachVolume", reflect.TypeOf((*CnsDetachVolume)(nil)).Elem()) +} + +type CnsDetachVolumeResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsVolumeAttachDetachSpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + Vm types.ManagedObjectReference `xml:"vm"` +} + +func init() { + types.Add("CnsVolumeAttachDetachSpec", reflect.TypeOf((*CnsVolumeAttachDetachSpec)(nil)).Elem()) +} + +type CnsQueryVolume CnsQueryVolumeRequestType + +func init() { + types.Add("CnsQueryVolume", reflect.TypeOf((*CnsQueryVolume)(nil)).Elem()) +} + +type CnsQueryVolumeRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + Filter CnsQueryFilter `xml:"filter"` +} + +func init() { + types.Add("CnsQueryVolumeRequestType", reflect.TypeOf((*CnsQueryVolumeRequestType)(nil)).Elem()) +} + +type CnsQueryVolumeResponse struct { + Returnval CnsQueryResult `xml:"returnval"` +} + +type CnsQueryVolumeInfo CnsQueryVolumeInfoRequestType + +func init() { + types.Add("CnsQueryVolumeInfo", reflect.TypeOf((*CnsQueryVolumeInfo)(nil)).Elem()) +} + +type CnsQueryVolumeInfoRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + VolumeIds []CnsVolumeId `xml:"volumes"` +} + +type CnsQueryVolumeInfoResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsQueryAllVolume CnsQueryAllVolumeRequestType + +func init() { + types.Add("CnsQueryAllVolume", reflect.TypeOf((*CnsQueryAllVolume)(nil)).Elem()) +} + +type CnsQueryAllVolumeRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + Filter CnsQueryFilter `xml:"filter"` + Selection CnsQuerySelection `xml:"selection"` +} + +func init() { + types.Add("CnsQueryAllVolumeRequestType", reflect.TypeOf((*CnsQueryVolumeRequestType)(nil)).Elem()) +} + +type CnsQueryAllVolumeResponse struct { + Returnval CnsQueryResult `xml:"returnval"` +} + +type CnsContainerCluster struct { + types.DynamicData + + ClusterType string `xml:"clusterType"` + ClusterId string `xml:"clusterId"` + VSphereUser string `xml:"vSphereUser"` + ClusterFlavor string `xml:"clusterFlavor,omitempty"` + ClusterDistribution string `xml:"clusterDistribution,omitempty"` +} + +func init() { + types.Add("CnsContainerCluster", reflect.TypeOf((*CnsContainerCluster)(nil)).Elem()) +} + +type CnsVolume struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + DatastoreUrl string `xml:"datastoreUrl,omitempty"` + Name string `xml:"name,omitempty"` + VolumeType string `xml:"volumeType,omitempty"` + StoragePolicyId string `xml:"storagePolicyId,omitempty"` + Metadata CnsVolumeMetadata `xml:"metadata,omitempty"` + BackingObjectDetails BaseCnsBackingObjectDetails `xml:"backingObjectDetails,omitempty"` + ComplianceStatus string `xml:"complianceStatus,omitempty"` + DatastoreAccessibilityStatus string `xml:"datastoreAccessibilityStatus,omitempty"` + HealthStatus string `xml:"healthStatus,omitempty"` +} + +func init() { + types.Add("CnsVolume", reflect.TypeOf((*CnsVolume)(nil)).Elem()) +} + +type CnsVolumeOperationResult struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId,omitempty"` + Fault *types.LocalizedMethodFault `xml:"fault,omitempty"` +} + +func init() { + types.Add("CnsVolumeOperationResult", reflect.TypeOf((*CnsVolumeOperationResult)(nil)).Elem()) +} + +type CnsVolumeOperationBatchResult struct { + types.DynamicData + + VolumeResults []BaseCnsVolumeOperationResult `xml:"volumeResults,omitempty,typeattr"` +} + +func init() { + types.Add("CnsVolumeOperationBatchResult", reflect.TypeOf((*CnsVolumeOperationBatchResult)(nil)).Elem()) +} + +type CnsPlacementResult struct { + Datastore types.ManagedObjectReference `xml:"datastore,omitempty"` + PlacementFaults []*types.LocalizedMethodFault `xml:"placementFaults,omitempty"` +} + +func init() { + types.Add("CnsPlacementResult", reflect.TypeOf((*CnsPlacementResult)(nil)).Elem()) +} + +type CnsVolumeCreateResult struct { + CnsVolumeOperationResult + Name string `xml:"name,omitempty"` + PlacementResults []CnsPlacementResult `xml:"placementResults,omitempty"` +} + +func init() { + types.Add("CnsVolumeCreateResult", reflect.TypeOf((*CnsVolumeCreateResult)(nil)).Elem()) +} + +type CnsVolumeAttachResult struct { + CnsVolumeOperationResult + + DiskUUID string `xml:"diskUUID,omitempty"` +} + +func init() { + types.Add("CnsVolumeAttachResult", reflect.TypeOf((*CnsVolumeAttachResult)(nil)).Elem()) +} + +type CnsVolumeId struct { + types.DynamicData + + Id string `xml:"id"` +} + +func init() { + types.Add("CnsVolumeId", reflect.TypeOf((*CnsVolumeId)(nil)).Elem()) +} + +type CnsBackingObjectDetails struct { + types.DynamicData + + CapacityInMb int64 `xml:"capacityInMb,omitempty"` +} + +func init() { + types.Add("CnsBackingObjectDetails", reflect.TypeOf((*CnsBackingObjectDetails)(nil)).Elem()) +} + +type CnsBlockBackingDetails struct { + CnsBackingObjectDetails + + BackingDiskId string `xml:"backingDiskId,omitempty"` + BackingDiskUrlPath string `xml:"backingDiskUrlPath,omitempty"` + BackingDiskObjectId string `xml:"backingDiskObjectId,omitempty"` +} + +func init() { + types.Add("CnsBlockBackingDetails", reflect.TypeOf((*CnsBlockBackingDetails)(nil)).Elem()) +} + +type CnsFileBackingDetails struct { + CnsBackingObjectDetails + + BackingFileId string `xml:"backingFileId,omitempty"` +} + +func init() { + types.Add("CnsFileBackingDetails", reflect.TypeOf((*CnsFileBackingDetails)(nil)).Elem()) +} + +type CnsVsanFileShareBackingDetails struct { + CnsFileBackingDetails + + Name string `xml:"name,omitempty"` + AccessPoints []types.KeyValue `xml:"accessPoints,omitempty"` +} + +func init() { + types.Add("CnsVsanFileShareBackingDetails", reflect.TypeOf((*CnsVsanFileShareBackingDetails)(nil)).Elem()) +} + +type CnsBaseCreateSpec struct { + types.DynamicData +} + +func init() { + types.Add("CnsBaseCreateSpec", reflect.TypeOf((*CnsBaseCreateSpec)(nil)).Elem()) +} + +type CnsFileCreateSpec struct { + CnsBaseCreateSpec +} + +func init() { + types.Add("CnsFileCreateSpec", reflect.TypeOf((*CnsFileCreateSpec)(nil)).Elem()) +} + +type CnsVSANFileCreateSpec struct { + CnsFileCreateSpec + SoftQuotaInMb int64 `xml:"softQuotaInMb,omitempty"` + Permission []vsanfstypes.VsanFileShareNetPermission `xml:"permission,omitempty,typeattr"` +} + +func init() { + types.Add("CnsVSANFileCreateSpec", reflect.TypeOf((*CnsVSANFileCreateSpec)(nil)).Elem()) +} + +type CnsQueryFilter struct { + types.DynamicData + + VolumeIds []CnsVolumeId `xml:"volumeIds,omitempty"` + Names []string `xml:"names,omitempty"` + ContainerClusterIds []string `xml:"containerClusterIds,omitempty"` + StoragePolicyId string `xml:"storagePolicyId,omitempty"` + Datastores []types.ManagedObjectReference `xml:"datastores,omitempty"` + Labels []types.KeyValue `xml:"labels,omitempty"` + ComplianceStatus string `xml:"complianceStatus,omitempty"` + DatastoreAccessibilityStatus string `xml:"datastoreAccessibilityStatus,omitempty"` + Cursor *CnsCursor `xml:"cursor,omitempty"` + HealthStatus string `xml:"healthStatus,omitempty"` +} + +func init() { + types.Add("CnsQueryFilter", reflect.TypeOf((*CnsQueryFilter)(nil)).Elem()) +} + +type CnsQuerySelection struct { + types.DynamicData + + Names []string `xml:"names,omitempty"` +} + +type CnsQueryResult struct { + types.DynamicData + + Volumes []CnsVolume `xml:"volumes,omitempty"` + Cursor CnsCursor `xml:"cursor"` +} + +func init() { + types.Add("CnsQueryResult", reflect.TypeOf((*CnsQueryResult)(nil)).Elem()) +} + +type CnsVolumeInfo struct { + types.DynamicData +} + +func init() { + types.Add("CnsVolumeInfo", reflect.TypeOf((*CnsVolumeInfo)(nil)).Elem()) +} + +type CnsBlockVolumeInfo struct { + CnsVolumeInfo + + VStorageObject types.VStorageObject `xml:"vStorageObject"` +} + +func init() { + types.Add("CnsBlockVolumeInfo", reflect.TypeOf((*CnsBlockVolumeInfo)(nil)).Elem()) +} + +type CnsQueryVolumeInfoResult struct { + CnsVolumeOperationResult + + VolumeInfo BaseCnsVolumeInfo `xml:"volumeInfo,typeattr,omitempty"` +} + +func init() { + types.Add("CnsQueryVolumeInfoResult", reflect.TypeOf((*CnsQueryVolumeInfoResult)(nil)).Elem()) +} + +type CnsRelocateVolumeRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + RelocateSpecs []BaseCnsVolumeRelocateSpec `xml:"relocateSpecs,typeattr"` +} + +func init() { + types.Add("CnsRelocateVolumeRequestType", reflect.TypeOf((*CnsRelocateVolumeRequestType)(nil)).Elem()) +} + +type CnsRelocateVolume CnsRelocateVolumeRequestType + +func init() { + types.Add("CnsRelocateVolume", reflect.TypeOf((*CnsRelocateVolume)(nil)).Elem()) +} + +type CnsRelocateVolumeResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsVolumeRelocateSpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + Datastore types.ManagedObjectReference `xml:"datastore"` + Profile []types.BaseVirtualMachineProfileSpec `xml:"profile,omitempty,typeattr"` +} + +func init() { + types.Add("CnsVolumeRelocateSpec", reflect.TypeOf((*CnsVolumeRelocateSpec)(nil)).Elem()) +} + +type CnsBlockVolumeRelocateSpec struct { + CnsVolumeRelocateSpec +} + +func NewCnsBlockVolumeRelocateSpec(volumeId string, datastore types.ManagedObjectReference, profile ...types.BaseVirtualMachineProfileSpec) CnsBlockVolumeRelocateSpec { + cnsVolumeID := CnsVolumeId{ + Id: volumeId, + } + volumeSpec := CnsVolumeRelocateSpec{ + VolumeId: cnsVolumeID, + Datastore: datastore, + Profile: profile, + } + blockVolSpec := CnsBlockVolumeRelocateSpec{ + CnsVolumeRelocateSpec: volumeSpec, + } + return blockVolSpec +} + +func init() { + types.Add("CnsBlockVolumeRelocateSpec", reflect.TypeOf((*CnsBlockVolumeRelocateSpec)(nil)).Elem()) +} + +type CnsCursor struct { + types.DynamicData + + Offset int64 `xml:"offset"` + Limit int64 `xml:"limit"` + TotalRecords int64 `xml:"totalRecords,omitempty"` +} + +func init() { + types.Add("CnsCursor", reflect.TypeOf((*CnsCursor)(nil)).Elem()) +} + +type CnsFault struct { + types.BaseMethodFault `xml:"fault,typeattr"` + + Reason string `xml:"reason,omitempty"` +} + +func init() { + types.Add("CnsFault", reflect.TypeOf((*CnsFault)(nil)).Elem()) +} + +type CnsVolumeNotFoundFault struct { + CnsFault + + VolumeId CnsVolumeId `xml:"volumeId"` +} + +func init() { + types.Add("CnsVolumeNotFoundFault", reflect.TypeOf((*CnsVolumeNotFoundFault)(nil)).Elem()) +} + +type CnsAlreadyRegisteredFault struct { + CnsFault `xml:"fault,typeattr"` + + VolumeId CnsVolumeId `xml:"volumeId,omitempty"` +} + +func init() { + types.Add("CnsAlreadyRegisteredFault", reflect.TypeOf((*CnsAlreadyRegisteredFault)(nil)).Elem()) +} + +type CnsSnapshotNotFoundFault struct { + CnsFault + + VolumeId CnsVolumeId `xml:"volumeId,omitempty"` + SnapshotId CnsSnapshotId `xml:"snapshotId"` +} + +func init() { + types.Add("CnsSnapshotNotFoundFault", reflect.TypeOf((*CnsSnapshotNotFoundFault)(nil)).Elem()) +} + +type CnsConfigureVolumeACLs CnsConfigureVolumeACLsRequestType + +func init() { + types.Add("vsan:CnsConfigureVolumeACLs", reflect.TypeOf((*CnsConfigureVolumeACLs)(nil)).Elem()) +} + +type CnsConfigureVolumeACLsRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + ACLConfigSpecs []CnsVolumeACLConfigureSpec `xml:"ACLConfigSpecs"` +} + +func init() { + types.Add("vsan:CnsConfigureVolumeACLsRequestType", reflect.TypeOf((*CnsConfigureVolumeACLsRequestType)(nil)).Elem()) +} + +type CnsConfigureVolumeACLsResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsVolumeACLConfigureSpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + AccessControlSpecList []CnsNFSAccessControlSpec `xml:"accessControlSpecList,typeattr"` +} + +type CnsNFSAccessControlSpec struct { + types.DynamicData + Permission []vsanfstypes.VsanFileShareNetPermission `xml:"netPermission,omitempty,typeattr"` + Delete bool `xml:"delete,omitempty"` +} + +func init() { + types.Add("CnsNFSAccessControlSpec", reflect.TypeOf((*CnsNFSAccessControlSpec)(nil)).Elem()) +} + +type CnsQueryAsync CnsQueryAsyncRequestType + +func init() { + types.Add("CnsQueryAsync", reflect.TypeOf((*CnsQueryAsync)(nil)).Elem()) +} + +type CnsQueryAsyncRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + Filter CnsQueryFilter `xml:"filter"` + Selection *CnsQuerySelection `xml:"selection,omitempty"` +} + +func init() { + types.Add("CnsQueryAsyncRequestType", reflect.TypeOf((*CnsQueryAsyncRequestType)(nil)).Elem()) +} + +type CnsQueryAsyncResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsAsyncQueryResult struct { + CnsVolumeOperationResult + + QueryResult CnsQueryResult `xml:"queryResult,omitempty"` +} + +func init() { + types.Add("CnsAsyncQueryResult", reflect.TypeOf((*CnsAsyncQueryResult)(nil)).Elem()) +} + +// Cns Snapshot Types + +type CnsCreateSnapshotsRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + SnapshotSpecs []CnsSnapshotCreateSpec `xml:"snapshotSpecs,omitempty"` +} + +func init() { + types.Add("CnsCreateSnapshotsRequestType", reflect.TypeOf((*CnsCreateSnapshotsRequestType)(nil)).Elem()) +} + +type CnsCreateSnapshots CnsCreateSnapshotsRequestType + +func init() { + types.Add("CnsCreateSnapshots", reflect.TypeOf((*CnsCreateSnapshots)(nil)).Elem()) +} + +type CnsCreateSnapshotsResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsSnapshotCreateSpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + Description string `xml:"description"` +} + +func init() { + types.Add("CnsSnapshotCreateSpec", reflect.TypeOf((*CnsSnapshotCreateSpec)(nil)).Elem()) +} + +type CnsDeleteSnapshotsRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + SnapshotDeleteSpecs []CnsSnapshotDeleteSpec `xml:"snapshotDeleteSpecs,omitempty"` +} + +func init() { + types.Add("CnsDeleteSnapshotsRequestType", reflect.TypeOf((*CnsDeleteSnapshotsRequestType)(nil)).Elem()) +} + +type CnsDeleteSnapshots CnsDeleteSnapshotsRequestType + +func init() { + types.Add("CnsDeleteSnapshots", reflect.TypeOf((*CnsDeleteSnapshots)(nil)).Elem()) +} + +type CnsDeleteSnapshotsResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsSnapshotId struct { + types.DynamicData + + Id string `xml:"id"` +} + +func init() { + types.Add("CnsSnapshotId", reflect.TypeOf((*CnsSnapshotId)(nil)).Elem()) +} + +type CnsSnapshotDeleteSpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + SnapshotId CnsSnapshotId `xml:"snapshotId"` +} + +func init() { + types.Add("CnsSnapshotDeleteSpec", reflect.TypeOf((*CnsSnapshotDeleteSpec)(nil)).Elem()) +} + +type CnsSnapshot struct { + types.DynamicData + + SnapshotId CnsSnapshotId `xml:"snapshotId"` + VolumeId CnsVolumeId `xml:"volumeId"` + Description string `xml:"description,omitempty"` + CreateTime time.Time `xml:"createTime"` +} + +func init() { + types.Add("CnsSnapshot", reflect.TypeOf((*CnsSnapshot)(nil)).Elem()) +} + +type CnsSnapshotOperationResult struct { + CnsVolumeOperationResult +} + +func init() { + types.Add("CnsSnapshotOperationResult", reflect.TypeOf((*CnsSnapshotOperationResult)(nil)).Elem()) +} + +type CnsSnapshotCreateResult struct { + CnsSnapshotOperationResult + Snapshot CnsSnapshot `xml:"snapshot,omitempty"` +} + +func init() { + types.Add("CnsSnapshotCreateResult", reflect.TypeOf((*CnsSnapshotCreateResult)(nil)).Elem()) +} + +type CnsSnapshotDeleteResult struct { + CnsSnapshotOperationResult + SnapshotId CnsSnapshotId `xml:"snapshotId,omitempty"` +} + +func init() { + types.Add("CnsSnapshotDeleteResult", reflect.TypeOf((*CnsSnapshotDeleteResult)(nil)).Elem()) +} + +type CnsVolumeSource struct { + types.DynamicData +} + +func init() { + types.Add("CnsVolumeSource", reflect.TypeOf((*CnsVolumeSource)(nil)).Elem()) +} + +type CnsSnapshotVolumeSource struct { + CnsVolumeSource + + VolumeId CnsVolumeId `xml:"volumeId,omitempty"` + SnapshotId CnsSnapshotId `xml:"snapshotId,omitempty"` +} + +func init() { + types.Add("CnsSnapshotVolumeSource", reflect.TypeOf((*CnsSnapshotVolumeSource)(nil)).Elem()) +} + +// CNS QuerySnapshots related types + +type CnsQuerySnapshotsRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + SnapshotQueryFilter CnsSnapshotQueryFilter `xml:"snapshotQueryFilter"` +} + +func init() { + types.Add("CnsQuerySnapshotsRequestType", reflect.TypeOf((*CnsQuerySnapshotsRequestType)(nil)).Elem()) +} + +type CnsQuerySnapshots CnsQuerySnapshotsRequestType + +func init() { + types.Add("CnsQuerySnapshots", reflect.TypeOf((*CnsQuerySnapshots)(nil)).Elem()) +} + +type CnsQuerySnapshotsResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsSnapshotQueryResult struct { + types.DynamicData + + Entries []CnsSnapshotQueryResultEntry `xml:"entries,omitempty"` + Cursor CnsCursor `xml:"cursor"` +} + +func init() { + types.Add("CnsSnapshotQueryResult", reflect.TypeOf((*CnsSnapshotQueryResult)(nil)).Elem()) +} + +type CnsSnapshotQueryResultEntry struct { + types.DynamicData + + Snapshot CnsSnapshot `xml:"snapshot,omitempty"` + Error *types.LocalizedMethodFault `xml:"error,omitempty"` +} + +func init() { + types.Add("CnsSnapshotQueryResultEntry", reflect.TypeOf((*CnsSnapshotQueryResultEntry)(nil)).Elem()) +} + +type CnsSnapshotQueryFilter struct { + types.DynamicData + + SnapshotQuerySpecs []CnsSnapshotQuerySpec `xml:"snapshotQuerySpecs,omitempty"` + Cursor *CnsCursor `xml:"cursor,omitempty"` +} + +func init() { + types.Add("CnsSnapshotQueryFilter", reflect.TypeOf((*CnsSnapshotQueryFilter)(nil)).Elem()) +} + +type CnsSnapshotQuerySpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + SnapshotId *CnsSnapshotId `xml:"snapshotId,omitempty"` +} + +func init() { + types.Add("CnsSnapshotQuerySpec", reflect.TypeOf((*CnsSnapshotQuerySpec)(nil)).Elem()) +} + +type CnsReconfigVolumePolicy CnsReconfigVolumePolicyRequestType + +func init() { + types.Add("vsan:CnsReconfigVolumePolicy", reflect.TypeOf((*CnsReconfigVolumePolicy)(nil)).Elem()) +} + +type CnsReconfigVolumePolicyRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + VolumePolicyReconfigSpecs []CnsVolumePolicyReconfigSpec `xml:"volumePolicyReconfigSpecs,omitempty"` +} + +func init() { + types.Add("vsan:CnsReconfigVolumePolicyRequestType", reflect.TypeOf((*CnsReconfigVolumePolicyRequestType)(nil)).Elem()) +} + +type CnsReconfigVolumePolicyResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} + +type CnsVolumePolicyReconfigSpec struct { + types.DynamicData + + VolumeId CnsVolumeId `xml:"volumeId"` + Profile []types.BaseVirtualMachineProfileSpec `xml:"profile,omitempty,typeattr"` +} + +func init() { + types.Add("vsan:CnsVolumePolicyReconfigSpec", reflect.TypeOf((*CnsVolumePolicyReconfigSpec)(nil)).Elem()) +} + +type CnsSyncDatastore CnsSyncDatastoreRequestType + +func init() { + types.Add("vsan:CnsSyncDatastore", reflect.TypeOf((*CnsSyncDatastore)(nil)).Elem()) +} + +type CnsSyncDatastoreRequestType struct { + This types.ManagedObjectReference `xml:"_this"` + DatastoreUrl string `xml:"datastoreUrl,omitempty"` + FullSync *bool `xml:"fullSync"` +} + +func init() { + types.Add("vsan:CnsSyncDatastoreRequestType", reflect.TypeOf((*CnsSyncDatastoreRequestType)(nil)).Elem()) +} + +type CnsSyncDatastoreResponse struct { + Returnval types.ManagedObjectReference `xml:"returnval"` +} diff --git a/vendor/github.com/vmware/govmomi/find/doc.go b/vendor/github.com/vmware/govmomi/find/doc.go index 0c8acee0163..d22e883534a 100644 --- a/vendor/github.com/vmware/govmomi/find/doc.go +++ b/vendor/github.com/vmware/govmomi/find/doc.go @@ -32,6 +32,6 @@ otherwise "find" mode is used. The exception is to use a "..." wildcard with a path to find all objects recursively underneath any root object. For example: VirtualMachineList("/DC1/...") -See also: https://github.com/vmware/govmomi/blob/master/govc/README.md#usage +See also: https://github.com/vmware/govmomi/blob/main/govc/README.md#usage */ package find diff --git a/vendor/github.com/vmware/govmomi/govc/cli/command.go b/vendor/github.com/vmware/govmomi/govc/cli/command.go new file mode 100644 index 00000000000..ef468c6221a --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/cli/command.go @@ -0,0 +1,249 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cli + +import ( + "context" + "flag" + "fmt" + "io" + "os" + "path/filepath" + "sort" + "strings" + "text/tabwriter" + + "github.com/vmware/govmomi/vim25/types" +) + +type HasFlags interface { + // Register may be called more than once and should be idempotent. + Register(ctx context.Context, f *flag.FlagSet) + + // Process may be called more than once and should be idempotent. + Process(ctx context.Context) error +} + +type Command interface { + HasFlags + + Run(ctx context.Context, f *flag.FlagSet) error +} + +func generalHelp(w io.Writer, filter string) { + var cmds, matches []string + for name := range commands { + cmds = append(cmds, name) + + if filter != "" && strings.Contains(name, filter) { + matches = append(matches, name) + } + } + + if len(matches) == 0 { + fmt.Fprintf(w, `Usage: %[1]s [COMMON OPTIONS] [PATH]... + +govmomi is a Go library for interacting with VMware vSphere APIs (ESXi and/or +vCenter Server). +It is licensed under the Apache License, Version 2.0 + +%[1]s is the CLI for govmomi. + +The available commands are listed below. A detailed description of each +command can be displayed with "govc -h". The description of all +commands can be also found at https://via.vmw.com/GJ98hk . + +Examples: + show usage of a command: govc -h + show toplevel structure: govc ls + show datacenter summary: govc datacenter.info + show all VMs: govc find -type m + upload a ISO file: govc datastore.upload -ds datastore1 ./config.iso vm-name/config.iso + +Common options: + -h Show this message + -cert= Certificate [GOVC_CERTIFICATE] + -debug=false Store debug logs [GOVC_DEBUG] + -trace=false Write SOAP/REST traffic to stderr + -verbose=false Write request/response data to stderr + -dump=false Enable output dump + -json=false Enable JSON output + -xml=false Enable XML output + -k=false Skip verification of server certificate [GOVC_INSECURE] + -key= Private key [GOVC_PRIVATE_KEY] + -persist-session=true Persist session to disk [GOVC_PERSIST_SESSION] + -tls-ca-certs= TLS CA certificates file [GOVC_TLS_CA_CERTS] + -tls-known-hosts= TLS known hosts file [GOVC_TLS_KNOWN_HOSTS] + -u= ESX or vCenter URL [GOVC_URL] + -vim-namespace=urn:vim25 Vim namespace [GOVC_VIM_NAMESPACE] + -vim-version=6.0 Vim version [GOVC_VIM_VERSION] + -dc= Datacenter [GOVC_DATACENTER] + -host.dns= Find host by FQDN + -host.ip= Find host by IP address + -host.ipath= Find host by inventory path + -host.uuid= Find host by UUID + -vm.dns= Find VM by FQDN + -vm.ip= Find VM by IP address + -vm.ipath= Find VM by inventory path + -vm.path= Find VM by path to .vmx file + -vm.uuid= Find VM by UUID + +Available commands: +`, filepath.Base(os.Args[0])) + + } else { + fmt.Fprintf(w, "%s: command '%s' not found, did you mean:\n", os.Args[0], filter) + cmds = matches + } + + sort.Strings(cmds) + for _, name := range cmds { + fmt.Fprintf(w, " %s\n", name) + } +} + +func commandHelp(w io.Writer, name string, cmd Command, f *flag.FlagSet) { + type HasUsage interface { + Usage() string + } + + fmt.Fprintf(w, "Usage: %s %s [OPTIONS]", os.Args[0], name) + if u, ok := cmd.(HasUsage); ok { + fmt.Fprintf(w, " %s", u.Usage()) + } + fmt.Fprintf(w, "\n") + + type HasDescription interface { + Description() string + } + + if u, ok := cmd.(HasDescription); ok { + fmt.Fprintf(w, "\n%s\n", u.Description()) + } + + n := 0 + f.VisitAll(func(_ *flag.Flag) { + n += 1 + }) + + if n > 0 { + fmt.Fprintf(w, "\nOptions:\n") + tw := tabwriter.NewWriter(w, 2, 0, 2, ' ', 0) + f.VisitAll(func(f *flag.Flag) { + fmt.Fprintf(tw, "\t-%s=%s\t%s\n", f.Name, f.DefValue, f.Usage) + }) + tw.Flush() + } +} + +func clientLogout(ctx context.Context, cmd Command) error { + type logout interface { + Logout(context.Context) error + } + + if l, ok := cmd.(logout); ok { + return l.Logout(ctx) + } + + return nil +} + +func Run(args []string) int { + hw := os.Stderr + rc := 1 + hwrc := func(arg string) { + arg = strings.TrimLeft(arg, "-") + if arg == "h" || arg == "help" { + hw = os.Stdout + rc = 0 + } + } + + var err error + + if len(args) == 0 { + generalHelp(hw, "") + return rc + } + + // Look up real command name in aliases table. + name, ok := aliases[args[0]] + if !ok { + name = args[0] + } + + cmd, ok := commands[name] + if !ok { + hwrc(name) + generalHelp(hw, name) + return rc + } + + fs := flag.NewFlagSet("", flag.ContinueOnError) + fs.SetOutput(io.Discard) + + ctx := context.Background() + + if id := os.Getenv("GOVC_OPERATION_ID"); id != "" { + ctx = context.WithValue(ctx, types.ID{}, id) + } + + cmd.Register(ctx, fs) + + if err = fs.Parse(args[1:]); err != nil { + goto error + } + + if err = cmd.Process(ctx); err != nil { + goto error + } + + if err = cmd.Run(ctx, fs); err != nil { + goto error + } + + if err = clientLogout(ctx, cmd); err != nil { + goto error + } + + return 0 + +error: + if err == flag.ErrHelp { + if len(args) == 2 { + hwrc(args[1]) + } + commandHelp(hw, args[0], cmd, fs) + } else { + if x, ok := err.(interface{ ExitCode() int }); ok { + // propagate exit code, e.g. from guest.run + rc = x.ExitCode() + } else { + w, ok := cmd.(interface{ WriteError(error) bool }) + if ok { + ok = w.WriteError(err) + } + if !ok { + fmt.Fprintf(os.Stderr, "%s: %s\n", os.Args[0], err) + } + } + } + + _ = clientLogout(ctx, cmd) + + return rc +} diff --git a/vendor/github.com/vmware/govmomi/govc/cli/register.go b/vendor/github.com/vmware/govmomi/govc/cli/register.go new file mode 100644 index 00000000000..866c5816bed --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/cli/register.go @@ -0,0 +1,47 @@ +/* +Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cli + +import "os" + +var commands = map[string]Command{} + +var aliases = map[string]string{} + +// hideUnreleased allows commands to be compiled into the govc binary without being registered by default. +// Unreleased commands are omitted from 'govc -h' help text and the generated govc/USAGE.md +// Setting the env var GOVC_SHOW_UNRELEASED=true enables any commands registered as unreleased. +var hideUnreleased = os.Getenv("GOVC_SHOW_UNRELEASED") != "true" + +func ShowUnreleased() bool { + return !hideUnreleased +} + +func Register(name string, c Command, unreleased ...bool) { + if len(unreleased) != 0 && unreleased[0] && hideUnreleased { + return + } + commands[name] = c +} + +func Alias(name string, alias string) { + aliases[alias] = name +} + +func Commands() map[string]Command { + return commands +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/client.go b/vendor/github.com/vmware/govmomi/govc/flags/client.go new file mode 100644 index 00000000000..9b04882ca2b --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/client.go @@ -0,0 +1,557 @@ +/* +Copyright (c) 2014-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "crypto/tls" + "errors" + "flag" + "fmt" + "net/url" + "os" + "os/signal" + "path/filepath" + "strings" + "syscall" + "time" + + "github.com/vmware/govmomi/cns" + "github.com/vmware/govmomi/pbm" + "github.com/vmware/govmomi/session" + "github.com/vmware/govmomi/session/cache" + "github.com/vmware/govmomi/session/keepalive" + "github.com/vmware/govmomi/vapi/rest" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" +) + +const ( + envURL = "GOVC_URL" + envUsername = "GOVC_USERNAME" + envPassword = "GOVC_PASSWORD" + envCertificate = "GOVC_CERTIFICATE" + envPrivateKey = "GOVC_PRIVATE_KEY" + envInsecure = "GOVC_INSECURE" + envPersist = "GOVC_PERSIST_SESSION" + envMinAPIVersion = "GOVC_MIN_API_VERSION" + envVimNamespace = "GOVC_VIM_NAMESPACE" + envVimVersion = "GOVC_VIM_VERSION" + envTLSCaCerts = "GOVC_TLS_CA_CERTS" + envTLSKnownHosts = "GOVC_TLS_KNOWN_HOSTS" + + defaultMinVimVersion = "5.5" +) + +const cDescr = "ESX or vCenter URL" + +type ClientFlag struct { + common + + *DebugFlag + + username string + password string + cert string + key string + persist bool + minAPIVersion string + vimNamespace string + vimVersion string + tlsCaCerts string + tlsKnownHosts string + client *vim25.Client + restClient *rest.Client + Session cache.Session +} + +var ( + home = os.Getenv("GOVMOMI_HOME") + clientFlagKey = flagKey("client") +) + +func init() { + if home == "" { + home = filepath.Join(os.Getenv("HOME"), ".govmomi") + } +} + +func NewClientFlag(ctx context.Context) (*ClientFlag, context.Context) { + if v := ctx.Value(clientFlagKey); v != nil { + return v.(*ClientFlag), ctx + } + + v := &ClientFlag{} + v.DebugFlag, ctx = NewDebugFlag(ctx) + ctx = context.WithValue(ctx, clientFlagKey, v) + return v, ctx +} + +func (flag *ClientFlag) String() string { + url := flag.Session.Endpoint() + if url == nil { + return "" + } + + return url.String() +} + +func (flag *ClientFlag) Set(s string) error { + var err error + + flag.Session.URL, err = soap.ParseURL(s) + + return err +} + +func (flag *ClientFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.DebugFlag.Register(ctx, f) + + { + flag.Set(os.Getenv(envURL)) + usage := fmt.Sprintf("%s [%s]", cDescr, envURL) + f.Var(flag, "u", usage) + } + + { + flag.username = os.Getenv(envUsername) + flag.password = os.Getenv(envPassword) + } + + { + value := os.Getenv(envCertificate) + usage := fmt.Sprintf("Certificate [%s]", envCertificate) + f.StringVar(&flag.cert, "cert", value, usage) + } + + { + value := os.Getenv(envPrivateKey) + usage := fmt.Sprintf("Private key [%s]", envPrivateKey) + f.StringVar(&flag.key, "key", value, usage) + } + + { + insecure := false + switch env := strings.ToLower(os.Getenv(envInsecure)); env { + case "1", "true": + insecure = true + } + + usage := fmt.Sprintf("Skip verification of server certificate [%s]", envInsecure) + f.BoolVar(&flag.Session.Insecure, "k", insecure, usage) + } + + { + persist := true + switch env := strings.ToLower(os.Getenv(envPersist)); env { + case "0", "false": + persist = false + } + + usage := fmt.Sprintf("Persist session to disk [%s]", envPersist) + f.BoolVar(&flag.persist, "persist-session", persist, usage) + } + + { + env := os.Getenv(envMinAPIVersion) + if env == "" { + env = defaultMinVimVersion + } + + flag.minAPIVersion = env + } + + { + value := os.Getenv(envVimNamespace) + if value == "" { + value = vim25.Namespace + } + usage := fmt.Sprintf("Vim namespace [%s]", envVimNamespace) + f.StringVar(&flag.vimNamespace, "vim-namespace", value, usage) + } + + { + value := os.Getenv(envVimVersion) + if value == "" { + value = vim25.Version + } + usage := fmt.Sprintf("Vim version [%s]", envVimVersion) + f.StringVar(&flag.vimVersion, "vim-version", value, usage) + } + + { + value := os.Getenv(envTLSCaCerts) + usage := fmt.Sprintf("TLS CA certificates file [%s]", envTLSCaCerts) + f.StringVar(&flag.tlsCaCerts, "tls-ca-certs", value, usage) + } + + { + value := os.Getenv(envTLSKnownHosts) + usage := fmt.Sprintf("TLS known hosts file [%s]", envTLSKnownHosts) + f.StringVar(&flag.tlsKnownHosts, "tls-known-hosts", value, usage) + } + }) +} + +func (flag *ClientFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + err := flag.DebugFlag.Process(ctx) + if err != nil { + return err + } + + if flag.Session.URL == nil { + return errors.New("specify an " + cDescr) + } + + if !flag.persist { + flag.Session.Passthrough = true + } + + flag.username, err = session.Secret(flag.username) + if err != nil { + return err + } + flag.password, err = session.Secret(flag.password) + if err != nil { + return err + } + + // Override username if set + if flag.username != "" { + var password string + var ok bool + + if flag.Session.URL.User != nil { + password, ok = flag.Session.URL.User.Password() + } + + if ok { + flag.Session.URL.User = url.UserPassword(flag.username, password) + } else { + flag.Session.URL.User = url.User(flag.username) + } + } + + // Override password if set + if flag.password != "" { + var username string + + if flag.Session.URL.User != nil { + username = flag.Session.URL.User.Username() + } + + flag.Session.URL.User = url.UserPassword(username, flag.password) + } + + return nil + }) +} + +func (flag *ClientFlag) ConfigureTLS(sc *soap.Client) error { + if flag.cert != "" { + cert, err := tls.LoadX509KeyPair(flag.cert, flag.key) + if err != nil { + return fmt.Errorf("%s=%q %s=%q: %s", envCertificate, flag.cert, envPrivateKey, flag.key, err) + } + + sc.SetCertificate(cert) + } + + // Set namespace and version + sc.Namespace = "urn:" + flag.vimNamespace + sc.Version = flag.vimVersion + + sc.UserAgent = fmt.Sprintf("govc/%s", strings.TrimPrefix(BuildVersion, "v")) + + if err := flag.SetRootCAs(sc); err != nil { + return err + } + + if err := sc.LoadThumbprints(flag.tlsKnownHosts); err != nil { + return err + } + + t := sc.DefaultTransport() + var err error + + value := os.Getenv("GOVC_TLS_HANDSHAKE_TIMEOUT") + if value != "" { + t.TLSHandshakeTimeout, err = time.ParseDuration(value) + if err != nil { + return err + } + } + + sc.UseJSON(os.Getenv("GOVC_VI_JSON") != "") + + return nil +} + +func (flag *ClientFlag) SetRootCAs(c *soap.Client) error { + if flag.tlsCaCerts != "" { + return c.SetRootCAs(flag.tlsCaCerts) + } + return nil +} + +func isDevelopmentVersion(apiVersion string) bool { + // Skip version check for development builds which can be in the form of "r4A70F" or "6.5.x" + return strings.Count(apiVersion, ".") == 0 || strings.HasSuffix(apiVersion, ".x") +} + +// apiVersionValid returns whether or not the API version supported by the +// server the client is connected to is not recent enough. +func apiVersionValid(c *vim25.Client, minVersionString string) error { + if minVersionString == "-" { + // Disable version check + return nil + } + + apiVersion := c.ServiceContent.About.ApiVersion + if isDevelopmentVersion(apiVersion) { + return nil + } + + realVersion, err := ParseVersion(apiVersion) + if err != nil { + return fmt.Errorf("error parsing API version %q: %s", apiVersion, err) + } + + minVersion, err := ParseVersion(minVersionString) + if err != nil { + return fmt.Errorf("error parsing %s=%q: %s", envMinAPIVersion, minVersionString, err) + } + + if !minVersion.Lte(realVersion) { + err = fmt.Errorf("require API version %q, connected to API version %q (set %s to override)", + minVersionString, + c.ServiceContent.About.ApiVersion, + envMinAPIVersion) + return err + } + + return nil +} + +func (flag *ClientFlag) RoundTripper(c *soap.Client) soap.RoundTripper { + // Retry twice when a temporary I/O error occurs. + // This means a maximum of 3 attempts. + rt := vim25.Retry(c, vim25.RetryTemporaryNetworkError, 3) + + switch { + case flag.dump: + rt = &dump{roundTripper: rt} + case flag.verbose: + rt = &verbose{roundTripper: rt} + } + + return rt +} + +func (flag *ClientFlag) Client() (*vim25.Client, error) { + if flag.client != nil { + return flag.client, nil + } + + c := new(vim25.Client) + err := flag.Session.Login(context.Background(), c, flag.ConfigureTLS) + if err != nil { + return nil, err + } + + // Check that the endpoint has the right API version + err = apiVersionValid(c, flag.minAPIVersion) + if err != nil { + return nil, err + } + + if flag.vimVersion == "" { + err = c.UseServiceVersion() + if err != nil { + return nil, err + } + } + + c.RoundTripper = flag.RoundTripper(c.Client) + flag.client = c + + return flag.client, nil +} + +func (flag *ClientFlag) RestClient() (*rest.Client, error) { + if flag.restClient != nil { + return flag.restClient, nil + } + + c := new(rest.Client) + + err := flag.Session.Login(context.Background(), c, flag.ConfigureTLS) + if err != nil { + return nil, err + } + + flag.restClient = c + return flag.restClient, nil +} + +func (flag *ClientFlag) PbmClient() (*pbm.Client, error) { + vc, err := flag.Client() + if err != nil { + return nil, err + } + c, err := pbm.NewClient(context.Background(), vc) + if err != nil { + return nil, err + } + + c.RoundTripper = flag.RoundTripper(c.Client) + + return c, nil +} + +func (flag *ClientFlag) CnsClient() (*cns.Client, error) { + vc, err := flag.Client() + if err != nil { + return nil, err + } + _ = vc.UseServiceVersion("vsan") + + c, err := cns.NewClient(context.Background(), vc) + if err != nil { + return nil, err + } + + c.RoundTripper = flag.RoundTripper(c.Client) + + return c, nil +} + +func (flag *ClientFlag) KeepAlive(client cache.Client) { + switch c := client.(type) { + case *vim25.Client: + keepalive.NewHandlerSOAP(c, 0, nil).Start() + case *rest.Client: + keepalive.NewHandlerREST(c, 0, nil).Start() + default: + panic(fmt.Sprintf("unsupported client type=%T", client)) + } +} + +func (flag *ClientFlag) Logout(ctx context.Context) error { + if flag.client != nil { + _ = flag.Session.Logout(ctx, flag.client) + } + + if flag.restClient != nil { + _ = flag.Session.Logout(ctx, flag.restClient) + } + + return nil +} + +// Environ returns the govc environment variables for this connection +func (flag *ClientFlag) Environ(extra bool) []string { + var env []string + add := func(k, v string) { + env = append(env, fmt.Sprintf("%s=%s", k, v)) + } + + u := *flag.Session.URL + if u.User != nil { + add(envUsername, u.User.Username()) + + if p, ok := u.User.Password(); ok { + add(envPassword, p) + } + + u.User = nil + } + + if u.Path == vim25.Path { + u.Path = "" + } + u.Fragment = "" + u.RawQuery = "" + + add(envURL, strings.TrimPrefix(u.String(), "https://")) + + keys := []string{ + envCertificate, + envPrivateKey, + envInsecure, + envPersist, + envMinAPIVersion, + envVimNamespace, + envVimVersion, + } + + for _, k := range keys { + if v := os.Getenv(k); v != "" { + add(k, v) + } + } + + if extra { + add("GOVC_URL_SCHEME", flag.Session.URL.Scheme) + + v := strings.SplitN(u.Host, ":", 2) + add("GOVC_URL_HOST", v[0]) + if len(v) == 2 { + add("GOVC_URL_PORT", v[1]) + } + + add("GOVC_URL_PATH", flag.Session.URL.Path) + + if f := flag.Session.URL.Fragment; f != "" { + add("GOVC_URL_FRAGMENT", f) + } + + if q := flag.Session.URL.RawQuery; q != "" { + add("GOVC_URL_QUERY", q) + } + } + + return env +} + +// WithCancel calls the given function, returning when complete or canceled via SIGINT. +func (flag *ClientFlag) WithCancel(ctx context.Context, f func(context.Context) error) error { + sig := make(chan os.Signal, 1) + signal.Notify(sig, syscall.SIGINT) + + wctx, cancel := context.WithCancel(ctx) + defer cancel() + + done := make(chan bool) + var werr error + + go func() { + defer close(done) + werr = f(wctx) + }() + + select { + case <-sig: + cancel() + <-done // Wait for f() to complete + case <-done: + } + + return werr +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/cluster.go b/vendor/github.com/vmware/govmomi/govc/flags/cluster.go new file mode 100644 index 00000000000..a386d33f2fc --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/cluster.go @@ -0,0 +1,204 @@ +/* +Copyright (c) 2017 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/view" + "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/types" +) + +type ClusterFlag struct { + common + + *DatacenterFlag + + Name string + + cluster *object.ClusterComputeResource + pc *property.Collector +} + +var clusterFlagKey = flagKey("cluster") + +func NewClusterFlag(ctx context.Context) (*ClusterFlag, context.Context) { + if v := ctx.Value(clusterFlagKey); v != nil { + return v.(*ClusterFlag), ctx + } + + v := &ClusterFlag{} + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + ctx = context.WithValue(ctx, clusterFlagKey, v) + return v, ctx +} + +func (f *ClusterFlag) Register(ctx context.Context, fs *flag.FlagSet) { + f.RegisterOnce(func() { + f.DatacenterFlag.Register(ctx, fs) + + env := "GOVC_CLUSTER" + value := os.Getenv(env) + usage := fmt.Sprintf("Cluster [%s]", env) + fs.StringVar(&f.Name, "cluster", value, usage) + }) +} + +// RegisterPlacement registers the -cluster flag without using GOVC_CLUSTER env as the default value, +// usage is specific to VM placement. +func (f *ClusterFlag) RegisterPlacement(ctx context.Context, fs *flag.FlagSet) { + f.RegisterOnce(func() { + f.DatacenterFlag.Register(ctx, fs) + + fs.StringVar(&f.Name, "cluster", "", "Use cluster for VM placement via DRS") + }) +} + +func (f *ClusterFlag) Process(ctx context.Context) error { + return f.ProcessOnce(func() error { + if err := f.DatacenterFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (f *ClusterFlag) Cluster() (*object.ClusterComputeResource, error) { + if f.cluster != nil { + return f.cluster, nil + } + + finder, err := f.Finder() + if err != nil { + return nil, err + } + + if f.cluster, err = finder.ClusterComputeResourceOrDefault(context.TODO(), f.Name); err != nil { + return nil, err + } + + f.pc = property.DefaultCollector(f.cluster.Client()) + + return f.cluster, nil +} + +func (f *ClusterFlag) ClusterIfSpecified() (*object.ClusterComputeResource, error) { + if f.Name == "" { + return nil, nil + } + return f.Cluster() +} + +func (f *ClusterFlag) Reconfigure(ctx context.Context, spec types.BaseComputeResourceConfigSpec) error { + cluster, err := f.Cluster() + if err != nil { + return err + } + + task, err := cluster.Reconfigure(ctx, spec, true) + if err != nil { + return err + } + + logger := f.ProgressLogger(fmt.Sprintf("Reconfigure %s...", cluster.InventoryPath)) + defer logger.Wait() + + _, err = task.WaitForResult(ctx, logger) + return err +} + +func (f *ClusterFlag) objectMap(ctx context.Context, kind string, names []string) (map[string]types.ManagedObjectReference, error) { + cluster, err := f.Cluster() + if err != nil { + return nil, err + } + + objects := make(map[string]types.ManagedObjectReference, len(names)) + for _, name := range names { + objects[name] = types.ManagedObjectReference{} + } + + m := view.NewManager(cluster.Client()) + v, err := m.CreateContainerView(ctx, cluster.Reference(), []string{kind}, true) + if err != nil { + return nil, err + } + + defer func() { + _ = v.Destroy(ctx) + }() + + var entities []mo.ManagedEntity + + err = v.Retrieve(ctx, []string{"ManagedEntity"}, []string{"name"}, &entities) + if err != nil { + return nil, err + } + + for _, e := range entities { + if _, ok := objects[e.Name]; ok { + objects[e.Name] = e.Self + } + } + + for name, ref := range objects { + if ref.Value == "" { + return nil, fmt.Errorf("%s %q not found", kind, name) + } + } + + return objects, nil +} + +func (f *ClusterFlag) ObjectList(ctx context.Context, kind string, names []string) ([]types.ManagedObjectReference, error) { + objs, err := f.objectMap(ctx, kind, names) + if err != nil { + return nil, err + } + + var refs []types.ManagedObjectReference + + for _, name := range names { // preserve order + refs = append(refs, objs[name]) + } + + return refs, nil +} + +func (f *ClusterFlag) Names(ctx context.Context, refs []types.ManagedObjectReference) (map[types.ManagedObjectReference]string, error) { + names := make(map[types.ManagedObjectReference]string, len(refs)) + + if len(refs) != 0 { + var objs []mo.ManagedEntity + err := f.pc.Retrieve(ctx, refs, []string{"name"}, &objs) + if err != nil { + return nil, err + } + + for _, obj := range objs { + names[obj.Self] = obj.Name + } + } + + return names, nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/common.go b/vendor/github.com/vmware/govmomi/govc/flags/common.go new file mode 100644 index 00000000000..002c239b9e9 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/common.go @@ -0,0 +1,38 @@ +/* +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package flags + +import "sync" + +// Key type for storing flag instances in a context.Context. +type flagKey string + +// Type to help flags out with only registering/processing once. +type common struct { + register sync.Once + process sync.Once +} + +func (c *common) RegisterOnce(fn func()) { + c.register.Do(fn) +} + +func (c *common) ProcessOnce(fn func() error) (err error) { + c.process.Do(func() { + err = fn() + }) + return err +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/datacenter.go b/vendor/github.com/vmware/govmomi/govc/flags/datacenter.go new file mode 100644 index 00000000000..d73f36a8192 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/datacenter.go @@ -0,0 +1,225 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + "strings" + + "github.com/vmware/govmomi/find" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/property" + "github.com/vmware/govmomi/vim25/types" +) + +type DatacenterFlag struct { + common + + *ClientFlag + *OutputFlag + + Name string + dc *object.Datacenter + finder *find.Finder + err error +} + +var datacenterFlagKey = flagKey("datacenter") + +func NewDatacenterFlag(ctx context.Context) (*DatacenterFlag, context.Context) { + if v := ctx.Value(datacenterFlagKey); v != nil { + return v.(*DatacenterFlag), ctx + } + + v := &DatacenterFlag{} + v.ClientFlag, ctx = NewClientFlag(ctx) + v.OutputFlag, ctx = NewOutputFlag(ctx) + ctx = context.WithValue(ctx, datacenterFlagKey, v) + return v, ctx +} + +func (flag *DatacenterFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.ClientFlag.Register(ctx, f) + flag.OutputFlag.Register(ctx, f) + + env := "GOVC_DATACENTER" + value := os.Getenv(env) + usage := fmt.Sprintf("Datacenter [%s]", env) + f.StringVar(&flag.Name, "dc", value, usage) + }) +} + +func (flag *DatacenterFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if err := flag.ClientFlag.Process(ctx); err != nil { + return err + } + if err := flag.OutputFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (flag *DatacenterFlag) Finder(all ...bool) (*find.Finder, error) { + if flag.finder != nil { + return flag.finder, nil + } + + c, err := flag.Client() + if err != nil { + return nil, err + } + + allFlag := false + if len(all) == 1 { + allFlag = all[0] + } + finder := find.NewFinder(c, allFlag) + + // Datacenter is not required (ls command for example). + // Set for relative func if dc flag is given or + // if there is a single (default) Datacenter + ctx := context.TODO() + if flag.Name == "" { + flag.dc, flag.err = finder.DefaultDatacenter(ctx) + } else { + if flag.dc, err = finder.Datacenter(ctx, flag.Name); err != nil { + return nil, err + } + } + + finder.SetDatacenter(flag.dc) + + flag.finder = finder + + return flag.finder, nil +} + +func (flag *DatacenterFlag) Datacenter() (*object.Datacenter, error) { + if flag.dc != nil { + return flag.dc, nil + } + + _, err := flag.Finder() + if err != nil { + return nil, err + } + + if flag.err != nil { + // Should only happen if no dc is specified and len(dcs) > 1 + return nil, flag.err + } + + return flag.dc, err +} + +func (flag *DatacenterFlag) DatacenterIfSpecified() (*object.Datacenter, error) { + if flag.Name == "" { + return nil, nil + } + return flag.Datacenter() +} + +func (flag *DatacenterFlag) ManagedObject(ctx context.Context, arg string) (types.ManagedObjectReference, error) { + var ref types.ManagedObjectReference + + finder, err := flag.Finder() + if err != nil { + return ref, err + } + + if ref.FromString(arg) { + if strings.HasPrefix(ref.Type, "com.vmware.content.") { + return ref, nil // special case for content library + } + pc := property.DefaultCollector(flag.client) + var content []types.ObjectContent + err = pc.RetrieveOne(ctx, ref, []string{"name"}, &content) + if err == nil { + return ref, nil + } + } + + l, err := finder.ManagedObjectList(ctx, arg) + if err != nil { + return ref, err + } + + switch len(l) { + case 0: + return ref, fmt.Errorf("%s not found", arg) + case 1: + return l[0].Object.Reference(), nil + default: + var objs []types.ManagedObjectReference + for _, o := range l { + objs = append(objs, o.Object.Reference()) + } + return ref, fmt.Errorf("%d objects at path %q: %s", len(l), arg, objs) + } +} + +func (flag *DatacenterFlag) ManagedObjects(ctx context.Context, args []string) ([]types.ManagedObjectReference, error) { + var refs []types.ManagedObjectReference + + c, err := flag.Client() + if err != nil { + return nil, err + } + + if len(args) == 0 { + refs = append(refs, c.ServiceContent.RootFolder) + return refs, nil + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + for _, arg := range args { + if ref := object.ReferenceFromString(arg); ref != nil { + // e.g. output from object.collect + refs = append(refs, *ref) + continue + } + + if !strings.Contains(arg, "/") { + return nil, fmt.Errorf("%q must be qualified with a path", arg) + } + + elements, err := finder.ManagedObjectList(ctx, arg) + if err != nil { + return nil, err + } + + if len(elements) == 0 { + return nil, fmt.Errorf("object '%s' not found", arg) + } + + for _, e := range elements { + refs = append(refs, e.Object.Reference()) + } + } + + return refs, nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/datastore.go b/vendor/github.com/vmware/govmomi/govc/flags/datastore.go new file mode 100644 index 00000000000..8030a6e00ef --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/datastore.go @@ -0,0 +1,150 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25/types" +) + +type DatastoreFlag struct { + common + + *DatacenterFlag + + Name string + + ds *object.Datastore +} + +var datastoreFlagKey = flagKey("datastore") + +// NewCustomDatastoreFlag creates and returns a new DatastoreFlag without +// trying to retrieve an existing one from the specified context. +func NewCustomDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) { + v := &DatastoreFlag{} + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + return v, ctx +} + +func NewDatastoreFlag(ctx context.Context) (*DatastoreFlag, context.Context) { + if v := ctx.Value(datastoreFlagKey); v != nil { + return v.(*DatastoreFlag), ctx + } + + v, ctx := NewCustomDatastoreFlag(ctx) + ctx = context.WithValue(ctx, datastoreFlagKey, v) + return v, ctx +} + +func (f *DatastoreFlag) Register(ctx context.Context, fs *flag.FlagSet) { + f.RegisterOnce(func() { + f.DatacenterFlag.Register(ctx, fs) + + env := "GOVC_DATASTORE" + value := os.Getenv(env) + usage := fmt.Sprintf("Datastore [%s]", env) + fs.StringVar(&f.Name, "ds", value, usage) + }) +} + +func (f *DatastoreFlag) Process(ctx context.Context) error { + return f.ProcessOnce(func() error { + if err := f.DatacenterFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (flag *DatastoreFlag) IsSet() bool { + return flag.Name != "" +} + +func (f *DatastoreFlag) Args(args []string) []object.DatastorePath { + var files []object.DatastorePath + + for _, arg := range args { + var p object.DatastorePath + + if p.FromString(arg) { + f.Name = p.Datastore + } else { + p.Datastore = f.Name + p.Path = arg + } + + files = append(files, p) + } + + return files +} + +func (f *DatastoreFlag) Datastore() (*object.Datastore, error) { + if f.ds != nil { + return f.ds, nil + } + + var p object.DatastorePath + if p.FromString(f.Name) { + // Example use case: + // -ds "$(govc object.collect -s vm/foo config.files.logDirectory)" + f.Name = p.Datastore + } + + finder, err := f.Finder() + if err != nil { + return nil, err + } + + if f.ds, err = finder.DatastoreOrDefault(context.TODO(), f.Name); err != nil { + return nil, err + } + + return f.ds, nil +} + +func (flag *DatastoreFlag) DatastoreIfSpecified() (*object.Datastore, error) { + if flag.Name == "" { + return nil, nil + } + return flag.Datastore() +} + +func (f *DatastoreFlag) DatastorePath(name string) (string, error) { + ds, err := f.Datastore() + if err != nil { + return "", err + } + + return ds.Path(name), nil +} + +func (f *DatastoreFlag) Stat(ctx context.Context, file string) (types.BaseFileInfo, error) { + ds, err := f.Datastore() + if err != nil { + return nil, err + } + + return ds.Stat(ctx, file) + +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/debug.go b/vendor/github.com/vmware/govmomi/govc/flags/debug.go new file mode 100644 index 00000000000..702cf42e664 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/debug.go @@ -0,0 +1,474 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "bufio" + "context" + "flag" + "fmt" + "io" + "os" + "os/exec" + "path/filepath" + "reflect" + "strings" + "sync" + "text/tabwriter" + "time" + + "github.com/dougm/pretty" + + "github.com/vmware/govmomi/vim25/debug" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" +) + +type cmdFormat struct { + path string + err error + args []string +} + +func (c *cmdFormat) lookPath(file string, args ...string) { + c.args = args + c.path, c.err = exec.LookPath(file) +} + +func (c *cmdFormat) cmd() (*exec.Cmd, error) { + if c.err != nil { + return nil, c.err + } + return exec.Command(c.path, c.args...), nil +} + +type DebugFlag struct { + common + + enable bool + trace bool + verbose bool + dump bool + xml cmdFormat + json cmdFormat +} + +var debugFlagKey = flagKey("debug") + +func NewDebugFlag(ctx context.Context) (*DebugFlag, context.Context) { + if v := ctx.Value(debugFlagKey); v != nil { + return v.(*DebugFlag), ctx + } + + v := &DebugFlag{} + ctx = context.WithValue(ctx, debugFlagKey, v) + return v, ctx +} + +func (flag *DebugFlag) Verbose() bool { + return flag.verbose +} + +func (flag *DebugFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + env := "GOVC_DEBUG" + enable := false + switch env := strings.ToLower(os.Getenv(env)); env { + case "1", "true": + enable = true + } + + usage := fmt.Sprintf("Store debug logs [%s]", env) + f.BoolVar(&flag.enable, "debug", enable, usage) + f.BoolVar(&flag.trace, "trace", false, "Write SOAP/REST traffic to stderr") + f.BoolVar(&flag.verbose, "verbose", false, "Write request/response data to stderr") + }) +} + +type cmdFormatCloser struct { + rc io.Closer + in io.Closer + cmd *exec.Cmd + wg *sync.WaitGroup +} + +func (c *cmdFormatCloser) Close() error { + _ = c.rc.Close() + _ = c.in.Close() + c.wg.Wait() + return c.cmd.Wait() +} + +func (flag *DebugFlag) newFormatReader(rc io.ReadCloser, w io.Writer, ext string) (io.ReadCloser, error) { + var err error + var cmd *exec.Cmd + + switch ext { + case "json": + cmd, err = flag.json.cmd() + if err != nil { + return nil, err + } + case "xml": + cmd, err = flag.xml.cmd() + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("unsupported type %s", ext) + } + + cmd.Stderr = os.Stderr + + stdin, err := cmd.StdinPipe() + if err != nil { + return nil, err + } + + stdout, err := cmd.StdoutPipe() + if err != nil { + return nil, err + } + + err = cmd.Start() + if err != nil { + return nil, err + } + + var wg sync.WaitGroup + wg.Add(1) + go func() { + _, _ = io.Copy(w, stdout) + wg.Done() + }() + + return debug.ReadCloser{ + Reader: io.TeeReader(rc, stdin), + Closer: &cmdFormatCloser{rc, stdin, cmd, &wg}, + }, nil +} + +func (flag *DebugFlag) debugTrace(rc io.ReadCloser, w io.Writer, ext string) io.ReadCloser { + fr, err := flag.newFormatReader(rc, w, ext) + if err != nil { + return debug.NewTeeReader(rc, w) + } + return fr +} + +func (flag *DebugFlag) Process(ctx context.Context) error { + // Base path for storing debug logs. + r := os.Getenv("GOVC_DEBUG_PATH") + + if flag.trace { + if flag.verbose { + flag.dump = true // output req/res as Go code + return nil + } + r = "-" + flag.enable = true + if os.Getenv("GOVC_DEBUG_FORMAT") != "false" { + debugXML := os.Getenv("GOVC_DEBUG_XML") + if debugXML == "" { + debugXML = "xmlstarlet" + } + flag.xml.lookPath(debugXML, "fo") + + debugJSON := os.Getenv("GOVC_DEBUG_JSON") + if debugJSON == "" { + debugJSON = "jq" + } + flag.json.lookPath(debugJSON, ".") + + soap.Trace = flag.debugTrace + } + } + + if !flag.enable { + return nil + } + + return flag.ProcessOnce(func() error { + switch r { + case "-": + debug.SetProvider(&debug.LogProvider{}) + return nil + case "": + r = home + } + r = filepath.Join(r, "debug") + + // Path for this particular run. + run := os.Getenv("GOVC_DEBUG_PATH_RUN") + if run == "" { + now := time.Now().Format("2006-01-02T15-04-05.999999999") + r = filepath.Join(r, now) + } else { + // reuse the same path + r = filepath.Join(r, run) + _ = os.RemoveAll(r) + } + + err := os.MkdirAll(r, 0700) + if err != nil { + return err + } + + p := debug.FileProvider{ + Path: r, + } + + debug.SetProvider(&p) + return nil + }) +} + +type dump struct { + roundTripper soap.RoundTripper +} + +func (d *dump) RoundTrip(ctx context.Context, req, res soap.HasFault) error { + vreq := reflect.ValueOf(req).Elem().FieldByName("Req").Elem() + + pretty.Fprintf(os.Stderr, "%# v\n", vreq.Interface()) + + err := d.roundTripper.RoundTrip(ctx, req, res) + if err != nil { + if fault := res.Fault(); fault != nil { + pretty.Fprintf(os.Stderr, "%# v\n", fault) + } + return err + } + + vres := reflect.ValueOf(res).Elem().FieldByName("Res").Elem() + pretty.Fprintf(os.Stderr, "%# v\n", vres.Interface()) + + return nil +} + +type verbose struct { + roundTripper soap.RoundTripper +} + +func (*verbose) mor(ref types.ManagedObjectReference) string { + if strings.HasPrefix(ref.Value, "session") { + ref.Value = "session[...]" + return ref.String() + } + return ref.Value +} + +func (*verbose) str(val reflect.Value) string { + if !val.IsValid() { + return "" + } + + switch val.Kind() { + case reflect.Ptr, reflect.Interface: + if val.IsNil() { + return "nil" + } + } + + p := "" + + switch pval := val.Interface().(type) { + case fmt.Stringer: + p = pval.String() + case string: + if len(pval) > 45 { + pval = pval[:42] + "..." + } + p = fmt.Sprintf("%s", pval) + case []string: + p = fmt.Sprintf("%v", pval) + case []types.ManagedObjectReference: + refs := make([]string, len(pval)) + for i := range pval { + refs[i] = pval[i].Value + } + p = fmt.Sprintf("%v", refs) + default: + return "" + } + + return p +} + +func (v *verbose) value(val types.AnyType) string { + rval := reflect.ValueOf(val) + if rval.Kind() == reflect.Ptr && !rval.IsNil() { + rval = rval.Elem() + } + if rval.Kind() == reflect.Struct { + if strings.HasPrefix(rval.Type().Name(), "ArrayOf") { + rval = rval.Field(0) + val = rval.Interface() + } + } + s := v.str(rval) + if s != "" { + return s + } + return v.prettyPrint(val) +} + +func (v *verbose) propertyValue(obj types.ManagedObjectReference, name string, pval types.AnyType) string { + val := v.value(pval) + if obj.Type != "Task" && !strings.HasPrefix(obj.Value, "session") { + if len(val) > 512 { + val = fmt.Sprintf("`govc object.collect -dump %s %s`", obj, name) + } + } + return fmt.Sprintf("%s\t%s:\t%s", v.mor(obj), name, val) +} + +func (v *verbose) missingSet(o types.ManagedObjectReference, m []types.MissingProperty) []string { + var s []string + for _, p := range m { + s = append(s, fmt.Sprintf("%s\t%s:\t%s", v.mor(o), p.Path, v.prettyPrint(p.Fault.Fault))) + } + return s +} + +func (v *verbose) updateSet(u *types.UpdateSet) []string { + var s []string + if u == nil { + return s + } + for _, f := range u.FilterSet { + for _, o := range f.ObjectSet { + for _, c := range o.ChangeSet { + s = append(s, v.propertyValue(o.Obj, c.Name, c.Val)) + } + s = append(s, v.missingSet(o.Obj, o.MissingSet)...) + } + } + return s +} + +func (v *verbose) objectContent(content []types.ObjectContent) []string { + var s []string + for _, o := range content { + for _, p := range o.PropSet { + s = append(s, v.propertyValue(o.Obj, p.Name, p.Val)) + } + s = append(s, v.missingSet(o.Obj, o.MissingSet)...) + } + return s +} + +func (v *verbose) prettyPrint(val interface{}) string { + p := pretty.Sprintf("%# v\n", val) + var res []string + scanner := bufio.NewScanner(strings.NewReader(p)) + for scanner.Scan() { + line := scanner.Text() + if strings.Contains(line, "nil,") || strings.Contains(line, "(nil),") { + continue // nil pointer field + } + if strings.Contains(line, `"",`) { + continue // empty string field + } + if strings.Contains(line, `{},`) { + continue // empty embedded struct + } + if strings.Contains(line, "[context]") { + continue // noisy base64 encoded backtrace + } + res = append(res, line) + } + return strings.Join(res, "\n") +} + +func (v *verbose) table(vals []string) { + tw := tabwriter.NewWriter(os.Stderr, 2, 0, 1, ' ', 0) + for _, val := range vals { + fmt.Fprintf(tw, "...%s\n", val) + } + tw.Flush() +} + +func (v *verbose) RoundTrip(ctx context.Context, req, res soap.HasFault) error { + vreq := reflect.ValueOf(req).Elem().FieldByName("Req").Elem() + param := []string{""} + switch f := vreq.Field(0).Interface().(type) { + case types.ManagedObjectReference: + param[0] = v.mor(f) + default: + param[0] = fmt.Sprintf("%v", f) + } + + for i := 1; i < vreq.NumField(); i++ { + val := vreq.Field(i) + + if val.Kind() == reflect.Interface { + val = val.Elem() + } + + p := v.str(val) + if p == "" { + switch val.Kind() { + case reflect.Ptr, reflect.Slice, reflect.Struct: + p = val.Type().String() + default: + p = fmt.Sprintf("%v", val.Interface()) + } + } + + param = append(param, p) + } + + fmt.Fprintf(os.Stderr, "%s(%s)...\n", vreq.Type().Name(), strings.Join(param, ", ")) + + err := v.roundTripper.RoundTrip(ctx, req, res) + if err != nil { + if fault := res.Fault(); fault != nil { + fmt.Fprintln(os.Stderr, v.prettyPrint(fault)) + } else { + fmt.Fprintf(os.Stderr, "...%s\n", err) + } + return err + } + + vres := reflect.ValueOf(res).Elem().FieldByName("Res").Elem() + ret := vres.FieldByName("Returnval") + var s interface{} = "void" + + if ret.IsValid() { + switch x := ret.Interface().(type) { + case types.ManagedObjectReference: + s = v.mor(x) + case *types.UpdateSet: + s = v.updateSet(x) + case []types.ObjectContent: + s = v.objectContent(x) + case fmt.Stringer: + s = x.String() + default: + s = v.value(x) + } + } + if vals, ok := s.([]string); ok { + v.table(vals) + } else { + fmt.Fprintf(os.Stderr, "...%s\n", s) + } + fmt.Fprintln(os.Stderr) + + return err +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/empty.go b/vendor/github.com/vmware/govmomi/govc/flags/empty.go new file mode 100644 index 00000000000..8b17241ba14 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/empty.go @@ -0,0 +1,31 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" +) + +type EmptyFlag struct{} + +func (flag *EmptyFlag) Register(ctx context.Context, f *flag.FlagSet) { +} + +func (flag *EmptyFlag) Process(ctx context.Context) error { + return nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/env.go b/vendor/github.com/vmware/govmomi/govc/flags/env.go new file mode 100644 index 00000000000..c8b4c53f210 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/env.go @@ -0,0 +1,94 @@ +/* +Copyright (c) 2023-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25/mo" +) + +type EnvBrowser struct { + *ClusterFlag + *HostSystemFlag + *VirtualMachineFlag +} + +func (cmd *EnvBrowser) Register(ctx context.Context, f *flag.FlagSet) { + cmd.ClusterFlag, ctx = NewClusterFlag(ctx) + cmd.ClusterFlag.Register(ctx, f) + + cmd.HostSystemFlag, ctx = NewHostSystemFlag(ctx) + cmd.HostSystemFlag.Register(ctx, f) + + cmd.VirtualMachineFlag, ctx = NewVirtualMachineFlag(ctx) + cmd.VirtualMachineFlag.Register(ctx, f) +} + +func (cmd *EnvBrowser) Process(ctx context.Context) error { + if err := cmd.ClusterFlag.Process(ctx); err != nil { + return err + } + if err := cmd.HostSystemFlag.Process(ctx); err != nil { + return err + } + return cmd.VirtualMachineFlag.Process(ctx) +} + +func (cmd *EnvBrowser) Browser(ctx context.Context) (*object.EnvironmentBrowser, error) { + c, err := cmd.VirtualMachineFlag.Client() + if err != nil { + return nil, err + } + + vm, err := cmd.VirtualMachine() + if err != nil { + return nil, err + } + if vm != nil { + return vm.EnvironmentBrowser(ctx) + } + + host, err := cmd.HostSystemIfSpecified() + if err != nil { + return nil, err + } + + if host != nil { + var h mo.HostSystem + err = host.Properties(ctx, host.Reference(), []string{"parent"}, &h) + if err != nil { + return nil, err + } + + return object.NewComputeResource(c, *h.Parent).EnvironmentBrowser(ctx) + } + + finder, ferr := cmd.ClusterFlag.Finder() + if ferr != nil { + return nil, ferr + } + + cr, ferr := finder.ComputeResourceOrDefault(ctx, cmd.ClusterFlag.Name) + if ferr != nil { + return nil, ferr + } + + return cr.EnvironmentBrowser(ctx) +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/folder.go b/vendor/github.com/vmware/govmomi/govc/flags/folder.go new file mode 100644 index 00000000000..da17bfa7260 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/folder.go @@ -0,0 +1,142 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/object" +) + +type FolderFlag struct { + common + + *DatacenterFlag + + name string + folder *object.Folder +} + +var folderFlagKey = flagKey("folder") + +func NewFolderFlag(ctx context.Context) (*FolderFlag, context.Context) { + if v := ctx.Value(folderFlagKey); v != nil { + return v.(*FolderFlag), ctx + } + + v := &FolderFlag{} + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + ctx = context.WithValue(ctx, folderFlagKey, v) + return v, ctx +} + +func (flag *FolderFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.DatacenterFlag.Register(ctx, f) + + env := "GOVC_FOLDER" + value := os.Getenv(env) + usage := fmt.Sprintf("Inventory folder [%s]", env) + f.StringVar(&flag.name, "folder", value, usage) + }) +} + +func (flag *FolderFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if err := flag.DatacenterFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (flag *FolderFlag) IsSet() bool { + return flag.name != "" +} + +func (flag *FolderFlag) Folder() (*object.Folder, error) { + if flag.folder != nil { + return flag.folder, nil + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + if flag.folder, err = finder.FolderOrDefault(context.TODO(), flag.name); err != nil { + return nil, err + } + + return flag.folder, nil +} + +func (flag *FolderFlag) FolderIfSpecified() (*object.Folder, error) { + if flag.name == "" { + return nil, nil + } + return flag.Folder() +} + +func (flag *FolderFlag) FolderOrDefault(kind string) (*object.Folder, error) { + if flag.folder != nil { + return flag.folder, nil + } + + if flag.name != "" { + return flag.Folder() + } + + // RootFolder, no dc required + if kind == "/" { + client, err := flag.Client() + if err != nil { + return nil, err + } + + flag.folder = object.NewRootFolder(client) + return flag.folder, nil + } + + dc, err := flag.Datacenter() + if err != nil { + return nil, err + } + + folders, err := dc.Folders(context.TODO()) + if err != nil { + return nil, err + } + + switch kind { + case "vm": + flag.folder = folders.VmFolder + case "host": + flag.folder = folders.HostFolder + case "datastore": + flag.folder = folders.DatastoreFolder + case "network": + flag.folder = folders.NetworkFolder + default: + panic(kind) + } + + return flag.folder, nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/host_connect.go b/vendor/github.com/vmware/govmomi/govc/flags/host_connect.go new file mode 100644 index 00000000000..c64e4368b22 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/host_connect.go @@ -0,0 +1,100 @@ +/* +Copyright (c) 2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "net/url" + + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/types" +) + +type HostConnectFlag struct { + common + + types.HostConnectSpec + + noverify bool +} + +var hostConnectFlagKey = flagKey("hostConnect") + +func NewHostConnectFlag(ctx context.Context) (*HostConnectFlag, context.Context) { + if v := ctx.Value(hostConnectFlagKey); v != nil { + return v.(*HostConnectFlag), ctx + } + + v := &HostConnectFlag{} + ctx = context.WithValue(ctx, hostConnectFlagKey, v) + return v, ctx +} + +func (flag *HostConnectFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + f.StringVar(&flag.HostName, "hostname", "", "Hostname or IP address of the host") + f.StringVar(&flag.UserName, "username", "", "Username of administration account on the host") + f.StringVar(&flag.Password, "password", "", "Password of administration account on the host") + f.StringVar(&flag.SslThumbprint, "thumbprint", "", "SHA-1 thumbprint of the host's SSL certificate") + f.BoolVar(&flag.Force, "force", false, "Force when host is managed by another VC") + + f.BoolVar(&flag.noverify, "noverify", false, "Accept host thumbprint without verification") + }) +} + +func (flag *HostConnectFlag) Process(ctx context.Context) error { + return nil +} + +// Spec attempts to fill in SslThumbprint if empty. +// First checks GOVC_TLS_KNOWN_HOSTS, if not found and noverify=true then +// use object.HostCertificateInfo to get the thumbprint. +func (flag *HostConnectFlag) Spec(c *vim25.Client) types.HostConnectSpec { + spec := flag.HostConnectSpec + + if spec.SslThumbprint == "" { + spec.SslThumbprint = c.Thumbprint(spec.HostName) + + if spec.SslThumbprint == "" && flag.noverify { + var info object.HostCertificateInfo + t := c.DefaultTransport() + _ = info.FromURL(&url.URL{Host: spec.HostName}, t.TLSClientConfig) + spec.SslThumbprint = info.ThumbprintSHA1 + } + } + + return spec +} + +// Fault checks if error is SSLVerifyFault, including the thumbprint if so +func (flag *HostConnectFlag) Fault(err error) error { + if err == nil { + return nil + } + + if f, ok := err.(types.HasFault); ok { + switch fault := f.Fault().(type) { + case *types.SSLVerifyFault: + return fmt.Errorf("%s thumbprint=%s", err, fault.Thumbprint) + } + } + + return err +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/host_system.go b/vendor/github.com/vmware/govmomi/govc/flags/host_system.go new file mode 100644 index 00000000000..f8704def1a7 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/host_system.go @@ -0,0 +1,141 @@ +/* +Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/object" +) + +type HostSystemFlag struct { + common + + *ClientFlag + *DatacenterFlag + *SearchFlag + + name string + host *object.HostSystem + pool *object.ResourcePool +} + +var hostSystemFlagKey = flagKey("hostSystem") + +func NewHostSystemFlag(ctx context.Context) (*HostSystemFlag, context.Context) { + if v := ctx.Value(hostSystemFlagKey); v != nil { + return v.(*HostSystemFlag), ctx + } + + v := &HostSystemFlag{} + v.ClientFlag, ctx = NewClientFlag(ctx) + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + v.SearchFlag, ctx = NewSearchFlag(ctx, SearchHosts) + ctx = context.WithValue(ctx, hostSystemFlagKey, v) + return v, ctx +} + +func (flag *HostSystemFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.ClientFlag.Register(ctx, f) + flag.DatacenterFlag.Register(ctx, f) + flag.SearchFlag.Register(ctx, f) + + env := "GOVC_HOST" + value := os.Getenv(env) + usage := fmt.Sprintf("Host system [%s]", env) + f.StringVar(&flag.name, "host", value, usage) + }) +} + +func (flag *HostSystemFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if err := flag.ClientFlag.Process(ctx); err != nil { + return err + } + if err := flag.DatacenterFlag.Process(ctx); err != nil { + return err + } + if err := flag.SearchFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (flag *HostSystemFlag) HostSystemIfSpecified() (*object.HostSystem, error) { + if flag.host != nil { + return flag.host, nil + } + + // Use search flags if specified. + if flag.SearchFlag.IsSet() && flag.SearchFlag.t == SearchHosts { + host, err := flag.SearchFlag.HostSystem() + if err != nil { + return nil, err + } + + flag.host = host + return flag.host, nil + } + + // Never look for a default host system. + // A host system parameter is optional for vm creation. It uses a mandatory + // resource pool parameter to determine where the vm should be placed. + if flag.name == "" { + return nil, nil + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + flag.host, err = finder.HostSystem(context.TODO(), flag.name) + return flag.host, err +} + +func (flag *HostSystemFlag) HostSystem() (*object.HostSystem, error) { + host, err := flag.HostSystemIfSpecified() + if err != nil { + return nil, err + } + + if host != nil { + return host, nil + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + flag.host, err = finder.DefaultHostSystem(context.TODO()) + return flag.host, err +} + +func (flag *HostSystemFlag) HostNetworkSystem() (*object.HostNetworkSystem, error) { + host, err := flag.HostSystem() + if err != nil { + return nil, err + } + + return host.ConfigManager().NetworkSystem(context.TODO()) +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/int32.go b/vendor/github.com/vmware/govmomi/govc/flags/int32.go new file mode 100644 index 00000000000..a993c3eeac9 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/int32.go @@ -0,0 +1,72 @@ +/* +Copyright (c) 2016-2017 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "flag" + "fmt" + "strconv" +) + +// This flag type is internal to stdlib: +// https://github.com/golang/go/blob/master/src/cmd/internal/obj/flag.go +type int32Value int32 + +func (i *int32Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 32) + *i = int32Value(v) + return err +} + +func (i *int32Value) Get() interface{} { + return int32(*i) +} + +func (i *int32Value) String() string { + return fmt.Sprintf("%v", *i) +} + +// NewInt32 behaves as flag.IntVar, but using an int32 type. +func NewInt32(v *int32) flag.Value { + return (*int32Value)(v) +} + +type int32ptrValue struct { + val **int32 +} + +func (i *int32ptrValue) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 32) + *i.val = new(int32) + **i.val = int32(v) + return err +} + +func (i *int32ptrValue) Get() interface{} { + if i.val == nil || *i.val == nil { + return nil + } + return *i.val +} + +func (i *int32ptrValue) String() string { + return fmt.Sprintf("%v", i.Get()) +} + +func NewOptionalInt32(v **int32) flag.Value { + return &int32ptrValue{val: v} +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/int64.go b/vendor/github.com/vmware/govmomi/govc/flags/int64.go new file mode 100644 index 00000000000..e3b8cc5a952 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/int64.go @@ -0,0 +1,72 @@ +/* +Copyright (c) 2017 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "flag" + "fmt" + "strconv" +) + +// This flag type is internal to stdlib: +// https://github.com/golang/go/blob/master/src/cmd/internal/obj/flag.go +type int64Value int64 + +func (i *int64Value) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 64) + *i = int64Value(v) + return err +} + +func (i *int64Value) Get() interface{} { + return int64(*i) +} + +func (i *int64Value) String() string { + return fmt.Sprintf("%v", *i) +} + +// NewInt64 behaves as flag.IntVar, but using an int64 type. +func NewInt64(v *int64) flag.Value { + return (*int64Value)(v) +} + +type int64ptrValue struct { + val **int64 +} + +func (i *int64ptrValue) Set(s string) error { + v, err := strconv.ParseInt(s, 0, 64) + *i.val = new(int64) + **i.val = int64(v) + return err +} + +func (i *int64ptrValue) Get() interface{} { + if i.val == nil || *i.val == nil { + return nil + } + return **i.val +} + +func (i *int64ptrValue) String() string { + return fmt.Sprintf("%v", i.Get()) +} + +func NewOptionalInt64(v **int64) flag.Value { + return &int64ptrValue{val: v} +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/library.go b/vendor/github.com/vmware/govmomi/govc/flags/library.go new file mode 100644 index 00000000000..3b715f457f6 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/library.go @@ -0,0 +1,93 @@ +/* +Copyright (c) 2020-2022 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "fmt" + + "github.com/vmware/govmomi/vapi/library" + "github.com/vmware/govmomi/vapi/library/finder" + "github.com/vmware/govmomi/vapi/rest" +) + +// errContentLibraryMatch is an error returned when a query returns more than one result. +type errContentLibraryMatch struct { + // Type is the type of object being queried. + Type string + + // Key is the key used to perform the query. + Key string + + // Val is the value used to perform the query. + Val string + + // Count is the number of objects returned. + Count int +} + +// Error returns the error string. +func (e errContentLibraryMatch) Error() string { + kind := e.Type + if kind == "" { + kind = "library|item" + } + hint := "" + if e.Count > 1 { + hint = fmt.Sprintf(" (use %q ID instead of NAME)", kind) + } + return fmt.Sprintf("%q=%q matches %d items%s", e.Key, e.Val, e.Count, hint) +} + +func ContentLibraryResult(ctx context.Context, c *rest.Client, kind string, path string) (finder.FindResult, error) { + res, err := finder.NewFinder(library.NewManager(c)).Find(ctx, path) + if err != nil { + return nil, err + } + if len(res) != 1 { + return nil, errContentLibraryMatch{Type: kind, Key: "path", Val: path, Count: len(res)} + } + return res[0], nil +} + +// ContentLibrary attempts to find a content library with the given path, +// asserting 1 match of type library.Library. +func ContentLibrary(ctx context.Context, c *rest.Client, path string) (*library.Library, error) { + r, err := ContentLibraryResult(ctx, c, "library", path) + if err != nil { + return nil, err + } + lib, ok := r.GetResult().(library.Library) + if !ok { + return nil, fmt.Errorf("%q is a %T", path, r) + } + return &lib, nil +} + +// ContentLibraryItem attempts to find a content library with the given path, +// asserting 1 match of type library.Item. +func ContentLibraryItem(ctx context.Context, c *rest.Client, path string) (*library.Item, error) { + r, err := ContentLibraryResult(ctx, c, "item", path) + if err != nil { + return nil, err + } + item, ok := r.GetResult().(library.Item) + if !ok { + return nil, fmt.Errorf("%q is a %T", path, r) + } + return &item, nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/list.go b/vendor/github.com/vmware/govmomi/govc/flags/list.go new file mode 100644 index 00000000000..0cd874b77a1 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/list.go @@ -0,0 +1,30 @@ +/* +Copyright (c) 2019 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import "fmt" + +type StringList []string + +func (l *StringList) String() string { + return fmt.Sprint(*l) +} + +func (l *StringList) Set(value string) error { + *l = append(*l, value) + return nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/network.go b/vendor/github.com/vmware/govmomi/govc/flags/network.go new file mode 100644 index 00000000000..5e187303c0a --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/network.go @@ -0,0 +1,165 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25/types" +) + +type NetworkFlag struct { + common + + *DatacenterFlag + + name string + net object.NetworkReference + adapter string + address string + isset bool + proto string +} + +var networkFlagKey = flagKey("network") + +func NewNetworkFlag(ctx context.Context) (*NetworkFlag, context.Context) { + if v := ctx.Value(networkFlagKey); v != nil { + return v.(*NetworkFlag), ctx + } + + v := &NetworkFlag{} + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + ctx = context.WithValue(ctx, networkFlagKey, v) + return v, ctx +} + +func (flag *NetworkFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.DatacenterFlag.Register(ctx, f) + + env := "GOVC_NETWORK" + value := os.Getenv(env) + flag.name = value + usage := fmt.Sprintf("Network [%s]", env) + f.Var(flag, "net", usage) + f.StringVar(&flag.adapter, "net.adapter", "e1000", "Network adapter type") + f.StringVar(&flag.address, "net.address", "", "Network hardware address") + f.StringVar(&flag.proto, "net.protocol", "", fmt.Sprintf("Network device protocol. Applicable to vmxnet3vrdma. Default to '%s'", string(types.VirtualVmxnet3VrdmaOptionDeviceProtocolsRocev2))) + }) +} + +func (flag *NetworkFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if err := flag.DatacenterFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (flag *NetworkFlag) String() string { + return flag.name +} + +func (flag *NetworkFlag) Set(name string) error { + flag.name = name + flag.isset = true + return nil +} + +func (flag *NetworkFlag) IsSet() bool { + return flag.isset +} + +func (flag *NetworkFlag) Network() (object.NetworkReference, error) { + if flag.net != nil { + return flag.net, nil + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + if flag.net, err = finder.NetworkOrDefault(context.TODO(), flag.name); err != nil { + return nil, err + } + + return flag.net, nil +} + +func (flag *NetworkFlag) Device() (types.BaseVirtualDevice, error) { + net, err := flag.Network() + if err != nil { + return nil, err + } + + backing, err := net.EthernetCardBackingInfo(context.TODO()) + if err != nil { + return nil, err + } + + device, err := object.EthernetCardTypes().CreateEthernetCard(flag.adapter, backing) + if err != nil { + return nil, err + } + + if a, ok := device.(*types.VirtualVmxnet3Vrdma); ok { + if flag.proto != "" { + if flag.proto != string(types.VirtualVmxnet3VrdmaOptionDeviceProtocolsRocev2) && + flag.proto != string(types.VirtualVmxnet3VrdmaOptionDeviceProtocolsRocev1) { + return nil, fmt.Errorf("invalid device protocol '%s'", flag.proto) + } + a.DeviceProtocol = flag.proto + } + } else if flag.proto != "" { + return nil, fmt.Errorf("device protocol is only supported for vmxnet3vrdma at the moment") + } + + if flag.address == "-" { + card := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard() + card.AddressType = string(types.VirtualEthernetCardMacTypeGenerated) + card.MacAddress = "" + } else if flag.address != "" { + card := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard() + card.AddressType = string(types.VirtualEthernetCardMacTypeManual) + card.MacAddress = flag.address + } + + return device, nil +} + +// Change applies update backing and hardware address changes to the given network device. +func (flag *NetworkFlag) Change(device types.BaseVirtualDevice, update types.BaseVirtualDevice) { + current := device.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard() + changed := update.(types.BaseVirtualEthernetCard).GetVirtualEthernetCard() + + current.Backing = changed.Backing + + if changed.MacAddress != "" { + current.MacAddress = changed.MacAddress + } + + if changed.AddressType != "" { + current.AddressType = changed.AddressType + } +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/optional_bool.go b/vendor/github.com/vmware/govmomi/govc/flags/optional_bool.go new file mode 100644 index 00000000000..db1b81f89b8 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/optional_bool.go @@ -0,0 +1,55 @@ +/* +Copyright (c) 2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "flag" + "fmt" + "strconv" +) + +type optionalBool struct { + val **bool +} + +func (b *optionalBool) Set(s string) error { + v, err := strconv.ParseBool(s) + *b.val = &v + return err +} + +func (b *optionalBool) Get() interface{} { + if *b.val == nil { + return nil + } + return **b.val +} + +func (b *optionalBool) String() string { + if b.val == nil || *b.val == nil { + return "" + } + return fmt.Sprintf("%v", **b.val) +} + +func (b *optionalBool) IsBoolFlag() bool { return true } + +// NewOptionalBool returns a flag.Value implementation where there is no default value. +// This avoids sending a default value over the wire as using flag.BoolVar() would. +func NewOptionalBool(v **bool) flag.Value { + return &optionalBool{v} +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/optional_string.go b/vendor/github.com/vmware/govmomi/govc/flags/optional_string.go new file mode 100644 index 00000000000..0460785d03d --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/optional_string.go @@ -0,0 +1,50 @@ +/* +Copyright (c) 2023-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "flag" +) + +type optionalString struct { + val **string +} + +func (s *optionalString) Set(input string) error { + *s.val = &input + return nil +} + +func (s *optionalString) Get() interface{} { + if *s.val == nil { + return nil + } + return **s.val +} + +func (s *optionalString) String() string { + if s.val == nil || *s.val == nil { + return "" + } + return **s.val +} + +// NewOptionalString returns a flag.Value implementation where there is no default value. +// This avoids sending a default value over the wire as using flag.StringVar() would. +func NewOptionalString(v **string) flag.Value { + return &optionalString{v} +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/output.go b/vendor/github.com/vmware/govmomi/govc/flags/output.go new file mode 100644 index 00000000000..c0338b18c3b --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/output.go @@ -0,0 +1,384 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "encoding/json" + "errors" + "flag" + "fmt" + "io" + "os" + "reflect" + "strings" + "sync" + "time" + + "github.com/dougm/pretty" + + "github.com/vmware/govmomi/task" + "github.com/vmware/govmomi/vim25/progress" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" + "github.com/vmware/govmomi/vim25/xml" +) + +type OutputWriter interface { + Write(io.Writer) error +} + +type OutputFlag struct { + common + + JSON bool + XML bool + TTY bool + Dump bool + Out io.Writer + + formatError bool + formatIndent bool +} + +var outputFlagKey = flagKey("output") + +func NewOutputFlag(ctx context.Context) (*OutputFlag, context.Context) { + if v := ctx.Value(outputFlagKey); v != nil { + return v.(*OutputFlag), ctx + } + + v := &OutputFlag{Out: os.Stdout} + ctx = context.WithValue(ctx, outputFlagKey, v) + return v, ctx +} + +func (flag *OutputFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + f.BoolVar(&flag.JSON, "json", false, "Enable JSON output") + f.BoolVar(&flag.XML, "xml", false, "Enable XML output") + f.BoolVar(&flag.Dump, "dump", false, "Enable Go output") + // Avoid adding more flags for now.. + flag.formatIndent = os.Getenv("GOVC_INDENT") != "false" // Default to indented output + flag.formatError = os.Getenv("GOVC_FORMAT_ERROR") != "false" // Default to formatted errors + }) +} + +func (flag *OutputFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if !flag.All() { + // Assume we have a tty if not outputting JSON + flag.TTY = true + } + + return nil + }) +} + +// Log outputs the specified string, prefixed with the current time. +// A newline is not automatically added. If the specified string +// starts with a '\r', the current line is cleared first. +func (flag *OutputFlag) Log(s string) (int, error) { + if len(s) > 0 && s[0] == '\r' { + flag.Write([]byte{'\r', 033, '[', 'K'}) + s = s[1:] + } + + return flag.WriteString(time.Now().Format("[02-01-06 15:04:05] ") + s) +} + +func (flag *OutputFlag) Write(b []byte) (int, error) { + if !flag.TTY { + return 0, nil + } + + w := flag.Out + if w == nil { + w = os.Stdout + } + n, err := w.Write(b) + if w == os.Stdout { + os.Stdout.Sync() + } + return n, err +} + +func (flag *OutputFlag) WriteString(s string) (int, error) { + return flag.Write([]byte(s)) +} + +func (flag *OutputFlag) All() bool { + return flag.JSON || flag.XML || flag.Dump +} + +func dumpValue(val interface{}) interface{} { + type dumper interface { + Dump() interface{} + } + + if d, ok := val.(dumper); ok { + return d.Dump() + } + + rval := reflect.ValueOf(val) + if rval.Type().Kind() != reflect.Ptr { + return val + } + + rval = rval.Elem() + if rval.Type().Kind() == reflect.Struct { + f := rval.Field(0) + if f.Type().Kind() == reflect.Slice { + // common case for the various 'type infoResult' + if f.Len() == 1 { + return f.Index(0).Interface() + } + return f.Interface() + } + + if rval.NumField() == 1 && rval.Type().Field(0).Anonymous { + // common case where govc type wraps govmomi type to implement OutputWriter + return f.Interface() + } + } + + return val +} + +func (flag *OutputFlag) WriteResult(result OutputWriter) error { + var err error + + switch { + case flag.Dump: + format := "%#v\n" + if flag.formatIndent { + format = "%# v\n" + } + _, err = pretty.Fprintf(flag.Out, format, dumpValue(result)) + case flag.JSON: + e := json.NewEncoder(flag.Out) + if flag.formatIndent { + e.SetIndent("", " ") + } + err = e.Encode(result) + case flag.XML: + e := xml.NewEncoder(flag.Out) + if flag.formatIndent { + e.Indent("", " ") + } + err = e.Encode(dumpValue(result)) + if err == nil { + fmt.Fprintln(flag.Out) + } + default: + err = result.Write(flag.Out) + } + + return err +} + +func (flag *OutputFlag) WriteError(err error) bool { + if flag.formatError { + flag.Out = os.Stderr + return flag.WriteResult(&errorOutput{err}) == nil + } + return false +} + +type errorOutput struct { + error +} + +func (e errorOutput) Write(w io.Writer) error { + reason := e.error.Error() + var messages []string + var faults []types.LocalizableMessage + + switch err := e.error.(type) { + case task.Error: + faults = err.LocalizedMethodFault.Fault.GetMethodFault().FaultMessage + if err.Description != nil { + reason = fmt.Sprintf("%s (%s)", reason, err.Description.Message) + } + default: + if soap.IsSoapFault(err) { + detail := soap.ToSoapFault(err).Detail.Fault + if f, ok := detail.(types.BaseMethodFault); ok { + faults = f.GetMethodFault().FaultMessage + } + } + } + + for _, m := range faults { + if m.Message != "" && !strings.HasPrefix(m.Message, "[context]") { + messages = append(messages, fmt.Sprintf("%s (%s)", m.Message, m.Key)) + } + } + + messages = append(messages, reason) + + for _, message := range messages { + if _, err := fmt.Fprintf(w, "%s: %s\n", os.Args[0], message); err != nil { + return err + } + } + + return nil +} + +func (e errorOutput) Dump() interface{} { + if f, ok := e.error.(task.Error); ok { + return f.LocalizedMethodFault + } + if soap.IsSoapFault(e.error) { + return soap.ToSoapFault(e.error) + } + if soap.IsVimFault(e.error) { + return soap.ToVimFault(e.error) + } + return e +} + +func (e errorOutput) canEncode() bool { + switch e.error.(type) { + case task.Error: + return true + } + return soap.IsSoapFault(e.error) || soap.IsVimFault(e.error) +} + +// cannotEncode causes cli.Run to output err.Error() as it would without an error format specified +var cannotEncode = errors.New("cannot encode error") + +func (e errorOutput) MarshalJSON() ([]byte, error) { + _, ok := e.error.(json.Marshaler) + if ok || e.canEncode() { + return json.Marshal(e.error) + } + return nil, cannotEncode +} + +func (e errorOutput) MarshalXML(encoder *xml.Encoder, start xml.StartElement) error { + _, ok := e.error.(xml.Marshaler) + if ok || e.canEncode() { + return encoder.Encode(e.error) + } + return cannotEncode +} + +type progressLogger struct { + flag *OutputFlag + prefix string + + wg sync.WaitGroup + + sink chan chan progress.Report + done chan struct{} +} + +func newProgressLogger(flag *OutputFlag, prefix string) *progressLogger { + p := &progressLogger{ + flag: flag, + prefix: prefix, + + sink: make(chan chan progress.Report), + done: make(chan struct{}), + } + + p.wg.Add(1) + + go p.loopA() + + return p +} + +// loopA runs before Sink() has been called. +func (p *progressLogger) loopA() { + var err error + + defer p.wg.Done() + + tick := time.NewTicker(100 * time.Millisecond) + defer tick.Stop() + + called := false + + for stop := false; !stop; { + select { + case ch := <-p.sink: + err = p.loopB(tick, ch) + stop = true + called = true + case <-p.done: + stop = true + case <-tick.C: + line := fmt.Sprintf("\r%s", p.prefix) + p.flag.Log(line) + } + } + + if err != nil && err != io.EOF { + p.flag.Log(fmt.Sprintf("\r%sError: %s\n", p.prefix, err)) + } else if called { + p.flag.Log(fmt.Sprintf("\r%sOK\n", p.prefix)) + } +} + +// loopA runs after Sink() has been called. +func (p *progressLogger) loopB(tick *time.Ticker, ch <-chan progress.Report) error { + var r progress.Report + var ok bool + var err error + + for ok = true; ok; { + select { + case r, ok = <-ch: + if !ok { + break + } + err = r.Error() + case <-tick.C: + line := fmt.Sprintf("\r%s", p.prefix) + if r != nil { + line += fmt.Sprintf("(%.0f%%", r.Percentage()) + detail := r.Detail() + if detail != "" { + line += fmt.Sprintf(", %s", detail) + } + line += ")" + } + p.flag.Log(line) + } + } + + return err +} + +func (p *progressLogger) Sink() chan<- progress.Report { + ch := make(chan progress.Report) + p.sink <- ch + return ch +} + +func (p *progressLogger) Wait() { + close(p.done) + p.wg.Wait() +} + +func (flag *OutputFlag) ProgressLogger(prefix string) *progressLogger { + return newProgressLogger(flag, prefix) +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/resource_allocation_info.go b/vendor/github.com/vmware/govmomi/govc/flags/resource_allocation_info.go new file mode 100644 index 00000000000..99a262ec458 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/resource_allocation_info.go @@ -0,0 +1,85 @@ +/* +Copyright (c) 2017 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "strconv" + "strings" + + "github.com/vmware/govmomi/vim25/types" +) + +type sharesInfo types.SharesInfo + +func (s *sharesInfo) String() string { + return string(s.Level) +} + +func (s *sharesInfo) Set(val string) error { + switch val { + case string(types.SharesLevelNormal), string(types.SharesLevelLow), string(types.SharesLevelHigh): + s.Level = types.SharesLevel(val) + default: + n, err := strconv.Atoi(val) + if err != nil { + return err + } + + s.Level = types.SharesLevelCustom + s.Shares = int32(n) + } + + return nil +} + +type ResourceAllocationFlag struct { + cpu, mem *types.ResourceAllocationInfo + ExpandableReservation bool +} + +func NewResourceAllocationFlag(cpu, mem *types.ResourceAllocationInfo) *ResourceAllocationFlag { + return &ResourceAllocationFlag{cpu, mem, true} +} + +func (r *ResourceAllocationFlag) Register(ctx context.Context, f *flag.FlagSet) { + opts := []struct { + name string + units string + *types.ResourceAllocationInfo + }{ + {"CPU", "MHz", r.cpu}, + {"Memory", "MB", r.mem}, + } + + for _, opt := range opts { + prefix := strings.ToLower(opt.name)[:3] + shares := (*sharesInfo)(opt.Shares) + + f.Var(NewOptionalInt64(&opt.Limit), prefix+".limit", opt.name+" limit in "+opt.units) + f.Var(NewOptionalInt64(&opt.Reservation), prefix+".reservation", opt.name+" reservation in "+opt.units) + if r.ExpandableReservation { + f.Var(NewOptionalBool(&opt.ExpandableReservation), prefix+".expandable", opt.name+" expandable reservation") + } + f.Var(shares, prefix+".shares", opt.name+" shares level or number") + } +} + +func (s *ResourceAllocationFlag) Process(ctx context.Context) error { + return nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/resource_pool.go b/vendor/github.com/vmware/govmomi/govc/flags/resource_pool.go new file mode 100644 index 00000000000..b3d87b71973 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/resource_pool.go @@ -0,0 +1,106 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/find" + "github.com/vmware/govmomi/object" +) + +type ResourcePoolFlag struct { + common + + *DatacenterFlag + + name string + pool *object.ResourcePool +} + +var resourcePoolFlagKey = flagKey("resourcePool") + +func NewResourcePoolFlag(ctx context.Context) (*ResourcePoolFlag, context.Context) { + if v := ctx.Value(resourcePoolFlagKey); v != nil { + return v.(*ResourcePoolFlag), ctx + } + + v := &ResourcePoolFlag{} + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + ctx = context.WithValue(ctx, resourcePoolFlagKey, v) + return v, ctx +} + +func (flag *ResourcePoolFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.DatacenterFlag.Register(ctx, f) + + env := "GOVC_RESOURCE_POOL" + value := os.Getenv(env) + usage := fmt.Sprintf("Resource pool [%s]", env) + f.StringVar(&flag.name, "pool", value, usage) + }) +} + +func (flag *ResourcePoolFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if err := flag.DatacenterFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (flag *ResourcePoolFlag) IsSet() bool { + return flag.name != "" +} + +func (flag *ResourcePoolFlag) ResourcePool() (*object.ResourcePool, error) { + if flag.pool != nil { + return flag.pool, nil + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + flag.pool, err = finder.ResourcePoolOrDefault(context.TODO(), flag.name) + if err != nil { + if _, ok := err.(*find.NotFoundError); ok { + vapp, verr := finder.VirtualApp(context.TODO(), flag.name) + if verr != nil { + return nil, err + } + flag.pool = vapp.ResourcePool + } else { + return nil, err + } + } + + return flag.pool, nil +} + +func (flag *ResourcePoolFlag) ResourcePoolIfSpecified() (*object.ResourcePool, error) { + if flag.name == "" { + return nil, nil + } + return flag.ResourcePool() +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/search.go b/vendor/github.com/vmware/govmomi/govc/flags/search.go new file mode 100644 index 00000000000..ba884090a74 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/search.go @@ -0,0 +1,438 @@ +/* +Copyright (c) 2014-2016 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "errors" + "flag" + "fmt" + "strings" + + "github.com/vmware/govmomi/find" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" +) + +const ( + SearchVirtualMachines = iota + 1 + SearchHosts + SearchVirtualApps +) + +type SearchFlag struct { + common + + *ClientFlag + *DatacenterFlag + + t int + entity string + + byDatastorePath string + byDNSName string + byInventoryPath string + byIP string + byUUID string + + isset bool +} + +func NewSearchFlag(ctx context.Context, t int) (*SearchFlag, context.Context) { + searchFlagKey := flagKey(fmt.Sprintf("search%d", t)) + + if v := ctx.Value(searchFlagKey); v != nil { + return v.(*SearchFlag), ctx + } + + v := &SearchFlag{ + t: t, + } + + v.ClientFlag, ctx = NewClientFlag(ctx) + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + + switch t { + case SearchVirtualMachines: + v.entity = "VM" + case SearchHosts: + v.entity = "host" + case SearchVirtualApps: + v.entity = "vapp" + default: + panic("invalid search type") + } + + ctx = context.WithValue(ctx, searchFlagKey, v) + return v, ctx +} + +func (flag *SearchFlag) Register(ctx context.Context, fs *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.ClientFlag.Register(ctx, fs) + flag.DatacenterFlag.Register(ctx, fs) + + register := func(v *string, f string, d string) { + f = fmt.Sprintf("%s.%s", strings.ToLower(flag.entity), f) + d = fmt.Sprintf(d, flag.entity) + fs.StringVar(v, f, "", d) + } + + switch flag.t { + case SearchVirtualMachines: + register(&flag.byDatastorePath, "path", "Find %s by path to .vmx file") + } + + switch flag.t { + case SearchVirtualMachines, SearchHosts: + register(&flag.byDNSName, "dns", "Find %s by FQDN") + register(&flag.byIP, "ip", "Find %s by IP address") + register(&flag.byUUID, "uuid", "Find %s by UUID") + } + + register(&flag.byInventoryPath, "ipath", "Find %s by inventory path") + }) +} + +func (flag *SearchFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if err := flag.ClientFlag.Process(ctx); err != nil { + return err + } + if err := flag.DatacenterFlag.Process(ctx); err != nil { + return err + } + + flags := []string{ + flag.byDatastorePath, + flag.byDNSName, + flag.byInventoryPath, + flag.byIP, + flag.byUUID, + } + + flag.isset = false + for _, f := range flags { + if f != "" { + if flag.isset { + return errors.New("cannot use more than one search flag") + } + flag.isset = true + } + } + + return nil + }) +} + +func (flag *SearchFlag) IsSet() bool { + return flag.isset +} + +func (flag *SearchFlag) searchIndex(c *vim25.Client) *object.SearchIndex { + return object.NewSearchIndex(c) +} + +func (flag *SearchFlag) searchByDatastorePath(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { + ctx := context.TODO() + switch flag.t { + case SearchVirtualMachines: + return flag.searchIndex(c).FindByDatastorePath(ctx, dc, flag.byDatastorePath) + default: + panic("unsupported type") + } +} + +func (flag *SearchFlag) searchByDNSName(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { + ctx := context.TODO() + switch flag.t { + case SearchVirtualMachines: + return flag.searchIndex(c).FindByDnsName(ctx, dc, flag.byDNSName, true) + case SearchHosts: + return flag.searchIndex(c).FindByDnsName(ctx, dc, flag.byDNSName, false) + default: + panic("unsupported type") + } +} + +func (flag *SearchFlag) searchByInventoryPath(c *vim25.Client) (object.Reference, error) { + ctx := context.TODO() + return flag.searchIndex(c).FindByInventoryPath(ctx, flag.byInventoryPath) +} + +func (flag *SearchFlag) searchByIP(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { + ctx := context.TODO() + switch flag.t { + case SearchVirtualMachines: + return flag.searchIndex(c).FindByIp(ctx, dc, flag.byIP, true) + case SearchHosts: + return flag.searchIndex(c).FindByIp(ctx, dc, flag.byIP, false) + default: + panic("unsupported type") + } +} + +func (flag *SearchFlag) searchByUUID(c *vim25.Client, dc *object.Datacenter) (object.Reference, error) { + ctx := context.TODO() + isVM := false + switch flag.t { + case SearchVirtualMachines: + isVM = true + case SearchHosts: + default: + panic("unsupported type") + } + + var ref object.Reference + var err error + + for _, iu := range []*bool{nil, types.NewBool(true)} { + ref, err = flag.searchIndex(c).FindByUuid(ctx, dc, flag.byUUID, isVM, iu) + if err != nil { + if soap.IsSoapFault(err) { + fault := soap.ToSoapFault(err).VimFault() + if _, ok := fault.(types.InvalidArgument); ok { + continue + } + } + return nil, err + } + if ref != nil { + break + } + } + + return ref, nil +} + +func (flag *SearchFlag) search() (object.Reference, error) { + ctx := context.TODO() + var ref object.Reference + var err error + var dc *object.Datacenter + + c, err := flag.Client() + if err != nil { + return nil, err + } + + isPath := flag.byInventoryPath != "" + if !isPath { + // All other SearchIndex methods require a Datacenter param + dc, err = flag.Datacenter() + if err != nil { + return nil, err + } + } + + switch { + case isPath: + ref, err = flag.searchByInventoryPath(c) + case flag.byDatastorePath != "": + ref, err = flag.searchByDatastorePath(c, dc) + case flag.byDNSName != "": + ref, err = flag.searchByDNSName(c, dc) + case flag.byIP != "": + ref, err = flag.searchByIP(c, dc) + case flag.byUUID != "": + ref, err = flag.searchByUUID(c, dc) + default: + err = errors.New("no search flag specified") + } + + if err != nil { + return nil, err + } + + if ref == nil { + return nil, fmt.Errorf("no such %s", flag.entity) + } + + // set the InventoryPath field + finder, err := flag.Finder() + if err != nil { + return nil, err + } + ref, err = finder.ObjectReference(ctx, ref.Reference()) + if err != nil { + return nil, err + } + + return ref, nil +} + +func (flag *SearchFlag) VirtualMachine() (*object.VirtualMachine, error) { + ref, err := flag.search() + if err != nil { + return nil, err + } + + vm, ok := ref.(*object.VirtualMachine) + if !ok { + return nil, fmt.Errorf("expected VirtualMachine entity, got %s", ref.Reference().Type) + } + + return vm, nil +} + +func (flag *SearchFlag) VirtualMachines(args []string) ([]*object.VirtualMachine, error) { + ctx := context.TODO() + var out []*object.VirtualMachine + + if flag.IsSet() { + vm, err := flag.VirtualMachine() + if err != nil { + return nil, err + } + + out = append(out, vm) + return out, nil + } + + // List virtual machines + if len(args) == 0 { + return nil, errors.New("no argument") + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + var nfe error + + // List virtual machines for every argument + for _, arg := range args { + vms, err := finder.VirtualMachineList(ctx, arg) + if err != nil { + if _, ok := err.(*find.NotFoundError); ok { + // Let caller decide how to handle NotFoundError + nfe = err + continue + } + return nil, err + } + + out = append(out, vms...) + } + + return out, nfe +} + +func (flag *SearchFlag) VirtualApp() (*object.VirtualApp, error) { + ref, err := flag.search() + if err != nil { + return nil, err + } + + app, ok := ref.(*object.VirtualApp) + if !ok { + return nil, fmt.Errorf("expected VirtualApp entity, got %s", ref.Reference().Type) + } + + return app, nil +} + +func (flag *SearchFlag) VirtualApps(args []string) ([]*object.VirtualApp, error) { + ctx := context.TODO() + var out []*object.VirtualApp + + if flag.IsSet() { + app, err := flag.VirtualApp() + if err != nil { + return nil, err + } + + out = append(out, app) + return out, nil + } + + // List virtual apps + if len(args) == 0 { + return nil, errors.New("no argument") + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + // List virtual apps for every argument + for _, arg := range args { + apps, err := finder.VirtualAppList(ctx, arg) + if err != nil { + return nil, err + } + + out = append(out, apps...) + } + + return out, nil +} + +func (flag *SearchFlag) HostSystem() (*object.HostSystem, error) { + ref, err := flag.search() + if err != nil { + return nil, err + } + + host, ok := ref.(*object.HostSystem) + if !ok { + return nil, fmt.Errorf("expected HostSystem entity, got %s", ref.Reference().Type) + } + + return host, nil +} + +func (flag *SearchFlag) HostSystems(args []string) ([]*object.HostSystem, error) { + ctx := context.TODO() + var out []*object.HostSystem + + if flag.IsSet() { + host, err := flag.HostSystem() + if err != nil { + return nil, err + } + + out = append(out, host) + return out, nil + } + + // List host system + if len(args) == 0 { + return nil, errors.New("no argument") + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + // List host systems for every argument + for _, arg := range args { + vms, err := finder.HostSystemList(ctx, arg) + if err != nil { + return nil, err + } + + out = append(out, vms...) + } + + return out, nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/storage_pod.go b/vendor/github.com/vmware/govmomi/govc/flags/storage_pod.go new file mode 100644 index 00000000000..a7631486f89 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/storage_pod.go @@ -0,0 +1,94 @@ +/* +Copyright (c) 2014-2022 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/object" +) + +type StoragePodFlag struct { + common + + *DatacenterFlag + + Name string + + sp *object.StoragePod +} + +var storagePodFlagKey = flagKey("storagePod") + +func NewStoragePodFlag(ctx context.Context) (*StoragePodFlag, context.Context) { + if v := ctx.Value(storagePodFlagKey); v != nil { + return v.(*StoragePodFlag), ctx + } + + v := &StoragePodFlag{} + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + ctx = context.WithValue(ctx, storagePodFlagKey, v) + return v, ctx +} + +func (f *StoragePodFlag) Register(ctx context.Context, fs *flag.FlagSet) { + f.RegisterOnce(func() { + f.DatacenterFlag.Register(ctx, fs) + + env := "GOVC_DATASTORE_CLUSTER" + value := os.Getenv(env) + usage := fmt.Sprintf("Datastore cluster [%s]", env) + fs.StringVar(&f.Name, "datastore-cluster", value, usage) + }) +} + +func (f *StoragePodFlag) Process(ctx context.Context) error { + return f.DatacenterFlag.Process(ctx) +} + +func (f *StoragePodFlag) Isset() bool { + return f.Name != "" +} + +func (f *StoragePodFlag) StoragePod() (*object.StoragePod, error) { + ctx := context.TODO() + if f.sp != nil { + return f.sp, nil + } + + finder, err := f.Finder() + if err != nil { + return nil, err + } + + if f.Isset() { + f.sp, err = finder.DatastoreCluster(ctx, f.Name) + if err != nil { + return nil, err + } + } else { + f.sp, err = finder.DefaultDatastoreCluster(ctx) + if err != nil { + return nil, err + } + } + + return f.sp, nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/version.go b/vendor/github.com/vmware/govmomi/govc/flags/version.go new file mode 100644 index 00000000000..72d0772b03e --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/version.go @@ -0,0 +1,71 @@ +/* +Copyright (c) 2014-2020 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "strconv" + "strings" +) + +var ( + BuildVersion = "v0.0.0" // govc-test requires an (arbitrary) version set + BuildCommit string + BuildDate string +) + +type version []int + +func ParseVersion(s string) (version, error) { + // remove any trailing "v" version identifier + s = strings.TrimPrefix(s, "v") + v := make(version, 0) + + ds := strings.Split(s, "-") + ps := strings.Split(ds[0], ".") + for _, p := range ps { + i, err := strconv.Atoi(p) + if err != nil { + return nil, err + } + + v = append(v, i) + } + + return v, nil +} + +func (v version) Lte(u version) bool { + lv := len(v) + lu := len(u) + + for i := 0; i < lv; i++ { + // Everything up to here has been equal and v has more elements than u. + if i >= lu { + return false + } + + // Move to next digit if equal. + if v[i] == u[i] { + continue + } + + return v[i] < u[i] + } + + // Equal. + return true +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/virtual_app.go b/vendor/github.com/vmware/govmomi/govc/flags/virtual_app.go new file mode 100644 index 00000000000..88a0b9cbfe2 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/virtual_app.go @@ -0,0 +1,106 @@ +/* +Copyright (c) 2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/object" +) + +type VirtualAppFlag struct { + common + + *DatacenterFlag + *SearchFlag + + name string + app *object.VirtualApp +} + +var virtualAppFlagKey = flagKey("virtualApp") + +func NewVirtualAppFlag(ctx context.Context) (*VirtualAppFlag, context.Context) { + if v := ctx.Value(virtualAppFlagKey); v != nil { + return v.(*VirtualAppFlag), ctx + } + + v := &VirtualAppFlag{} + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualApps) + ctx = context.WithValue(ctx, virtualAppFlagKey, v) + return v, ctx +} + +func (flag *VirtualAppFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.DatacenterFlag.Register(ctx, f) + flag.SearchFlag.Register(ctx, f) + + env := "GOVC_VAPP" + value := os.Getenv(env) + usage := fmt.Sprintf("Virtual App [%s]", env) + f.StringVar(&flag.name, "vapp", value, usage) + }) +} + +func (flag *VirtualAppFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if err := flag.DatacenterFlag.Process(ctx); err != nil { + return err + } + if err := flag.SearchFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (flag *VirtualAppFlag) VirtualApp() (*object.VirtualApp, error) { + ctx := context.TODO() + + if flag.app != nil { + return flag.app, nil + } + + // Use search flags if specified. + if flag.SearchFlag.IsSet() { + app, err := flag.SearchFlag.VirtualApp() + if err != nil { + return nil, err + } + + flag.app = app + return flag.app, nil + } + + // Never look for a default virtual app. + if flag.name == "" { + return nil, nil + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + flag.app, err = finder.VirtualApp(ctx, flag.name) + return flag.app, err +} diff --git a/vendor/github.com/vmware/govmomi/govc/flags/virtual_machine.go b/vendor/github.com/vmware/govmomi/govc/flags/virtual_machine.go new file mode 100644 index 00000000000..e0b1acae8c8 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/flags/virtual_machine.go @@ -0,0 +1,112 @@ +/* +Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package flags + +import ( + "context" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/object" +) + +type VirtualMachineFlag struct { + common + + *ClientFlag + *DatacenterFlag + *SearchFlag + + name string + vm *object.VirtualMachine +} + +var virtualMachineFlagKey = flagKey("virtualMachine") + +func NewVirtualMachineFlag(ctx context.Context) (*VirtualMachineFlag, context.Context) { + if v := ctx.Value(virtualMachineFlagKey); v != nil { + return v.(*VirtualMachineFlag), ctx + } + + v := &VirtualMachineFlag{} + v.ClientFlag, ctx = NewClientFlag(ctx) + v.DatacenterFlag, ctx = NewDatacenterFlag(ctx) + v.SearchFlag, ctx = NewSearchFlag(ctx, SearchVirtualMachines) + ctx = context.WithValue(ctx, virtualMachineFlagKey, v) + return v, ctx +} + +func (flag *VirtualMachineFlag) Register(ctx context.Context, f *flag.FlagSet) { + flag.RegisterOnce(func() { + flag.ClientFlag.Register(ctx, f) + flag.DatacenterFlag.Register(ctx, f) + flag.SearchFlag.Register(ctx, f) + + env := "GOVC_VM" + value := os.Getenv(env) + usage := fmt.Sprintf("Virtual machine [%s]", env) + f.StringVar(&flag.name, "vm", value, usage) + }) +} + +func (flag *VirtualMachineFlag) Process(ctx context.Context) error { + return flag.ProcessOnce(func() error { + if err := flag.ClientFlag.Process(ctx); err != nil { + return err + } + if err := flag.DatacenterFlag.Process(ctx); err != nil { + return err + } + if err := flag.SearchFlag.Process(ctx); err != nil { + return err + } + return nil + }) +} + +func (flag *VirtualMachineFlag) VirtualMachine() (*object.VirtualMachine, error) { + ctx := context.TODO() + + if flag.vm != nil { + return flag.vm, nil + } + + // Use search flags if specified. + if flag.SearchFlag.IsSet() { + vm, err := flag.SearchFlag.VirtualMachine() + if err != nil { + return nil, err + } + + flag.vm = vm + return flag.vm, nil + } + + // Never look for a default virtual machine. + if flag.name == "" { + return nil, nil + } + + finder, err := flag.Finder() + if err != nil { + return nil, err + } + + flag.vm, err = finder.VirtualMachine(ctx, flag.name) + return flag.vm, err +} diff --git a/vendor/github.com/vmware/govmomi/govc/importx/archive.go b/vendor/github.com/vmware/govmomi/govc/importx/archive.go new file mode 100644 index 00000000000..fef36abdcb4 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/importx/archive.go @@ -0,0 +1,205 @@ +/* +Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package importx + +import ( + "archive/tar" + "bytes" + "context" + "errors" + "flag" + "fmt" + "io" + "net/url" + "os" + "path" + "path/filepath" + "strings" + + "github.com/vmware/govmomi/ovf" + "github.com/vmware/govmomi/vapi/library" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" +) + +// ArchiveFlag doesn't register any flags; +// only encapsulates some common archive related functionality. +type ArchiveFlag struct { + Archive + + manifest map[string]*library.Checksum +} + +func newArchiveFlag(ctx context.Context) (*ArchiveFlag, context.Context) { + return &ArchiveFlag{}, ctx +} + +func (f *ArchiveFlag) Register(ctx context.Context, fs *flag.FlagSet) { +} + +func (f *ArchiveFlag) Process(ctx context.Context) error { + return nil +} + +func (f *ArchiveFlag) ReadOvf(fpath string) ([]byte, error) { + r, _, err := f.Open(fpath) + if err != nil { + return nil, err + } + defer r.Close() + + return io.ReadAll(r) +} + +func (f *ArchiveFlag) ReadEnvelope(data []byte) (*ovf.Envelope, error) { + e, err := ovf.Unmarshal(bytes.NewReader(data)) + if err != nil { + return nil, fmt.Errorf("failed to parse ovf: %s", err) + } + + return e, nil +} + +func (f *ArchiveFlag) readManifest(fpath string) error { + base := filepath.Base(fpath) + ext := filepath.Ext(base) + mfName := strings.Replace(base, ext, ".mf", 1) + + mf, _, err := f.Open(mfName) + if err != nil { + msg := fmt.Sprintf("manifest %q: %s", mf, err) + fmt.Fprintln(os.Stderr, msg) + return errors.New(msg) + } + f.manifest, err = library.ReadManifest(mf) + _ = mf.Close() + return err +} + +type Archive interface { + Open(string) (io.ReadCloser, int64, error) +} + +type TapeArchive struct { + Path string + Opener +} + +type TapeArchiveEntry struct { + io.Reader + f io.Closer + + Name string +} + +func (t *TapeArchiveEntry) Close() error { + return t.f.Close() +} + +func (t *TapeArchive) Open(name string) (io.ReadCloser, int64, error) { + f, _, err := t.OpenFile(t.Path) + if err != nil { + return nil, 0, err + } + + r := tar.NewReader(f) + + for { + h, err := r.Next() + if err == io.EOF { + break + } + if err != nil { + return nil, 0, err + } + + matched, err := path.Match(name, path.Base(h.Name)) + if err != nil { + return nil, 0, err + } + + if matched { + return &TapeArchiveEntry{r, f, h.Name}, h.Size, nil + } + } + + _ = f.Close() + + return nil, 0, os.ErrNotExist +} + +type FileArchive struct { + Path string + Opener +} + +func (t *FileArchive) Open(name string) (io.ReadCloser, int64, error) { + fpath := name + if name != t.Path { + index := strings.LastIndex(t.Path, "/") + if index != -1 { + fpath = t.Path[:index] + "/" + name + } + } + + return t.OpenFile(fpath) +} + +type Opener struct { + *vim25.Client +} + +func isRemotePath(path string) bool { + if strings.HasPrefix(path, "http://") || strings.HasPrefix(path, "https://") { + return true + } + return false +} + +func (o Opener) OpenLocal(path string) (io.ReadCloser, int64, error) { + f, err := os.Open(filepath.Clean(path)) + if err != nil { + return nil, 0, err + } + + s, err := f.Stat() + if err != nil { + return nil, 0, err + } + + return f, s.Size(), nil +} + +func (o Opener) OpenFile(path string) (io.ReadCloser, int64, error) { + if isRemotePath(path) { + return o.OpenRemote(path) + } + return o.OpenLocal(path) +} + +func (o Opener) OpenRemote(link string) (io.ReadCloser, int64, error) { + if o.Client == nil { + return nil, 0, errors.New("remote path not supported") + } + + u, err := url.Parse(link) + if err != nil { + return nil, 0, err + } + + return o.Download(context.Background(), u, &soap.DefaultDownload) +} diff --git a/vendor/github.com/vmware/govmomi/govc/importx/importable.go b/vendor/github.com/vmware/govmomi/govc/importx/importable.go new file mode 100644 index 00000000000..14e31670b0a --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/importx/importable.go @@ -0,0 +1,59 @@ +/* +Copyright (c) 2014 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package importx + +import ( + "fmt" + "path" +) + +type importable struct { + localPath string + remotePath string +} + +func (i importable) Ext() string { + return path.Ext(i.localPath) +} + +func (i importable) Base() string { + return path.Base(i.localPath) +} + +func (i importable) BaseClean() string { + b := i.Base() + e := i.Ext() + return b[:len(b)-len(e)] +} + +func (i importable) RemoteSrcVMDK() string { + file := fmt.Sprintf("%s-src.vmdk", i.BaseClean()) + return i.toRemotePath(file) +} + +func (i importable) RemoteDstVMDK() string { + file := fmt.Sprintf("%s.vmdk", i.BaseClean()) + return i.toRemotePath(file) +} + +func (i importable) toRemotePath(p string) string { + if i.remotePath == "" { + return p + } + + return path.Join(i.remotePath, p) +} diff --git a/vendor/github.com/vmware/govmomi/govc/importx/options.go b/vendor/github.com/vmware/govmomi/govc/importx/options.go new file mode 100644 index 00000000000..3d8190ec028 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/importx/options.go @@ -0,0 +1,236 @@ +/* +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package importx + +import ( + "context" + "encoding/json" + "flag" + "fmt" + "os" + + "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/ovf" + "github.com/vmware/govmomi/vim25/types" +) + +type KeyValue struct { + Key string + Value string +} + +// case insensitive for Key + Value +func (kv *KeyValue) UnmarshalJSON(b []byte) error { + e := struct { + types.KeyValue + Key *string + Value *string + }{ + types.KeyValue{}, &kv.Key, &kv.Value, + } + + err := json.Unmarshal(b, &e) + if err != nil { + return err + } + + if kv.Key == "" { + kv.Key = e.KeyValue.Key // "key" + } + + if kv.Value == "" { + kv.Value = e.KeyValue.Value // "value" + } + + return nil +} + +type Property struct { + KeyValue + Spec *ovf.Property `json:",omitempty"` +} + +type Network struct { + Name string + Network string +} + +type Options struct { + AllDeploymentOptions []string `json:",omitempty"` + Deployment string `json:",omitempty"` + + AllDiskProvisioningOptions []string `json:",omitempty"` + DiskProvisioning string + + AllIPAllocationPolicyOptions []string `json:",omitempty"` + IPAllocationPolicy string + + AllIPProtocolOptions []string `json:",omitempty"` + IPProtocol string + + PropertyMapping []Property `json:",omitempty"` + + NetworkMapping []Network `json:",omitempty"` + + Annotation string `json:",omitempty"` + + MarkAsTemplate bool + PowerOn bool + InjectOvfEnv bool + WaitForIP bool + Name *string +} + +type OptionsFlag struct { + Options Options + + path string +} + +func newOptionsFlag(ctx context.Context) (*OptionsFlag, context.Context) { + return &OptionsFlag{}, ctx +} + +func (flag *OptionsFlag) Register(ctx context.Context, f *flag.FlagSet) { + f.StringVar(&flag.path, "options", "", "Options spec file path for VM deployment") +} + +func (flag *OptionsFlag) Process(ctx context.Context) error { + if len(flag.path) == 0 { + return nil + } + + var err error + in := os.Stdin + + if flag.path != "-" { + in, err = os.Open(flag.path) + if err != nil { + return err + } + defer in.Close() + } + + return json.NewDecoder(in).Decode(&flag.Options) +} + +func (flag *OptionsFlag) powerOn(vm *object.VirtualMachine, out *flags.OutputFlag) error { + if !flag.Options.PowerOn || flag.Options.MarkAsTemplate { + return nil + } + + out.Log("Powering on VM...\n") + + task, err := vm.PowerOn(context.Background()) + if err != nil { + return err + } + + return task.Wait(context.Background()) +} + +func (flag *OptionsFlag) markAsTemplate(vm *object.VirtualMachine, out *flags.OutputFlag) error { + if !flag.Options.MarkAsTemplate { + return nil + } + + out.Log("Marking VM as template...\n") + + return vm.MarkAsTemplate(context.Background()) +} + +func (flag *OptionsFlag) injectOvfEnv(vm *object.VirtualMachine, out *flags.OutputFlag) error { + if !flag.Options.InjectOvfEnv { + return nil + } + + out.Log("Injecting OVF environment...\n") + + var opts []types.BaseOptionValue + + a := vm.Client().ServiceContent.About + + // build up Environment in order to marshal to xml + var props []ovf.EnvProperty + for _, p := range flag.Options.PropertyMapping { + props = append(props, ovf.EnvProperty{ + Key: p.Key, + Value: p.Value, + }) + } + + env := ovf.Env{ + EsxID: vm.Reference().Value, + Platform: &ovf.PlatformSection{ + Kind: a.Name, + Version: a.Version, + Vendor: a.Vendor, + Locale: "US", + }, + Property: &ovf.PropertySection{ + Properties: props, + }, + } + + opts = append(opts, &types.OptionValue{ + Key: "guestinfo.ovfEnv", + Value: env.MarshalManual(), + }) + + task, err := vm.Reconfigure(context.Background(), types.VirtualMachineConfigSpec{ + ExtraConfig: opts, + }) + + if err != nil { + return err + } + + return task.Wait(context.Background()) +} + +func (flag *OptionsFlag) waitForIP(vm *object.VirtualMachine, out *flags.OutputFlag) error { + if !flag.Options.PowerOn || !flag.Options.WaitForIP || flag.Options.MarkAsTemplate { + return nil + } + + out.Log("Waiting for IP address...\n") + ip, err := vm.WaitForIP(context.Background()) + if err != nil { + return err + } + + out.Log(fmt.Sprintf("Received IP address: %s\n", ip)) + return nil +} + +func (flag *OptionsFlag) Deploy(vm *object.VirtualMachine, out *flags.OutputFlag) error { + deploy := []func(*object.VirtualMachine, *flags.OutputFlag) error{ + flag.injectOvfEnv, + flag.markAsTemplate, + flag.powerOn, + flag.waitForIP, + } + + for _, step := range deploy { + if err := step(vm, out); err != nil { + return err + } + } + + return nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/importx/ova.go b/vendor/github.com/vmware/govmomi/govc/importx/ova.go new file mode 100644 index 00000000000..343cdcddab6 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/importx/ova.go @@ -0,0 +1,63 @@ +/* +Copyright (c) 2014-2015 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package importx + +import ( + "context" + "flag" + + "github.com/vmware/govmomi/govc/cli" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/vim25/types" +) + +type ova struct { + *ovfx +} + +func init() { + cli.Register("import.ova", &ova{&ovfx{}}) +} + +func (cmd *ova) Usage() string { + return "PATH_TO_OVA" +} + +func (cmd *ova) Run(ctx context.Context, f *flag.FlagSet) error { + fpath, err := cmd.Prepare(f) + if err != nil { + return err + } + + archive := &TapeArchive{Path: fpath} + archive.Client = cmd.Client + + cmd.Archive = archive + + moref, err := cmd.Import(fpath) + if err != nil { + return err + } + + vm := object.NewVirtualMachine(cmd.Client, *moref) + return cmd.Deploy(vm, cmd.OutputFlag) +} + +func (cmd *ova) Import(fpath string) (*types.ManagedObjectReference, error) { + ovf := "*.ovf" + return cmd.ovfx.Import(ovf) +} diff --git a/vendor/github.com/vmware/govmomi/govc/importx/ovf.go b/vendor/github.com/vmware/govmomi/govc/importx/ovf.go new file mode 100644 index 00000000000..e1765f4cb16 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/importx/ovf.go @@ -0,0 +1,451 @@ +/* +Copyright (c) 2014-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package importx + +import ( + "bytes" + "context" + "errors" + "flag" + "fmt" + "path" + "strings" + + "github.com/vmware/govmomi/find" + "github.com/vmware/govmomi/govc/cli" + "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/nfc" + "github.com/vmware/govmomi/object" + "github.com/vmware/govmomi/ovf" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" +) + +type ovfx struct { + *flags.DatastoreFlag + *flags.HostSystemFlag + *flags.OutputFlag + *flags.ResourcePoolFlag + *flags.FolderFlag + + *ArchiveFlag + *OptionsFlag + + Name string + VerifyManifest bool + Hidden bool + + Client *vim25.Client + Datacenter *object.Datacenter + Datastore *object.Datastore + ResourcePool *object.ResourcePool +} + +func init() { + cli.Register("import.ovf", &ovfx{}) +} + +func (cmd *ovfx) Register(ctx context.Context, f *flag.FlagSet) { + cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx) + cmd.DatastoreFlag.Register(ctx, f) + cmd.HostSystemFlag, ctx = flags.NewHostSystemFlag(ctx) + cmd.HostSystemFlag.Register(ctx, f) + cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) + cmd.OutputFlag.Register(ctx, f) + cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx) + cmd.ResourcePoolFlag.Register(ctx, f) + cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx) + cmd.FolderFlag.Register(ctx, f) + + cmd.ArchiveFlag, ctx = newArchiveFlag(ctx) + cmd.ArchiveFlag.Register(ctx, f) + cmd.OptionsFlag, ctx = newOptionsFlag(ctx) + cmd.OptionsFlag.Register(ctx, f) + + f.StringVar(&cmd.Name, "name", "", "Name to use for new entity") + f.BoolVar(&cmd.VerifyManifest, "m", false, "Verify checksum of uploaded files against manifest (.mf)") + f.BoolVar(&cmd.Hidden, "hidden", false, "Enable hidden properties") +} + +func (cmd *ovfx) Process(ctx context.Context) error { + if err := cmd.DatastoreFlag.Process(ctx); err != nil { + return err + } + if err := cmd.HostSystemFlag.Process(ctx); err != nil { + return err + } + if err := cmd.OutputFlag.Process(ctx); err != nil { + return err + } + if err := cmd.ResourcePoolFlag.Process(ctx); err != nil { + return err + } + if err := cmd.ArchiveFlag.Process(ctx); err != nil { + return err + } + if err := cmd.OptionsFlag.Process(ctx); err != nil { + return err + } + if err := cmd.FolderFlag.Process(ctx); err != nil { + return err + } + return nil +} + +func (cmd *ovfx) Usage() string { + return "PATH_TO_OVF" +} + +func (cmd *ovfx) Run(ctx context.Context, f *flag.FlagSet) error { + fpath, err := cmd.Prepare(f) + if err != nil { + return err + } + + archive := &FileArchive{Path: fpath} + archive.Client = cmd.Client + + cmd.Archive = archive + + moref, err := cmd.Import(fpath) + if err != nil { + return err + } + + vm := object.NewVirtualMachine(cmd.Client, *moref) + return cmd.Deploy(vm, cmd.OutputFlag) +} + +func (cmd *ovfx) Prepare(f *flag.FlagSet) (string, error) { + var err error + + args := f.Args() + if len(args) != 1 { + return "", errors.New("no file specified") + } + + cmd.Client, err = cmd.DatastoreFlag.Client() + if err != nil { + return "", err + } + + cmd.Datacenter, err = cmd.DatastoreFlag.Datacenter() + if err != nil { + return "", err + } + + cmd.Datastore, err = cmd.DatastoreFlag.Datastore() + if err != nil { + return "", err + } + + cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePoolIfSpecified() + if err != nil { + return "", err + } + + return f.Arg(0), nil +} + +func (cmd *ovfx) Map(op []Property) (p []types.KeyValue) { + for _, v := range op { + p = append(p, types.KeyValue{ + Key: v.Key, + Value: v.Value, + }) + } + + return +} + +func (cmd *ovfx) validateNetwork(e *ovf.Envelope, net Network) { + var names []string + + if e.Network != nil { + for _, n := range e.Network.Networks { + if n.Name == net.Name { + return + } + names = append(names, n.Name) + } + } + + _, _ = cmd.Log(fmt.Sprintf("Warning: invalid NetworkMapping.Name=%q, valid names=%s\n", net.Name, names)) +} + +func (cmd *ovfx) NetworkMap(e *ovf.Envelope) ([]types.OvfNetworkMapping, error) { + ctx := context.TODO() + finder, err := cmd.DatastoreFlag.Finder() + if err != nil { + return nil, err + } + + var nmap []types.OvfNetworkMapping + for _, m := range cmd.Options.NetworkMapping { + if m.Network == "" { + continue // Not set, let vSphere choose the default network + } + cmd.validateNetwork(e, m) + + var ref types.ManagedObjectReference + + net, err := finder.Network(ctx, m.Network) + if err != nil { + switch err.(type) { + case *find.NotFoundError: + if !ref.FromString(m.Network) { + return nil, err + } // else this is a raw MO ref + default: + return nil, err + } + } else { + ref = net.Reference() + } + + nmap = append(nmap, types.OvfNetworkMapping{ + Name: m.Name, + Network: ref, + }) + } + + return nmap, err +} + +func (cmd *ovfx) Import(fpath string) (*types.ManagedObjectReference, error) { + ctx := context.TODO() + + o, err := cmd.ReadOvf(fpath) + if err != nil { + return nil, err + } + + e, err := cmd.ReadEnvelope(o) + if err != nil { + return nil, fmt.Errorf("failed to parse ovf: %s", err) + } + + name := "Govc Virtual Appliance" + if e.VirtualSystem != nil { + name = e.VirtualSystem.ID + if e.VirtualSystem.Name != nil { + name = *e.VirtualSystem.Name + } + + if cmd.Hidden { + // TODO: userConfigurable is optional and defaults to false, so we should *add* userConfigurable=true + // if not set for a Property. But, there'd be a bunch more work involved to preserve other data in doing + // a complete xml.Marshal of the .ovf + o = bytes.ReplaceAll(o, []byte(`userConfigurable="false"`), []byte(`userConfigurable="true"`)) + } + } + + // Override name from options if specified + if cmd.Options.Name != nil { + name = *cmd.Options.Name + } + + // Override name from arguments if specified + if cmd.Name != "" { + name = cmd.Name + } + + nmap, err := cmd.NetworkMap(e) + if err != nil { + return nil, err + } + + cisp := types.OvfCreateImportSpecParams{ + DiskProvisioning: cmd.Options.DiskProvisioning, + EntityName: name, + IpAllocationPolicy: cmd.Options.IPAllocationPolicy, + IpProtocol: cmd.Options.IPProtocol, + OvfManagerCommonParams: types.OvfManagerCommonParams{ + DeploymentOption: cmd.Options.Deployment, + Locale: "US"}, + PropertyMapping: cmd.Map(cmd.Options.PropertyMapping), + NetworkMapping: nmap, + } + + host, err := cmd.HostSystemIfSpecified() + if err != nil { + return nil, err + } + + if cmd.ResourcePool == nil { + if host == nil { + cmd.ResourcePool, err = cmd.ResourcePoolFlag.ResourcePool() + } else { + cmd.ResourcePool, err = host.ResourcePool(ctx) + } + if err != nil { + return nil, err + } + } + + m := ovf.NewManager(cmd.Client) + spec, err := m.CreateImportSpec(ctx, string(o), cmd.ResourcePool, cmd.Datastore, cisp) + if err != nil { + return nil, err + } + if spec.Error != nil { + return nil, errors.New(spec.Error[0].LocalizedMessage) + } + if spec.Warning != nil { + for _, w := range spec.Warning { + _, _ = cmd.Log(fmt.Sprintf("Warning: %s\n", w.LocalizedMessage)) + } + } + + if cmd.Options.Annotation != "" { + switch s := spec.ImportSpec.(type) { + case *types.VirtualMachineImportSpec: + s.ConfigSpec.Annotation = cmd.Options.Annotation + case *types.VirtualAppImportSpec: + s.VAppConfigSpec.Annotation = cmd.Options.Annotation + } + } + + var folder *object.Folder + // The folder argument must not be set on a VM in a vApp, otherwise causes + // InvalidArgument fault: A specified parameter was not correct: pool + if cmd.ResourcePool.Reference().Type != "VirtualApp" { + folder, err = cmd.FolderOrDefault("vm") + if err != nil { + return nil, err + } + } + + if cmd.VerifyManifest { + err = cmd.readManifest(fpath) + if err != nil { + return nil, err + } + } + + lease, err := cmd.ResourcePool.ImportVApp(ctx, spec.ImportSpec, folder, host) + if err != nil { + return nil, err + } + + info, err := lease.Wait(ctx, spec.FileItem) + if err != nil { + return nil, err + } + + u := lease.StartUpdater(ctx, info) + defer u.Done() + + for _, i := range info.Items { + err = cmd.Upload(ctx, lease, i) + if err != nil { + return nil, err + } + } + + return &info.Entity, lease.Complete(ctx) +} + +func (cmd *ovfx) Upload(ctx context.Context, lease *nfc.Lease, item nfc.FileItem) error { + file := item.Path + + f, size, err := cmd.Open(file) + if err != nil { + return err + } + defer f.Close() + + logger := cmd.ProgressLogger(fmt.Sprintf("Uploading %s... ", path.Base(file))) + defer logger.Wait() + + opts := soap.Upload{ + ContentLength: size, + Progress: logger, + } + + err = lease.Upload(ctx, item, f, opts) + if err != nil { + return err + } + + if cmd.VerifyManifest { + mapImportKeyToKey := func(urls []types.HttpNfcLeaseDeviceUrl, importKey string) string { + for _, url := range urls { + if url.ImportKey == importKey { + return url.Key + } + } + return "" + } + leaseInfo, err := lease.Wait(ctx, nil) + if err != nil { + return err + } + return cmd.validateChecksum(ctx, lease, file, mapImportKeyToKey(leaseInfo.DeviceUrl, item.DeviceId)) + } + return nil +} + +func (cmd *ovfx) validateChecksum(ctx context.Context, lease *nfc.Lease, file string, key string) error { + sum, found := cmd.manifest[file] + if !found { + msg := fmt.Sprintf("missing checksum for %v in manifest file", file) + return errors.New(msg) + } + // Perform the checksum match eagerly, after each file upload, instead + // of after uploading all the files, to provide fail-fast behavior. + // (Trade-off here is multiple GetManifest() API calls to the server.) + manifests, err := lease.GetManifest(ctx) + if err != nil { + return err + } + for _, m := range manifests { + if m.Key == key { + // Compare server-side computed checksum of uploaded file + // against the client's manifest entry (assuming client's + // manifest has correct checksums - client doesn't compute + // checksum of the file before uploading). + + // Try matching sha1 first (newer versions have moved to sha256). + if strings.ToUpper(sum.Algorithm) == "SHA1" { + if sum.Checksum != m.Sha1 { + msg := fmt.Sprintf("manifest checksum %v mismatch with uploaded checksum %v for file %v", + sum.Checksum, m.Sha1, file) + return errors.New(msg) + } + // Uploaded file checksum computed by server matches with local manifest entry. + return nil + } + // If not sha1, check for other types (in a separate field). + if !strings.EqualFold(sum.Algorithm, m.ChecksumType) { + msg := fmt.Sprintf("manifest checksum type %v mismatch with uploaded checksum type %v for file %v", + sum.Algorithm, m.ChecksumType, file) + return errors.New(msg) + } + if !strings.EqualFold(sum.Checksum, m.Checksum) { + msg := fmt.Sprintf("manifest checksum %v mismatch with uploaded checksum %v for file %v", + sum.Checksum, m.Checksum, file) + return errors.New(msg) + } + // Uploaded file checksum computed by server matches with local manifest entry. + return nil + } + } + msg := fmt.Sprintf("missing manifest entry on server for uploaded file %v (key %v), manifests=%#v", file, key, manifests) + return errors.New(msg) +} diff --git a/vendor/github.com/vmware/govmomi/govc/importx/spec.go b/vendor/github.com/vmware/govmomi/govc/importx/spec.go new file mode 100644 index 00000000000..09763e2b117 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/importx/spec.go @@ -0,0 +1,250 @@ +/* +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package importx + +import ( + "context" + "flag" + "fmt" + "io" + "path" + "strings" + + "github.com/vmware/govmomi/govc/cli" + "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/ovf" + "github.com/vmware/govmomi/vim25/types" +) + +var ( + allDiskProvisioningOptions = []string{ + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeFlat), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeMonolithicSparse), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeMonolithicFlat), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeTwoGbMaxExtentSparse), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeTwoGbMaxExtentFlat), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeThin), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeThick), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeSeSparse), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeEagerZeroedThick), + string(types.OvfCreateImportSpecParamsDiskProvisioningTypeSparse), + } + allIPAllocationPolicyOptions = []string{ + string(types.VAppIPAssignmentInfoIpAllocationPolicyDhcpPolicy), + string(types.VAppIPAssignmentInfoIpAllocationPolicyTransientPolicy), + string(types.VAppIPAssignmentInfoIpAllocationPolicyFixedPolicy), + string(types.VAppIPAssignmentInfoIpAllocationPolicyFixedAllocatedPolicy), + } + allIPProtocolOptions = []string{ + string(types.VAppIPAssignmentInfoProtocolsIPv4), + string(types.VAppIPAssignmentInfoProtocolsIPv6), + } +) + +type spec struct { + *ArchiveFlag + *flags.ClientFlag + *flags.OutputFlag + + hidden bool +} + +func init() { + cli.Register("import.spec", &spec{}) +} + +func (cmd *spec) Register(ctx context.Context, f *flag.FlagSet) { + cmd.ArchiveFlag, ctx = newArchiveFlag(ctx) + cmd.ArchiveFlag.Register(ctx, f) + cmd.ClientFlag, ctx = flags.NewClientFlag(ctx) + cmd.ClientFlag.Register(ctx, f) + + cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) + cmd.OutputFlag.Register(ctx, f) + + f.BoolVar(&cmd.hidden, "hidden", false, "Enable hidden properties") +} + +func (cmd *spec) Process(ctx context.Context) error { + if err := cmd.ArchiveFlag.Process(ctx); err != nil { + return err + } + if err := cmd.ClientFlag.Process(ctx); err != nil { + return err + } + return cmd.OutputFlag.Process(ctx) +} + +func (cmd *spec) Usage() string { + return "PATH_TO_OVF_OR_OVA" +} + +func (cmd *spec) Run(ctx context.Context, f *flag.FlagSet) error { + fpath := "" + args := f.Args() + if len(args) == 1 { + fpath = f.Arg(0) + } + + if len(fpath) > 0 { + switch path.Ext(fpath) { + case ".ovf": + cmd.Archive = &FileArchive{Path: fpath} + case "", ".ova": + cmd.Archive = &TapeArchive{Path: fpath} + fpath = "*.ovf" + default: + return fmt.Errorf("invalid file extension %s", path.Ext(fpath)) + } + + if isRemotePath(f.Arg(0)) { + client, err := cmd.Client() + if err != nil { + return err + } + switch archive := cmd.Archive.(type) { + case *FileArchive: + archive.Client = client + case *TapeArchive: + archive.Client = client + } + } + } + + env, err := cmd.Spec(fpath) + if err != nil { + return err + } + + if !cmd.All() { + cmd.JSON = true + } + return cmd.WriteResult(&specResult{env}) +} + +type specResult struct { + *Options +} + +func (*specResult) Write(w io.Writer) error { + return nil +} + +func (cmd *spec) Map(e *ovf.Envelope) (res []Property) { + if e == nil || e.VirtualSystem == nil { + return nil + } + + for _, p := range e.VirtualSystem.Product { + for i, v := range p.Property { + if v.UserConfigurable == nil { + continue + } + if !*v.UserConfigurable && !cmd.hidden { + continue + } + + d := "" + if v.Default != nil { + d = *v.Default + } + + // vSphere only accept True/False as boolean values for some reason + if v.Type == "boolean" { + d = strings.Title(d) + } + + np := Property{KeyValue: KeyValue{Key: p.Key(v), Value: d}} + + if cmd.Verbose() { + np.Spec = &p.Property[i] + } + + res = append(res, np) + } + } + + return +} + +func (cmd *spec) Spec(fpath string) (*Options, error) { + e := &ovf.Envelope{} + if fpath != "" { + d, err := cmd.ReadOvf(fpath) + if err != nil { + return nil, err + } + + if e, err = cmd.ReadEnvelope(d); err != nil { + return nil, err + } + } + + var deploymentOptions []string + if e.DeploymentOption != nil && e.DeploymentOption.Configuration != nil { + // add default first + for _, c := range e.DeploymentOption.Configuration { + if c.Default != nil && *c.Default { + deploymentOptions = append(deploymentOptions, c.ID) + } + } + + for _, c := range e.DeploymentOption.Configuration { + if c.Default == nil || !*c.Default { + deploymentOptions = append(deploymentOptions, c.ID) + } + } + } + + o := Options{ + DiskProvisioning: allDiskProvisioningOptions[0], + IPAllocationPolicy: allIPAllocationPolicyOptions[0], + IPProtocol: allIPProtocolOptions[0], + MarkAsTemplate: false, + PowerOn: false, + WaitForIP: false, + InjectOvfEnv: false, + PropertyMapping: cmd.Map(e), + } + + if deploymentOptions != nil { + o.Deployment = deploymentOptions[0] + } + + if e.VirtualSystem != nil && e.VirtualSystem.Annotation != nil { + for _, a := range e.VirtualSystem.Annotation { + o.Annotation += a.Annotation + } + } + + if e.Network != nil { + for _, net := range e.Network.Networks { + o.NetworkMapping = append(o.NetworkMapping, Network{net.Name, ""}) + } + } + + if cmd.Verbose() { + if deploymentOptions != nil { + o.AllDeploymentOptions = deploymentOptions + } + o.AllDiskProvisioningOptions = allDiskProvisioningOptions + o.AllIPAllocationPolicyOptions = allIPAllocationPolicyOptions + o.AllIPProtocolOptions = allIPProtocolOptions + } + + return &o, nil +} diff --git a/vendor/github.com/vmware/govmomi/govc/importx/vmdk.go b/vendor/github.com/vmware/govmomi/govc/importx/vmdk.go new file mode 100644 index 00000000000..6e0ac5f992b --- /dev/null +++ b/vendor/github.com/vmware/govmomi/govc/importx/vmdk.go @@ -0,0 +1,132 @@ +/* +Copyright (c) 2014-2017 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package importx + +import ( + "context" + "errors" + "flag" + "fmt" + "path" + + "github.com/vmware/govmomi/govc/cli" + "github.com/vmware/govmomi/govc/flags" + "github.com/vmware/govmomi/vmdk" +) + +type disk struct { + *flags.DatastoreFlag + *flags.ResourcePoolFlag + *flags.FolderFlag + *flags.OutputFlag + + force bool +} + +func init() { + cli.Register("import.vmdk", &disk{}) +} + +func (cmd *disk) Register(ctx context.Context, f *flag.FlagSet) { + cmd.DatastoreFlag, ctx = flags.NewDatastoreFlag(ctx) + cmd.DatastoreFlag.Register(ctx, f) + cmd.ResourcePoolFlag, ctx = flags.NewResourcePoolFlag(ctx) + cmd.ResourcePoolFlag.Register(ctx, f) + cmd.FolderFlag, ctx = flags.NewFolderFlag(ctx) + cmd.FolderFlag.Register(ctx, f) + cmd.OutputFlag, ctx = flags.NewOutputFlag(ctx) + cmd.OutputFlag.Register(ctx, f) + + f.BoolVar(&cmd.force, "force", false, "Overwrite existing disk") +} + +func (cmd *disk) Process(ctx context.Context) error { + if err := cmd.DatastoreFlag.Process(ctx); err != nil { + return err + } + if err := cmd.ResourcePoolFlag.Process(ctx); err != nil { + return err + } + if err := cmd.FolderFlag.Process(ctx); err != nil { + return err + } + if err := cmd.OutputFlag.Process(ctx); err != nil { + return err + } + return nil +} + +func (cmd *disk) Usage() string { + return "PATH_TO_VMDK [REMOTE_DIRECTORY]" +} + +func (cmd *disk) Run(ctx context.Context, f *flag.FlagSet) error { + args := f.Args() + if len(args) < 1 { + return errors.New("no file to import") + } + + src := f.Arg(0) + + c, err := cmd.DatastoreFlag.Client() + if err != nil { + return err + } + + dc, err := cmd.DatastoreFlag.Datacenter() + if err != nil { + return err + } + + ds, err := cmd.DatastoreFlag.Datastore() + if err != nil { + return err + } + + pool, err := cmd.ResourcePoolFlag.ResourcePool() + if err != nil { + return err + } + + folder, err := cmd.FolderOrDefault("vm") + if err != nil { + return err + } + + logger := cmd.ProgressLogger(fmt.Sprintf("Uploading %s... ", path.Base(src))) + defer logger.Wait() + + p := vmdk.ImportParams{ + Path: f.Arg(1), + Logger: logger, + Type: "", // TODO: flag + Force: cmd.force, + Datacenter: dc, + Pool: pool, + Folder: folder, + } + + err = vmdk.Import(ctx, c, src, ds, p) + if err != nil && err == vmdk.ErrInvalidFormat { + return fmt.Errorf(`%s +The vmdk can be converted using one of: + vmware-vdiskmanager -t 5 -r '%s' new.vmdk + qemu-img convert -O vmdk -o subformat=streamOptimized '%s' new.vmdk`, err, src, src) + } + + return err +} diff --git a/vendor/github.com/vmware/govmomi/internal/helpers.go b/vendor/github.com/vmware/govmomi/internal/helpers.go index b3eafeadfd9..41e533fd756 100644 --- a/vendor/github.com/vmware/govmomi/internal/helpers.go +++ b/vendor/github.com/vmware/govmomi/internal/helpers.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2020 VMware, Inc. All Rights Reserved. +Copyright (c) 2020-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,13 +17,25 @@ limitations under the License. package internal import ( + "context" + "fmt" "net" + "net/http" + "net/url" + "os" "path" + "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/mo" + "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" ) +const ( + vCenterHostGatewaySocket = "/var/run/envoy-hgw/hgw-pipe" + vCenterHostGatewaySocketEnv = "VCENTER_ENVOY_HOST_GATEWAY" +) + // InventoryPath composed of entities by Name func InventoryPath(entities []mo.ManagedEntity) string { val := "/" @@ -61,3 +73,69 @@ func HostSystemManagementIPs(config []types.VirtualNicManagerNetConfig) []net.IP return ips } + +// UsingEnvoySidecar determines if the given *vim25.Client is using vCenter's +// local Envoy sidecar (as opposed to using the HTTPS port.) +// Returns a boolean indicating whether to use the sidecar or not. +func UsingEnvoySidecar(c *vim25.Client) bool { + envoySidecarPort := os.Getenv("GOVMOMI_ENVOY_SIDECAR_PORT") + if envoySidecarPort == "" { + envoySidecarPort = "1080" + } + envoySidecarHost := os.Getenv("GOVMOMI_ENVOY_SIDECAR_HOST") + if envoySidecarHost == "" { + envoySidecarHost = "localhost" + } + return c.URL().Hostname() == envoySidecarHost && c.URL().Scheme == "http" && c.URL().Port() == envoySidecarPort +} + +// ClientWithEnvoyHostGateway clones the provided soap.Client and returns a new +// one that uses a Unix socket to leverage vCenter's local Envoy host +// gateway. +// This should be used to construct clients that talk to ESX. +// This method returns a new *vim25.Client and does not modify the original input. +// This client disables HTTP keep alives and is intended for a single round +// trip. (eg. guest file transfer, datastore file transfer) +func ClientWithEnvoyHostGateway(vc *vim25.Client) *vim25.Client { + // Override the vim client with a new one that wraps a Unix socket transport. + // Using HTTP here so secure means nothing. + sc := soap.NewClient(vc.URL(), true) + // Clone the underlying HTTP transport, only replacing the dialer logic. + transport := sc.DefaultTransport().Clone() + hostGatewaySocketPath := os.Getenv(vCenterHostGatewaySocketEnv) + if hostGatewaySocketPath == "" { + hostGatewaySocketPath = vCenterHostGatewaySocket + } + transport.DialContext = func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial("unix", hostGatewaySocketPath) + } + // We use this client for a single request, so we don't require keepalives. + transport.DisableKeepAlives = true + sc.Client = http.Client{ + Transport: transport, + } + newVC := &vim25.Client{ + Client: sc, + } + return newVC +} + +// HostGatewayTransferURL rewrites the provided URL to be suitable for use +// with the Envoy host gateway on vCenter. +// It returns a copy of the provided URL with the host, scheme rewritten as needed. +// Receivers of such URLs must typically also use ClientWithEnvoyHostGateway to +// use the appropriate http.Transport to be able to make use of the host +// gateway. +// nil input yields an uninitialized struct. +func HostGatewayTransferURL(u *url.URL, hostMoref types.ManagedObjectReference) *url.URL { + if u == nil { + return &url.URL{} + } + // Make a copy of the provided URL. + turl := *u + turl.Host = "localhost" + turl.Scheme = "http" + oldPath := turl.Path + turl.Path = fmt.Sprintf("/hgw/%s%s", hostMoref.Value, oldPath) + return &turl +} diff --git a/vendor/github.com/vmware/govmomi/internal/version/version.go b/vendor/github.com/vmware/govmomi/internal/version/version.go index c3763327222..f66c30de457 100644 --- a/vendor/github.com/vmware/govmomi/internal/version/version.go +++ b/vendor/github.com/vmware/govmomi/internal/version/version.go @@ -21,5 +21,5 @@ const ( ClientName = "govmomi" // ClientVersion is the version of this SDK - ClientVersion = "0.30.4" + ClientVersion = "0.34.0" ) diff --git a/vendor/github.com/vmware/govmomi/nfc/lease.go b/vendor/github.com/vmware/govmomi/nfc/lease.go index 45756803362..eb3ef9fcaf3 100644 --- a/vendor/github.com/vmware/govmomi/nfc/lease.go +++ b/vendor/github.com/vmware/govmomi/nfc/lease.go @@ -71,17 +71,17 @@ func (l *Lease) Complete(ctx context.Context) error { } // GetManifest wraps methods.GetManifest -func (l *Lease) GetManifest(ctx context.Context) error { +func (l *Lease) GetManifest(ctx context.Context) ([]types.HttpNfcLeaseManifestEntry, error) { req := types.HttpNfcLeaseGetManifest{ This: l.Reference(), } - _, err := methods.HttpNfcLeaseGetManifest(ctx, l.c, &req) + res, err := methods.HttpNfcLeaseGetManifest(ctx, l.c, &req) if err != nil { - return err + return nil, err } - return nil + return res.Returnval, nil } // Progress wraps methods.Progress diff --git a/vendor/github.com/vmware/govmomi/object/compute_resource.go b/vendor/github.com/vmware/govmomi/object/compute_resource.go index 7645fddaf31..4a2db741170 100644 --- a/vendor/github.com/vmware/govmomi/object/compute_resource.go +++ b/vendor/github.com/vmware/govmomi/object/compute_resource.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -18,6 +18,7 @@ package object import ( "context" + "fmt" "path" "github.com/vmware/govmomi/property" @@ -84,6 +85,21 @@ func (c ComputeResource) Datastores(ctx context.Context) ([]*Datastore, error) { return dss, nil } +func (c ComputeResource) EnvironmentBrowser(ctx context.Context) (*EnvironmentBrowser, error) { + var cr mo.ComputeResource + + err := c.Properties(ctx, c.Reference(), []string{"environmentBrowser"}, &cr) + if err != nil { + return nil, err + } + + if cr.EnvironmentBrowser == nil { + return nil, fmt.Errorf("%s: nil environmentBrowser", c.Reference()) + } + + return NewEnvironmentBrowser(c.c, *cr.EnvironmentBrowser), nil +} + func (c ComputeResource) ResourcePool(ctx context.Context) (*ResourcePool, error) { var cr mo.ComputeResource diff --git a/vendor/github.com/vmware/govmomi/object/datastore.go b/vendor/github.com/vmware/govmomi/object/datastore.go index 65264ae152d..991ad4f8227 100644 --- a/vendor/github.com/vmware/govmomi/object/datastore.go +++ b/vendor/github.com/vmware/govmomi/object/datastore.go @@ -27,6 +27,7 @@ import ( "path" "strings" + "github.com/vmware/govmomi/internal" "github.com/vmware/govmomi/property" "github.com/vmware/govmomi/session" "github.com/vmware/govmomi/vim25" @@ -67,6 +68,31 @@ func NewDatastore(c *vim25.Client, ref types.ManagedObjectReference) *Datastore } } +// FindInventoryPath sets InventoryPath and DatacenterPath, +// needed by NewURL() to compose an upload/download endpoint URL +func (d *Datastore) FindInventoryPath(ctx context.Context) error { + entities, err := mo.Ancestors(ctx, d.c, d.c.ServiceContent.PropertyCollector, d.r) + if err != nil { + return err + } + + val := "/" + + for _, entity := range entities { + if entity.Parent == nil { + continue // root folder + } + val = path.Join(val, entity.Name) + if entity.Self.Type == "Datacenter" { + d.DatacenterPath = val + } + } + + d.InventoryPath = val + + return nil +} + func (d Datastore) Path(path string) string { var p DatastorePath if p.FromString(path) { @@ -83,8 +109,14 @@ func (d Datastore) Path(path string) string { func (d Datastore) NewURL(path string) *url.URL { u := d.c.URL() + scheme := u.Scheme + // In rare cases where vCenter and ESX are accessed using different schemes. + if overrideScheme := os.Getenv("GOVMOMI_DATASTORE_ACCESS_SCHEME"); overrideScheme != "" { + scheme = overrideScheme + } + return &url.URL{ - Scheme: u.Scheme, + Scheme: scheme, Host: u.Host, Path: fmt.Sprintf("/folder/%s", path), RawQuery: url.Values{ @@ -94,11 +126,6 @@ func (d Datastore) NewURL(path string) *url.URL { } } -// URL is deprecated, use NewURL instead. -func (d Datastore) URL(ctx context.Context, dc *Datacenter, path string) (*url.URL, error) { - return d.NewURL(path), nil -} - func (d Datastore) Browser(ctx context.Context) (*HostDatastoreBrowser, error) { var do mo.Datastore @@ -179,6 +206,10 @@ func (d Datastore) HostContext(ctx context.Context, host *HostSystem) context.Co // that can be used along with the ticket cookie to access the given path. An host is chosen at random unless the // the given Context was created with a specific host via the HostContext method. func (d Datastore) ServiceTicket(ctx context.Context, path string, method string) (*url.URL, *http.Cookie, error) { + if d.InventoryPath == "" { + _ = d.FindInventoryPath(ctx) + } + u := d.NewURL(path) host, ok := ctx.Value(datastoreServiceTicketHostKey{}).(*HostSystem) @@ -223,8 +254,18 @@ func (d Datastore) ServiceTicket(ctx context.Context, path string, method string delete(q, "dcPath") u.RawQuery = q.Encode() + // Now that we have a host selected, take a copy of the URL. + transferURL := *u + + if internal.UsingEnvoySidecar(d.Client()) { + // Rewrite the host URL to go through the Envoy sidecar on VC. + // Reciever must use a custom dialer. + u = internal.HostGatewayTransferURL(u, host.Reference()) + } + spec := types.SessionManagerHttpServiceRequestSpec{ - Url: u.String(), + // Use the original URL (without rewrites) for the session ticket. + Url: transferURL.String(), // See SessionManagerHttpServiceRequestSpecMethod enum Method: fmt.Sprintf("http%s%s", method[0:1], strings.ToLower(method[1:])), } @@ -261,7 +302,10 @@ func (d Datastore) uploadTicket(ctx context.Context, path string, param *soap.Up return nil, nil, err } - p.Ticket = ticket + if ticket != nil { + p.Ticket = ticket + p.Close = true // disable Keep-Alive connection to ESX + } return u, &p, nil } @@ -277,7 +321,10 @@ func (d Datastore) downloadTicket(ctx context.Context, path string, param *soap. return nil, nil, err } - p.Ticket = ticket + if ticket != nil { + p.Ticket = ticket + p.Close = true // disable Keep-Alive connection to ESX + } return u, &p, nil } @@ -297,7 +344,13 @@ func (d Datastore) UploadFile(ctx context.Context, file string, path string, par if err != nil { return err } - return d.Client().UploadFile(ctx, file, u, p) + vc := d.Client() + if internal.UsingEnvoySidecar(vc) { + // Override the vim client with a new one that wraps a Unix socket transport. + // Using HTTP here so secure means nothing. + vc = internal.ClientWithEnvoyHostGateway(vc) + } + return vc.UploadFile(ctx, file, u, p) } // Download via soap.Download with an http service ticket @@ -315,7 +368,13 @@ func (d Datastore) DownloadFile(ctx context.Context, path string, file string, p if err != nil { return err } - return d.Client().DownloadFile(ctx, file, u, p) + vc := d.Client() + if internal.UsingEnvoySidecar(vc) { + // Override the vim client with a new one that wraps a Unix socket transport. + // Using HTTP here so secure means nothing. + vc = internal.ClientWithEnvoyHostGateway(vc) + } + return vc.DownloadFile(ctx, file, u, p) } // AttachedHosts returns hosts that have this Datastore attached, accessible and writable. diff --git a/vendor/github.com/vmware/govmomi/object/environment_browser.go b/vendor/github.com/vmware/govmomi/object/environment_browser.go new file mode 100644 index 00000000000..54ab4cb8d5e --- /dev/null +++ b/vendor/github.com/vmware/govmomi/object/environment_browser.go @@ -0,0 +1,98 @@ +/* +Copyright (c) 2023-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package object + +import ( + "context" + + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" +) + +type EnvironmentBrowser struct { + Common +} + +func NewEnvironmentBrowser(c *vim25.Client, ref types.ManagedObjectReference) *EnvironmentBrowser { + return &EnvironmentBrowser{ + Common: NewCommon(c, ref), + } +} + +func (b EnvironmentBrowser) QueryConfigTarget(ctx context.Context, host *HostSystem) (*types.ConfigTarget, error) { + req := types.QueryConfigTarget{ + This: b.Reference(), + } + + if host != nil { + ref := host.Reference() + req.Host = &ref + } + + res, err := methods.QueryConfigTarget(ctx, b.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (b EnvironmentBrowser) QueryTargetCapabilities(ctx context.Context, host *HostSystem) (*types.HostCapability, error) { + req := types.QueryTargetCapabilities{ + This: b.Reference(), + } + + if host != nil { + ref := host.Reference() + req.Host = &ref + } + + res, err := methods.QueryTargetCapabilities(ctx, b.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (b EnvironmentBrowser) QueryConfigOption(ctx context.Context, spec *types.EnvironmentBrowserConfigOptionQuerySpec) (*types.VirtualMachineConfigOption, error) { + req := types.QueryConfigOptionEx{ + This: b.Reference(), + Spec: spec, + } + + res, err := methods.QueryConfigOptionEx(ctx, b.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (b EnvironmentBrowser) QueryConfigOptionDescriptor(ctx context.Context) ([]types.VirtualMachineConfigOptionDescriptor, error) { + req := types.QueryConfigOptionDescriptor{ + This: b.Reference(), + } + + res, err := methods.QueryConfigOptionDescriptor(ctx, b.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} diff --git a/vendor/github.com/vmware/govmomi/object/host_certificate_info.go b/vendor/github.com/vmware/govmomi/object/host_certificate_info.go index 52c26a9dd68..fd9b370ebae 100644 --- a/vendor/github.com/vmware/govmomi/object/host_certificate_info.go +++ b/vendor/github.com/vmware/govmomi/object/host_certificate_info.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2016 VMware, Inc. All Rights Reserved. +Copyright (c) 2016-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -36,10 +36,10 @@ import ( type HostCertificateInfo struct { types.HostCertificateManagerCertificateInfo - ThumbprintSHA1 string - ThumbprintSHA256 string + ThumbprintSHA1 string `json:"thumbprintSHA1"` + ThumbprintSHA256 string `json:"thumbprintSHA256"` - Err error + Err error `json:"err"` Certificate *x509.Certificate `json:"-"` subjectName *pkix.Name @@ -86,10 +86,7 @@ func (info *HostCertificateInfo) FromURL(u *url.URL, config *tls.Config) error { conn, err := tls.Dial("tcp", addr, config) if err != nil { - switch err.(type) { - case x509.UnknownAuthorityError: - case x509.HostnameError: - default: + if !soap.IsCertificateUntrusted(err) { return err } diff --git a/vendor/github.com/vmware/govmomi/object/search_index.go b/vendor/github.com/vmware/govmomi/object/search_index.go index bcf5e29f271..288f78097cf 100644 --- a/vendor/github.com/vmware/govmomi/object/search_index.go +++ b/vendor/github.com/vmware/govmomi/object/search_index.go @@ -93,7 +93,18 @@ func (s SearchIndex) FindByInventoryPath(ctx context.Context, path string) (Refe if res.Returnval == nil { return nil, nil } - return NewReference(s.c, *res.Returnval), nil + + r := NewReference(s.c, *res.Returnval) + + type common interface { + SetInventoryPath(string) + } + + if c, ok := r.(common); ok { + c.SetInventoryPath(path) + } + + return r, nil } // FindByIp finds a virtual machine or host by IP address. diff --git a/vendor/github.com/vmware/govmomi/object/virtual_device_list.go b/vendor/github.com/vmware/govmomi/object/virtual_device_list.go index 3765506532e..92797dcdabc 100644 --- a/vendor/github.com/vmware/govmomi/object/virtual_device_list.go +++ b/vendor/github.com/vmware/govmomi/object/virtual_device_list.go @@ -404,9 +404,13 @@ func (l VirtualDeviceList) PickController(kind types.BaseVirtualController) type } // newUnitNumber returns the unit number to use for attaching a new device to the given controller. -func (l VirtualDeviceList) newUnitNumber(c types.BaseVirtualController) int32 { +func (l VirtualDeviceList) newUnitNumber(c types.BaseVirtualController, offset int) int32 { units := make([]bool, 30) + for i := 0; i < offset; i++ { + units[i] = true + } + switch sc := c.(type) { case types.BaseVirtualSCSIController: // The SCSI controller sits on its own bus @@ -455,7 +459,14 @@ func (l VirtualDeviceList) AssignController(device types.BaseVirtualDevice, c ty d := device.GetVirtualDevice() d.ControllerKey = c.GetVirtualController().Key d.UnitNumber = new(int32) - *d.UnitNumber = l.newUnitNumber(c) + + offset := 0 + switch device.(type) { + case types.BaseVirtualEthernetCard: + offset = 7 + } + *d.UnitNumber = l.newUnitNumber(c, offset) + if d.Key == 0 { d.Key = l.newRandomKey() } diff --git a/vendor/github.com/vmware/govmomi/object/virtual_machine.go b/vendor/github.com/vmware/govmomi/object/virtual_machine.go index eeffc19fd3c..4665fcb744c 100644 --- a/vendor/github.com/vmware/govmomi/object/virtual_machine.go +++ b/vendor/github.com/vmware/govmomi/object/virtual_machine.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015-2021 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -172,6 +172,15 @@ func (v VirtualMachine) ShutdownGuest(ctx context.Context) error { return err } +func (v VirtualMachine) StandbyGuest(ctx context.Context) error { + req := types.StandbyGuest{ + This: v.Reference(), + } + + _, err := methods.StandbyGuest(ctx, v.c, &req) + return err +} + func (v VirtualMachine) RebootGuest(ctx context.Context) error { req := types.RebootGuest{ This: v.Reference(), @@ -429,6 +438,17 @@ func (v VirtualMachine) Device(ctx context.Context) (VirtualDeviceList, error) { return VirtualDeviceList(o.Config.Hardware.Device), nil } +func (v VirtualMachine) EnvironmentBrowser(ctx context.Context) (*EnvironmentBrowser, error) { + var vm mo.VirtualMachine + + err := v.Properties(ctx, v.Reference(), []string{"environmentBrowser"}, &vm) + if err != nil { + return nil, err + } + + return NewEnvironmentBrowser(v.c, vm.EnvironmentBrowser), nil +} + func (v VirtualMachine) HostSystem(ctx context.Context) (*HostSystem, error) { var o mo.VirtualMachine @@ -909,27 +929,6 @@ func (v VirtualMachine) Unregister(ctx context.Context) error { return err } -// QueryEnvironmentBrowser is a helper to get the environmentBrowser property. -func (v VirtualMachine) QueryConfigTarget(ctx context.Context) (*types.ConfigTarget, error) { - var vm mo.VirtualMachine - - err := v.Properties(ctx, v.Reference(), []string{"environmentBrowser"}, &vm) - if err != nil { - return nil, err - } - - req := types.QueryConfigTarget{ - This: vm.EnvironmentBrowser, - } - - res, err := methods.QueryConfigTarget(ctx, v.Client(), &req) - if err != nil { - return nil, err - } - - return res.Returnval, nil -} - func (v VirtualMachine) MountToolsInstaller(ctx context.Context) error { req := types.MountToolsInstaller{ This: v.Reference(), diff --git a/vendor/github.com/vmware/govmomi/ovf/envelope.go b/vendor/github.com/vmware/govmomi/ovf/envelope.go index 274adb9df1e..aa77aab2de4 100644 --- a/vendor/github.com/vmware/govmomi/ovf/envelope.go +++ b/vendor/github.com/vmware/govmomi/ovf/envelope.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -16,6 +16,10 @@ limitations under the License. package ovf +import ( + "fmt" +) + type Envelope struct { References []File `xml:"References>File"` @@ -61,6 +65,7 @@ type Content struct { type Section struct { Required *bool `xml:"required,attr"` Info string `xml:"Info"` + Category string `xml:"Category"` } type AnnotationSection struct { @@ -85,6 +90,20 @@ type ProductSection struct { Property []Property `xml:"Property"` } +func (p ProductSection) Key(prop Property) string { + // From OVF spec, section 9.5.1: + // key-value-env = [class-value "."] key-value-prod ["." instance-value] + + k := prop.Key + if p.Class != nil { + k = fmt.Sprintf("%s.%s", *p.Class, k) + } + if p.Instance != nil { + k = fmt.Sprintf("%s.%s", k, *p.Instance) + } + return k +} + type Property struct { Key string `xml:"key,attr"` Type string `xml:"type,attr"` diff --git a/vendor/github.com/vmware/govmomi/pbm/client.go b/vendor/github.com/vmware/govmomi/pbm/client.go index ba2531ec966..3c7965ca8ea 100644 --- a/vendor/github.com/vmware/govmomi/pbm/client.go +++ b/vendor/github.com/vmware/govmomi/pbm/client.go @@ -285,3 +285,31 @@ func (c *Client) GetProfileNameByID(ctx context.Context, profileID string) (stri } return "", fmt.Errorf("no pbm profile found with id: %q", profileID) } + +func (c *Client) QueryAssociatedProfile(ctx context.Context, entity types.PbmServerObjectRef) ([]types.PbmProfileId, error) { + req := types.PbmQueryAssociatedProfile{ + This: c.ServiceContent.ProfileManager, + Entity: entity, + } + + res, err := methods.PbmQueryAssociatedProfile(ctx, c, &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} + +func (c *Client) QueryAssociatedProfiles(ctx context.Context, entities []types.PbmServerObjectRef) ([]types.PbmQueryProfileResult, error) { + req := types.PbmQueryAssociatedProfiles{ + This: c.ServiceContent.ProfileManager, + Entities: entities, + } + + res, err := methods.PbmQueryAssociatedProfiles(ctx, c, &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil +} diff --git a/vendor/github.com/vmware/govmomi/pbm/methods/methods.go b/vendor/github.com/vmware/govmomi/pbm/methods/methods.go index fa7f2b200ff..032c15c54c3 100644 --- a/vendor/github.com/vmware/govmomi/pbm/methods/methods.go +++ b/vendor/github.com/vmware/govmomi/pbm/methods/methods.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2014-2022 VMware, Inc. All Rights Reserved. +Copyright (c) 2014-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/github.com/vmware/govmomi/pbm/types/enum.go b/vendor/github.com/vmware/govmomi/pbm/types/enum.go index 66751bb1f4d..be05cfd2a04 100644 --- a/vendor/github.com/vmware/govmomi/pbm/types/enum.go +++ b/vendor/github.com/vmware/govmomi/pbm/types/enum.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2014-2022 VMware, Inc. All Rights Reserved. +Copyright (c) 2014-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -25,8 +25,11 @@ import ( type PbmAssociateAndApplyPolicyStatusPolicyStatus string const ( + // Policy applied successfully. PbmAssociateAndApplyPolicyStatusPolicyStatusSuccess = PbmAssociateAndApplyPolicyStatusPolicyStatus("success") - PbmAssociateAndApplyPolicyStatusPolicyStatusFailed = PbmAssociateAndApplyPolicyStatusPolicyStatus("failed") + // Policy cannot be applied + PbmAssociateAndApplyPolicyStatusPolicyStatusFailed = PbmAssociateAndApplyPolicyStatusPolicyStatus("failed") + // Policy cannot be applied PbmAssociateAndApplyPolicyStatusPolicyStatusInvalid = PbmAssociateAndApplyPolicyStatusPolicyStatus("invalid") ) @@ -34,28 +37,90 @@ func init() { types.Add("pbm:PbmAssociateAndApplyPolicyStatusPolicyStatus", reflect.TypeOf((*PbmAssociateAndApplyPolicyStatusPolicyStatus)(nil)).Elem()) } +// The `PbmBuiltinGenericType_enum` enumerated type defines the list +// of builtin generic datatypes. +// +// See +// `PbmCapabilityGenericTypeInfo*.*PbmCapabilityGenericTypeInfo.genericTypeName`. +// +// A generic datatype indicates how to interpret a collection of values +// of a specific datatype (`PbmCapabilityTypeInfo.typeName`). type PbmBuiltinGenericType string const ( + // Indicates a full or partial range of values (`PbmCapabilityRange`). + // + // A full range specifies both min and max values. + // A partial range specifies one or the other, min or max. PbmBuiltinGenericTypeVMW_RANGE = PbmBuiltinGenericType("VMW_RANGE") - PbmBuiltinGenericTypeVMW_SET = PbmBuiltinGenericType("VMW_SET") + // Indicates a single value or a discrete set of values + // (`PbmCapabilityDiscreteSet`). + PbmBuiltinGenericTypeVMW_SET = PbmBuiltinGenericType("VMW_SET") ) func init() { types.Add("pbm:PbmBuiltinGenericType", reflect.TypeOf((*PbmBuiltinGenericType)(nil)).Elem()) } +// The `PbmBuiltinType_enum` enumerated type defines datatypes +// for storage profiles. +// +// Property metadata +// (`PbmCapabilityPropertyMetadata`) uses the builtin types +// to define data types for storage capabilities and requirements. +// It may also specify the semantics that are applied to a collection +// of builtin type values. See `PbmCapabilityTypeInfo`. +// These semantics are specified as a generic builtin type. +// See `PbmCapabilityGenericTypeInfo`. +// The type information determines how capability constraints are interpreted +// `PbmCapabilityPropertyInstance.value`). type PbmBuiltinType string const ( - PbmBuiltinTypeXSD_LONG = PbmBuiltinType("XSD_LONG") - PbmBuiltinTypeXSD_SHORT = PbmBuiltinType("XSD_SHORT") - PbmBuiltinTypeXSD_INTEGER = PbmBuiltinType("XSD_INTEGER") - PbmBuiltinTypeXSD_INT = PbmBuiltinType("XSD_INT") - PbmBuiltinTypeXSD_STRING = PbmBuiltinType("XSD_STRING") - PbmBuiltinTypeXSD_BOOLEAN = PbmBuiltinType("XSD_BOOLEAN") - PbmBuiltinTypeXSD_DOUBLE = PbmBuiltinType("XSD_DOUBLE") + // Unsigned long value. + // + // This datatype supports the following constraint values. + // - Single value + // - Full or partial range of values (`PbmCapabilityRange`) + // - Discrete set of values (`PbmCapabilityDiscreteSet`) + PbmBuiltinTypeXSD_LONG = PbmBuiltinType("XSD_LONG") + // Datatype not supported. + PbmBuiltinTypeXSD_SHORT = PbmBuiltinType("XSD_SHORT") + // Datatype not supported. + // + // Use XSD\_INT instead. + PbmBuiltinTypeXSD_INTEGER = PbmBuiltinType("XSD_INTEGER") + // Integer value. + // + // This datatype supports the following constraint values. + // - Single value + // - Full or partial range of values (`PbmCapabilityRange`) + // - Discrete set of values (`PbmCapabilityDiscreteSet`) + PbmBuiltinTypeXSD_INT = PbmBuiltinType("XSD_INT") + // String value. + // + // This datatype supports a single value + // or a discrete set of values (`PbmCapabilityDiscreteSet`). + PbmBuiltinTypeXSD_STRING = PbmBuiltinType("XSD_STRING") + // Boolean value. + PbmBuiltinTypeXSD_BOOLEAN = PbmBuiltinType("XSD_BOOLEAN") + // Double precision floating point value. + // + // This datatype supports the following + // constraint values. + // - Single value + // - Full or partial range of values (`PbmCapabilityRange`) + // - Discrete set of values (`PbmCapabilityDiscreteSet`) + PbmBuiltinTypeXSD_DOUBLE = PbmBuiltinType("XSD_DOUBLE") + // Date and time value. PbmBuiltinTypeXSD_DATETIME = PbmBuiltinType("XSD_DATETIME") + // Timespan value (`PbmCapabilityTimeSpan`). + // + // This datatype supports + // the following constraint values. + // - Single value + // - Full or partial range of values (`PbmCapabilityRange`) + // - Discrete set of values (`PbmCapabilityDiscreteSet`) PbmBuiltinTypeVMW_TIMESPAN = PbmBuiltinType("VMW_TIMESPAN") PbmBuiltinTypeVMW_POLICY = PbmBuiltinType("VMW_POLICY") ) @@ -64,6 +129,10 @@ func init() { types.Add("pbm:PbmBuiltinType", reflect.TypeOf((*PbmBuiltinType)(nil)).Elem()) } +// List of operators that are supported for constructing policy. +// +// Currently only tag based properties can use this operator. +// Other operators can be added as required. type PbmCapabilityOperator string const ( @@ -74,52 +143,96 @@ func init() { types.Add("pbm:PbmCapabilityOperator", reflect.TypeOf((*PbmCapabilityOperator)(nil)).Elem()) } +// The `PbmCapabilityTimeUnitType_enum` enumeration type +// defines the supported list of time units for profiles that specify +// time span capabilities and constraints. +// +// See `PbmCapabilityTimeSpan`. type PbmCapabilityTimeUnitType string const ( + // Constraints and capabilities expressed in units of seconds. PbmCapabilityTimeUnitTypeSECONDS = PbmCapabilityTimeUnitType("SECONDS") + // Constraints and capabilities expressed in units of minutes. PbmCapabilityTimeUnitTypeMINUTES = PbmCapabilityTimeUnitType("MINUTES") - PbmCapabilityTimeUnitTypeHOURS = PbmCapabilityTimeUnitType("HOURS") - PbmCapabilityTimeUnitTypeDAYS = PbmCapabilityTimeUnitType("DAYS") - PbmCapabilityTimeUnitTypeWEEKS = PbmCapabilityTimeUnitType("WEEKS") - PbmCapabilityTimeUnitTypeMONTHS = PbmCapabilityTimeUnitType("MONTHS") - PbmCapabilityTimeUnitTypeYEARS = PbmCapabilityTimeUnitType("YEARS") + // Constraints and capabilities expressed in units of hours. + PbmCapabilityTimeUnitTypeHOURS = PbmCapabilityTimeUnitType("HOURS") + // Constraints and capabilities expressed in units of days. + PbmCapabilityTimeUnitTypeDAYS = PbmCapabilityTimeUnitType("DAYS") + // Constraints and capabilities expressed in units of weeks. + PbmCapabilityTimeUnitTypeWEEKS = PbmCapabilityTimeUnitType("WEEKS") + // Constraints and capabilities expressed in units of months. + PbmCapabilityTimeUnitTypeMONTHS = PbmCapabilityTimeUnitType("MONTHS") + // Constraints and capabilities expressed in units of years. + PbmCapabilityTimeUnitTypeYEARS = PbmCapabilityTimeUnitType("YEARS") ) func init() { types.Add("pbm:PbmCapabilityTimeUnitType", reflect.TypeOf((*PbmCapabilityTimeUnitType)(nil)).Elem()) } +// The `PbmComplianceResultComplianceTaskStatus_enum` +// enumeration type defines the set of task status for compliance +// operations. +// +// See `PbmComplianceResult` and +// `PbmRollupComplianceResult`. type PbmComplianceResultComplianceTaskStatus string const ( + // Compliance calculation is in progress. PbmComplianceResultComplianceTaskStatusInProgress = PbmComplianceResultComplianceTaskStatus("inProgress") - PbmComplianceResultComplianceTaskStatusSuccess = PbmComplianceResultComplianceTaskStatus("success") - PbmComplianceResultComplianceTaskStatusFailed = PbmComplianceResultComplianceTaskStatus("failed") + // Compliance calculation has succeeded. + PbmComplianceResultComplianceTaskStatusSuccess = PbmComplianceResultComplianceTaskStatus("success") + // Compliance calculation failed due to some exception. + PbmComplianceResultComplianceTaskStatusFailed = PbmComplianceResultComplianceTaskStatus("failed") ) func init() { types.Add("pbm:PbmComplianceResultComplianceTaskStatus", reflect.TypeOf((*PbmComplianceResultComplianceTaskStatus)(nil)).Elem()) } +// The `PbmComplianceStatus_enum` +// enumeration type defines the set of status values +// for compliance operations. +// +// See `PbmComplianceResult` and +// `PbmRollupComplianceResult`. type PbmComplianceStatus string const ( - PbmComplianceStatusCompliant = PbmComplianceStatus("compliant") - PbmComplianceStatusNonCompliant = PbmComplianceStatus("nonCompliant") - PbmComplianceStatusUnknown = PbmComplianceStatus("unknown") + // Entity is in compliance. + PbmComplianceStatusCompliant = PbmComplianceStatus("compliant") + // Entity is out of compliance. + PbmComplianceStatusNonCompliant = PbmComplianceStatus("nonCompliant") + // Compliance status of the entity is not known. + PbmComplianceStatusUnknown = PbmComplianceStatus("unknown") + // Compliance computation is not applicable for this entity, + // because it does not have any storage requirements that + // apply to the object-based datastore on which this entity is placed. PbmComplianceStatusNotApplicable = PbmComplianceStatus("notApplicable") - PbmComplianceStatusOutOfDate = PbmComplianceStatus("outOfDate") + // This is the same as `PbmComplianceResult.mismatch` + // variable. + // + // Compliance status becomes out-of-date when the profile + // associated with the entity is edited and not applied. The compliance + // status will remain in out-of-date compliance status until the latest + // policy is applied to the entity. + PbmComplianceStatusOutOfDate = PbmComplianceStatus("outOfDate") ) func init() { types.Add("pbm:PbmComplianceStatus", reflect.TypeOf((*PbmComplianceStatus)(nil)).Elem()) } +// This enum corresponds to the keystores used by +// sps. type PbmDebugManagerKeystoreName string const ( - PbmDebugManagerKeystoreNameSMS = PbmDebugManagerKeystoreName("SMS") + // Refers to SMS keystore + PbmDebugManagerKeystoreNameSMS = PbmDebugManagerKeystoreName("SMS") + // Refers to TRUSTED\_ROOTS keystore. PbmDebugManagerKeystoreNameTRUSTED_ROOTS = PbmDebugManagerKeystoreName("TRUSTED_ROOTS") ) @@ -127,12 +240,30 @@ func init() { types.Add("pbm:PbmDebugManagerKeystoreName", reflect.TypeOf((*PbmDebugManagerKeystoreName)(nil)).Elem()) } +// The enumeration type defines the set of health status values for an entity +// that is part of entity health operation. type PbmHealthStatusForEntity string const ( - PbmHealthStatusForEntityRed = PbmHealthStatusForEntity("red") - PbmHealthStatusForEntityYellow = PbmHealthStatusForEntity("yellow") - PbmHealthStatusForEntityGreen = PbmHealthStatusForEntity("green") + // For file share: 'red' if the file server for this file share is in error + // state or any of its backing vSAN objects are degraded. + // + // For FCD: 'red' if the datastore on which the FCD resides is not + // accessible from any of the hosts it is mounted. + PbmHealthStatusForEntityRed = PbmHealthStatusForEntity("red") + // For file share: 'yellow' if some backing objects are repairing, i.e. + // + // warning state. + // For FCD: 'yellow' if the datastore on which the entity resides is + // accessible only from some of the hosts it is mounted but not all. + PbmHealthStatusForEntityYellow = PbmHealthStatusForEntity("yellow") + // For file share: 'green' if the file server for this file share is + // running properly and all its backing vSAN objects are healthy. + // + // For FCD: 'green' if the datastore on which the entity resides + // is accessible from all the hosts it is mounted. + PbmHealthStatusForEntityGreen = PbmHealthStatusForEntity("green") + // If the health status of a file share is unknown, not valid for FCD. PbmHealthStatusForEntityUnknown = PbmHealthStatusForEntity("unknown") ) @@ -140,6 +271,11 @@ func init() { types.Add("pbm:PbmHealthStatusForEntity", reflect.TypeOf((*PbmHealthStatusForEntity)(nil)).Elem()) } +// Recognized types of an IO Filter. +// +// String constant used in `IofilterInfo#filterType`. +// These should match(upper case) the IO Filter classes as defined by IO Filter framework. +// See https://opengrok.eng.vmware.com/source/xref/vmcore-main.perforce.1666/bora/scons/apps/esx/iofilterApps.sc#33 type PbmIofilterInfoFilterType string const ( @@ -156,6 +292,7 @@ func init() { types.Add("pbm:PbmIofilterInfoFilterType", reflect.TypeOf((*PbmIofilterInfoFilterType)(nil)).Elem()) } +// Denotes the line of service of a schema. type PbmLineOfServiceInfoLineOfServiceEnum string const ( @@ -174,28 +311,43 @@ func init() { types.Add("pbm:PbmLineOfServiceInfoLineOfServiceEnum", reflect.TypeOf((*PbmLineOfServiceInfoLineOfServiceEnum)(nil)).Elem()) } +// This enum corresponds to the different packages whose logging +// is configured independently by sps service. type PbmLoggingConfigurationComponent string const ( - PbmLoggingConfigurationComponentPbm = PbmLoggingConfigurationComponent("pbm") - PbmLoggingConfigurationComponentVslm = PbmLoggingConfigurationComponent("vslm") - PbmLoggingConfigurationComponentSms = PbmLoggingConfigurationComponent("sms") - PbmLoggingConfigurationComponentSpbm = PbmLoggingConfigurationComponent("spbm") - PbmLoggingConfigurationComponentSps = PbmLoggingConfigurationComponent("sps") - PbmLoggingConfigurationComponentHttpclient_header = PbmLoggingConfigurationComponent("httpclient_header") + // Modifies logging level of com.vmware.pbm package. + PbmLoggingConfigurationComponentPbm = PbmLoggingConfigurationComponent("pbm") + // Modifies logging level of com.vmware.vslm package. + PbmLoggingConfigurationComponentVslm = PbmLoggingConfigurationComponent("vslm") + // Modifies logging level of com.vmware.vim.sms package. + PbmLoggingConfigurationComponentSms = PbmLoggingConfigurationComponent("sms") + // Modifies logging level of com.vmware.spbm package. + PbmLoggingConfigurationComponentSpbm = PbmLoggingConfigurationComponent("spbm") + // Modifies logging level of com.vmware.sps package. + PbmLoggingConfigurationComponentSps = PbmLoggingConfigurationComponent("sps") + // Modifies logging level of httpclient wire header. + PbmLoggingConfigurationComponentHttpclient_header = PbmLoggingConfigurationComponent("httpclient_header") + // Modifies logging level of httpclient wire content. PbmLoggingConfigurationComponentHttpclient_content = PbmLoggingConfigurationComponent("httpclient_content") - PbmLoggingConfigurationComponentVmomi = PbmLoggingConfigurationComponent("vmomi") + // Modifies logging level of com.vmware.vim.vmomi package. + PbmLoggingConfigurationComponentVmomi = PbmLoggingConfigurationComponent("vmomi") ) func init() { types.Add("pbm:PbmLoggingConfigurationComponent", reflect.TypeOf((*PbmLoggingConfigurationComponent)(nil)).Elem()) } +// This enum corresponds to the different log levels supported +// by sps service. type PbmLoggingConfigurationLogLevel string const ( - PbmLoggingConfigurationLogLevelINFO = PbmLoggingConfigurationLogLevel("INFO") + // Refers to INFO level logging + PbmLoggingConfigurationLogLevelINFO = PbmLoggingConfigurationLogLevel("INFO") + // Refers to DEBUG level logging. PbmLoggingConfigurationLogLevelDEBUG = PbmLoggingConfigurationLogLevel("DEBUG") + // Refers to TRACE level logging. PbmLoggingConfigurationLogLevelTRACE = PbmLoggingConfigurationLogLevel("TRACE") ) @@ -203,42 +355,76 @@ func init() { types.Add("pbm:PbmLoggingConfigurationLogLevel", reflect.TypeOf((*PbmLoggingConfigurationLogLevel)(nil)).Elem()) } +// The `PbmObjectType_enum` enumerated type +// defines vSphere Server object types that are known +// to the Storage Policy Server. +// +// See `PbmServerObjectRef*.*PbmServerObjectRef.objectType`. type PbmObjectType string const ( - PbmObjectTypeVirtualMachine = PbmObjectType("virtualMachine") + // Indicates a virtual machine, not including the disks, identified by the virtual machine + // identifier _virtual-machine-mor_. + PbmObjectTypeVirtualMachine = PbmObjectType("virtualMachine") + // Indicates the virtual machine and all its disks, identified by the virtual machine + // identifier _virtual-machine-mor_. PbmObjectTypeVirtualMachineAndDisks = PbmObjectType("virtualMachineAndDisks") - PbmObjectTypeVirtualDiskId = PbmObjectType("virtualDiskId") - PbmObjectTypeVirtualDiskUUID = PbmObjectType("virtualDiskUUID") - PbmObjectTypeDatastore = PbmObjectType("datastore") - PbmObjectTypeVsanObjectId = PbmObjectType("vsanObjectId") - PbmObjectTypeFileShareId = PbmObjectType("fileShareId") - PbmObjectTypeUnknown = PbmObjectType("unknown") + // Indicates a virtual disk, identified by disk key + // (_virtual-machine-mor_:_disk-key_). + PbmObjectTypeVirtualDiskId = PbmObjectType("virtualDiskId") + // Indicates a virtual disk, identified by UUID - for First Class Storage Object support. + PbmObjectTypeVirtualDiskUUID = PbmObjectType("virtualDiskUUID") + // Indicates a datastore. + PbmObjectTypeDatastore = PbmObjectType("datastore") + // Indicates a VSAN object + PbmObjectTypeVsanObjectId = PbmObjectType("vsanObjectId") + // Indicates a file service + PbmObjectTypeFileShareId = PbmObjectType("fileShareId") + // Unknown object type. + PbmObjectTypeUnknown = PbmObjectType("unknown") ) func init() { types.Add("pbm:PbmObjectType", reflect.TypeOf((*PbmObjectType)(nil)).Elem()) } +// The `PbmOperation_enum` enumerated type +// defines the provisioning operation being performed on the entity like FCD, virtual machine. type PbmOperation string const ( - PbmOperationCREATE = PbmOperation("CREATE") - PbmOperationREGISTER = PbmOperation("REGISTER") + // Indicates create operation of an entity. + PbmOperationCREATE = PbmOperation("CREATE") + // Indicates register operation of an entity. + PbmOperationREGISTER = PbmOperation("REGISTER") + // Indicates reconfigure operation of an entity. PbmOperationRECONFIGURE = PbmOperation("RECONFIGURE") - PbmOperationMIGRATE = PbmOperation("MIGRATE") - PbmOperationCLONE = PbmOperation("CLONE") + // Indicates migrate operation of an entity. + PbmOperationMIGRATE = PbmOperation("MIGRATE") + // Indicates clone operation of an entity. + PbmOperationCLONE = PbmOperation("CLONE") ) func init() { types.Add("pbm:PbmOperation", reflect.TypeOf((*PbmOperation)(nil)).Elem()) } +// Volume allocation type constants. type PbmPolicyAssociationVolumeAllocationType string const ( - PbmPolicyAssociationVolumeAllocationTypeFullyInitialized = PbmPolicyAssociationVolumeAllocationType("FullyInitialized") - PbmPolicyAssociationVolumeAllocationTypeReserveSpace = PbmPolicyAssociationVolumeAllocationType("ReserveSpace") + // Space required is fully allocated and initialized. + // + // It is wiped clean of any previous content on the + // physical media. Gives faster runtime IO performance. + PbmPolicyAssociationVolumeAllocationTypeFullyInitialized = PbmPolicyAssociationVolumeAllocationType("FullyInitialized") + // Space required is fully allocated. + // + // It may contain + // stale data on the physical media. + PbmPolicyAssociationVolumeAllocationTypeReserveSpace = PbmPolicyAssociationVolumeAllocationType("ReserveSpace") + // Space required is allocated and zeroed on demand + // as the space is used. PbmPolicyAssociationVolumeAllocationTypeConserveSpaceWhenPossible = PbmPolicyAssociationVolumeAllocationType("ConserveSpaceWhenPossible") ) @@ -246,11 +432,30 @@ func init() { types.Add("pbm:PbmPolicyAssociationVolumeAllocationType", reflect.TypeOf((*PbmPolicyAssociationVolumeAllocationType)(nil)).Elem()) } +// The `PbmProfileCategoryEnum_enum` +// enumerated type defines the profile categories for a capability-based +// storage profile. +// +// See +// `PbmCapabilityProfile`. type PbmProfileCategoryEnum string const ( - PbmProfileCategoryEnumREQUIREMENT = PbmProfileCategoryEnum("REQUIREMENT") - PbmProfileCategoryEnumRESOURCE = PbmProfileCategoryEnum("RESOURCE") + // Indicates a storage requirement. + // + // Requirements are based on + // storage capabilities. + PbmProfileCategoryEnumREQUIREMENT = PbmProfileCategoryEnum("REQUIREMENT") + // Indicates a storage capability. + // + // Storage capabilities + // are defined by storage providers. + PbmProfileCategoryEnumRESOURCE = PbmProfileCategoryEnum("RESOURCE") + // Indicates a data service policy that can be embedded into + // another storage policy. + // + // Policies of this type can't be assigned to + // Virtual Machines or Virtual Disks. PbmProfileCategoryEnumDATA_SERVICE_POLICY = PbmProfileCategoryEnum("DATA_SERVICE_POLICY") ) @@ -258,9 +463,14 @@ func init() { types.Add("pbm:PbmProfileCategoryEnum", reflect.TypeOf((*PbmProfileCategoryEnum)(nil)).Elem()) } +// The `PbmProfileResourceTypeEnum_enum` enumerated type defines the set of resource +// types that are supported for profile management. +// +// See `PbmProfileResourceType`. type PbmProfileResourceTypeEnum string const ( + // Indicates resources that support storage profiles. PbmProfileResourceTypeEnumSTORAGE = PbmProfileResourceTypeEnum("STORAGE") ) @@ -268,12 +478,21 @@ func init() { types.Add("pbm:PbmProfileResourceTypeEnum", reflect.TypeOf((*PbmProfileResourceTypeEnum)(nil)).Elem()) } +// System pre-created profile types. type PbmSystemCreatedProfileType string const ( - PbmSystemCreatedProfileTypeVsanDefaultProfile = PbmSystemCreatedProfileType("VsanDefaultProfile") - PbmSystemCreatedProfileTypeVVolDefaultProfile = PbmSystemCreatedProfileType("VVolDefaultProfile") - PbmSystemCreatedProfileTypePmemDefaultProfile = PbmSystemCreatedProfileType("PmemDefaultProfile") + // Indicates the system pre-created editable VSAN default profile. + PbmSystemCreatedProfileTypeVsanDefaultProfile = PbmSystemCreatedProfileType("VsanDefaultProfile") + // Indicates the system pre-created non-editable default profile + // for VVOL datastores. + PbmSystemCreatedProfileTypeVVolDefaultProfile = PbmSystemCreatedProfileType("VVolDefaultProfile") + // Indicates the system pre-created non-editable default profile + // for PMem datastores + PbmSystemCreatedProfileTypePmemDefaultProfile = PbmSystemCreatedProfileType("PmemDefaultProfile") + // Indicates the system pre-created non-editable VMC default profile. + PbmSystemCreatedProfileTypeVmcManagementProfile = PbmSystemCreatedProfileType("VmcManagementProfile") + // Indicates the system pre-created non-editable VSANMAX default profile. PbmSystemCreatedProfileTypeVsanMaxDefaultProfile = PbmSystemCreatedProfileType("VsanMaxDefaultProfile") ) @@ -281,25 +500,39 @@ func init() { types.Add("pbm:PbmSystemCreatedProfileType", reflect.TypeOf((*PbmSystemCreatedProfileType)(nil)).Elem()) } +// The `PbmVmOperation_enum` enumerated type +// defines the provisioning operation being performed on the virtual machine. type PbmVmOperation string const ( - PbmVmOperationCREATE = PbmVmOperation("CREATE") + // Indicates create operation of a virtual machine. + PbmVmOperationCREATE = PbmVmOperation("CREATE") + // Indicates reconfigure operation of a virtual machine. PbmVmOperationRECONFIGURE = PbmVmOperation("RECONFIGURE") - PbmVmOperationMIGRATE = PbmVmOperation("MIGRATE") - PbmVmOperationCLONE = PbmVmOperation("CLONE") + // Indicates migrate operation of a virtual machine. + PbmVmOperationMIGRATE = PbmVmOperation("MIGRATE") + // Indicates clone operation of a virtual machine. + PbmVmOperationCLONE = PbmVmOperation("CLONE") ) func init() { types.Add("pbm:PbmVmOperation", reflect.TypeOf((*PbmVmOperation)(nil)).Elem()) } +// The `PbmVvolType_enum` enumeration type +// defines VVOL types. +// +// VvolType's are referenced to specify which objectType +// to fetch for default capability. type PbmVvolType string const ( + // meta-data volume PbmVvolTypeConfig = PbmVvolType("Config") - PbmVvolTypeData = PbmVvolType("Data") - PbmVvolTypeSwap = PbmVvolType("Swap") + // vmdk volume + PbmVvolTypeData = PbmVvolType("Data") + // swap volume + PbmVvolTypeSwap = PbmVvolType("Swap") ) func init() { diff --git a/vendor/github.com/vmware/govmomi/pbm/types/if.go b/vendor/github.com/vmware/govmomi/pbm/types/if.go index a740a25dabe..4008dffff71 100644 --- a/vendor/github.com/vmware/govmomi/pbm/types/if.go +++ b/vendor/github.com/vmware/govmomi/pbm/types/if.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2014-2022 VMware, Inc. All Rights Reserved. +Copyright (c) 2014-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/vendor/github.com/vmware/govmomi/pbm/types/types.go b/vendor/github.com/vmware/govmomi/pbm/types/types.go index 1687df447db..4c6f72caecc 100644 --- a/vendor/github.com/vmware/govmomi/pbm/types/types.go +++ b/vendor/github.com/vmware/govmomi/pbm/types/types.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2014-2022 VMware, Inc. All Rights Reserved. +Copyright (c) 2014-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -23,246 +23,304 @@ import ( "github.com/vmware/govmomi/vim25/types" ) +// A boxed array of `PbmCapabilityConstraintInstance`. To be used in `Any` placeholders. type ArrayOfPbmCapabilityConstraintInstance struct { - PbmCapabilityConstraintInstance []PbmCapabilityConstraintInstance `xml:"PbmCapabilityConstraintInstance,omitempty"` + PbmCapabilityConstraintInstance []PbmCapabilityConstraintInstance `xml:"PbmCapabilityConstraintInstance,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilityConstraintInstance", reflect.TypeOf((*ArrayOfPbmCapabilityConstraintInstance)(nil)).Elem()) } +// A boxed array of `PbmCapabilityInstance`. To be used in `Any` placeholders. type ArrayOfPbmCapabilityInstance struct { - PbmCapabilityInstance []PbmCapabilityInstance `xml:"PbmCapabilityInstance,omitempty"` + PbmCapabilityInstance []PbmCapabilityInstance `xml:"PbmCapabilityInstance,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilityInstance", reflect.TypeOf((*ArrayOfPbmCapabilityInstance)(nil)).Elem()) } +// A boxed array of `PbmCapabilityMetadata`. To be used in `Any` placeholders. type ArrayOfPbmCapabilityMetadata struct { - PbmCapabilityMetadata []PbmCapabilityMetadata `xml:"PbmCapabilityMetadata,omitempty"` + PbmCapabilityMetadata []PbmCapabilityMetadata `xml:"PbmCapabilityMetadata,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilityMetadata", reflect.TypeOf((*ArrayOfPbmCapabilityMetadata)(nil)).Elem()) } +// A boxed array of `PbmCapabilityMetadataPerCategory`. To be used in `Any` placeholders. type ArrayOfPbmCapabilityMetadataPerCategory struct { - PbmCapabilityMetadataPerCategory []PbmCapabilityMetadataPerCategory `xml:"PbmCapabilityMetadataPerCategory,omitempty"` + PbmCapabilityMetadataPerCategory []PbmCapabilityMetadataPerCategory `xml:"PbmCapabilityMetadataPerCategory,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilityMetadataPerCategory", reflect.TypeOf((*ArrayOfPbmCapabilityMetadataPerCategory)(nil)).Elem()) } +// A boxed array of `PbmCapabilityPropertyInstance`. To be used in `Any` placeholders. type ArrayOfPbmCapabilityPropertyInstance struct { - PbmCapabilityPropertyInstance []PbmCapabilityPropertyInstance `xml:"PbmCapabilityPropertyInstance,omitempty"` + PbmCapabilityPropertyInstance []PbmCapabilityPropertyInstance `xml:"PbmCapabilityPropertyInstance,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilityPropertyInstance", reflect.TypeOf((*ArrayOfPbmCapabilityPropertyInstance)(nil)).Elem()) } +// A boxed array of `PbmCapabilityPropertyMetadata`. To be used in `Any` placeholders. type ArrayOfPbmCapabilityPropertyMetadata struct { - PbmCapabilityPropertyMetadata []PbmCapabilityPropertyMetadata `xml:"PbmCapabilityPropertyMetadata,omitempty"` + PbmCapabilityPropertyMetadata []PbmCapabilityPropertyMetadata `xml:"PbmCapabilityPropertyMetadata,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilityPropertyMetadata", reflect.TypeOf((*ArrayOfPbmCapabilityPropertyMetadata)(nil)).Elem()) } +// A boxed array of `PbmCapabilitySchema`. To be used in `Any` placeholders. type ArrayOfPbmCapabilitySchema struct { - PbmCapabilitySchema []PbmCapabilitySchema `xml:"PbmCapabilitySchema,omitempty"` + PbmCapabilitySchema []PbmCapabilitySchema `xml:"PbmCapabilitySchema,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilitySchema", reflect.TypeOf((*ArrayOfPbmCapabilitySchema)(nil)).Elem()) } +// A boxed array of `PbmCapabilitySubProfile`. To be used in `Any` placeholders. type ArrayOfPbmCapabilitySubProfile struct { - PbmCapabilitySubProfile []PbmCapabilitySubProfile `xml:"PbmCapabilitySubProfile,omitempty"` + PbmCapabilitySubProfile []PbmCapabilitySubProfile `xml:"PbmCapabilitySubProfile,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilitySubProfile", reflect.TypeOf((*ArrayOfPbmCapabilitySubProfile)(nil)).Elem()) } +// A boxed array of `PbmCapabilityVendorNamespaceInfo`. To be used in `Any` placeholders. type ArrayOfPbmCapabilityVendorNamespaceInfo struct { - PbmCapabilityVendorNamespaceInfo []PbmCapabilityVendorNamespaceInfo `xml:"PbmCapabilityVendorNamespaceInfo,omitempty"` + PbmCapabilityVendorNamespaceInfo []PbmCapabilityVendorNamespaceInfo `xml:"PbmCapabilityVendorNamespaceInfo,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilityVendorNamespaceInfo", reflect.TypeOf((*ArrayOfPbmCapabilityVendorNamespaceInfo)(nil)).Elem()) } +// A boxed array of `PbmCapabilityVendorResourceTypeInfo`. To be used in `Any` placeholders. type ArrayOfPbmCapabilityVendorResourceTypeInfo struct { - PbmCapabilityVendorResourceTypeInfo []PbmCapabilityVendorResourceTypeInfo `xml:"PbmCapabilityVendorResourceTypeInfo,omitempty"` + PbmCapabilityVendorResourceTypeInfo []PbmCapabilityVendorResourceTypeInfo `xml:"PbmCapabilityVendorResourceTypeInfo,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCapabilityVendorResourceTypeInfo", reflect.TypeOf((*ArrayOfPbmCapabilityVendorResourceTypeInfo)(nil)).Elem()) } +// A boxed array of `PbmCompliancePolicyStatus`. To be used in `Any` placeholders. type ArrayOfPbmCompliancePolicyStatus struct { - PbmCompliancePolicyStatus []PbmCompliancePolicyStatus `xml:"PbmCompliancePolicyStatus,omitempty"` + PbmCompliancePolicyStatus []PbmCompliancePolicyStatus `xml:"PbmCompliancePolicyStatus,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmCompliancePolicyStatus", reflect.TypeOf((*ArrayOfPbmCompliancePolicyStatus)(nil)).Elem()) } +// A boxed array of `PbmComplianceResult`. To be used in `Any` placeholders. type ArrayOfPbmComplianceResult struct { - PbmComplianceResult []PbmComplianceResult `xml:"PbmComplianceResult,omitempty"` + PbmComplianceResult []PbmComplianceResult `xml:"PbmComplianceResult,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmComplianceResult", reflect.TypeOf((*ArrayOfPbmComplianceResult)(nil)).Elem()) } +// A boxed array of `PbmDatastoreSpaceStatistics`. To be used in `Any` placeholders. type ArrayOfPbmDatastoreSpaceStatistics struct { - PbmDatastoreSpaceStatistics []PbmDatastoreSpaceStatistics `xml:"PbmDatastoreSpaceStatistics,omitempty"` + PbmDatastoreSpaceStatistics []PbmDatastoreSpaceStatistics `xml:"PbmDatastoreSpaceStatistics,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmDatastoreSpaceStatistics", reflect.TypeOf((*ArrayOfPbmDatastoreSpaceStatistics)(nil)).Elem()) } +// A boxed array of `PbmDefaultProfileInfo`. To be used in `Any` placeholders. type ArrayOfPbmDefaultProfileInfo struct { - PbmDefaultProfileInfo []PbmDefaultProfileInfo `xml:"PbmDefaultProfileInfo,omitempty"` + PbmDefaultProfileInfo []PbmDefaultProfileInfo `xml:"PbmDefaultProfileInfo,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmDefaultProfileInfo", reflect.TypeOf((*ArrayOfPbmDefaultProfileInfo)(nil)).Elem()) } +// A boxed array of `PbmFaultNoPermissionEntityPrivileges`. To be used in `Any` placeholders. +type ArrayOfPbmFaultNoPermissionEntityPrivileges struct { + PbmFaultNoPermissionEntityPrivileges []PbmFaultNoPermissionEntityPrivileges `xml:"PbmFaultNoPermissionEntityPrivileges,omitempty" json:"_value"` +} + +func init() { + types.Add("pbm:ArrayOfPbmFaultNoPermissionEntityPrivileges", reflect.TypeOf((*ArrayOfPbmFaultNoPermissionEntityPrivileges)(nil)).Elem()) +} + +// A boxed array of `PbmLoggingConfiguration`. To be used in `Any` placeholders. +type ArrayOfPbmLoggingConfiguration struct { + PbmLoggingConfiguration []PbmLoggingConfiguration `xml:"PbmLoggingConfiguration,omitempty" json:"_value"` +} + +func init() { + types.Add("pbm:ArrayOfPbmLoggingConfiguration", reflect.TypeOf((*ArrayOfPbmLoggingConfiguration)(nil)).Elem()) +} + +// A boxed array of `PbmPlacementCompatibilityResult`. To be used in `Any` placeholders. type ArrayOfPbmPlacementCompatibilityResult struct { - PbmPlacementCompatibilityResult []PbmPlacementCompatibilityResult `xml:"PbmPlacementCompatibilityResult,omitempty"` + PbmPlacementCompatibilityResult []PbmPlacementCompatibilityResult `xml:"PbmPlacementCompatibilityResult,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmPlacementCompatibilityResult", reflect.TypeOf((*ArrayOfPbmPlacementCompatibilityResult)(nil)).Elem()) } +// A boxed array of `PbmPlacementHub`. To be used in `Any` placeholders. type ArrayOfPbmPlacementHub struct { - PbmPlacementHub []PbmPlacementHub `xml:"PbmPlacementHub,omitempty"` + PbmPlacementHub []PbmPlacementHub `xml:"PbmPlacementHub,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmPlacementHub", reflect.TypeOf((*ArrayOfPbmPlacementHub)(nil)).Elem()) } +// A boxed array of `PbmPlacementMatchingResources`. To be used in `Any` placeholders. type ArrayOfPbmPlacementMatchingResources struct { - PbmPlacementMatchingResources []BasePbmPlacementMatchingResources `xml:"PbmPlacementMatchingResources,omitempty,typeattr"` + PbmPlacementMatchingResources []BasePbmPlacementMatchingResources `xml:"PbmPlacementMatchingResources,omitempty,typeattr" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmPlacementMatchingResources", reflect.TypeOf((*ArrayOfPbmPlacementMatchingResources)(nil)).Elem()) } +// A boxed array of `PbmPlacementRequirement`. To be used in `Any` placeholders. type ArrayOfPbmPlacementRequirement struct { - PbmPlacementRequirement []BasePbmPlacementRequirement `xml:"PbmPlacementRequirement,omitempty,typeattr"` + PbmPlacementRequirement []BasePbmPlacementRequirement `xml:"PbmPlacementRequirement,omitempty,typeattr" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmPlacementRequirement", reflect.TypeOf((*ArrayOfPbmPlacementRequirement)(nil)).Elem()) } +// A boxed array of `PbmPlacementResourceUtilization`. To be used in `Any` placeholders. type ArrayOfPbmPlacementResourceUtilization struct { - PbmPlacementResourceUtilization []PbmPlacementResourceUtilization `xml:"PbmPlacementResourceUtilization,omitempty"` + PbmPlacementResourceUtilization []PbmPlacementResourceUtilization `xml:"PbmPlacementResourceUtilization,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmPlacementResourceUtilization", reflect.TypeOf((*ArrayOfPbmPlacementResourceUtilization)(nil)).Elem()) } +// A boxed array of `PbmProfile`. To be used in `Any` placeholders. type ArrayOfPbmProfile struct { - PbmProfile []BasePbmProfile `xml:"PbmProfile,omitempty,typeattr"` + PbmProfile []BasePbmProfile `xml:"PbmProfile,omitempty,typeattr" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmProfile", reflect.TypeOf((*ArrayOfPbmProfile)(nil)).Elem()) } +// A boxed array of `PbmProfileId`. To be used in `Any` placeholders. type ArrayOfPbmProfileId struct { - PbmProfileId []PbmProfileId `xml:"PbmProfileId,omitempty"` + PbmProfileId []PbmProfileId `xml:"PbmProfileId,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmProfileId", reflect.TypeOf((*ArrayOfPbmProfileId)(nil)).Elem()) } +// A boxed array of `PbmProfileOperationOutcome`. To be used in `Any` placeholders. type ArrayOfPbmProfileOperationOutcome struct { - PbmProfileOperationOutcome []PbmProfileOperationOutcome `xml:"PbmProfileOperationOutcome,omitempty"` + PbmProfileOperationOutcome []PbmProfileOperationOutcome `xml:"PbmProfileOperationOutcome,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmProfileOperationOutcome", reflect.TypeOf((*ArrayOfPbmProfileOperationOutcome)(nil)).Elem()) } +// A boxed array of `PbmProfileResourceType`. To be used in `Any` placeholders. type ArrayOfPbmProfileResourceType struct { - PbmProfileResourceType []PbmProfileResourceType `xml:"PbmProfileResourceType,omitempty"` + PbmProfileResourceType []PbmProfileResourceType `xml:"PbmProfileResourceType,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmProfileResourceType", reflect.TypeOf((*ArrayOfPbmProfileResourceType)(nil)).Elem()) } +// A boxed array of `PbmProfileType`. To be used in `Any` placeholders. type ArrayOfPbmProfileType struct { - PbmProfileType []PbmProfileType `xml:"PbmProfileType,omitempty"` + PbmProfileType []PbmProfileType `xml:"PbmProfileType,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmProfileType", reflect.TypeOf((*ArrayOfPbmProfileType)(nil)).Elem()) } +// A boxed array of `PbmQueryProfileResult`. To be used in `Any` placeholders. type ArrayOfPbmQueryProfileResult struct { - PbmQueryProfileResult []PbmQueryProfileResult `xml:"PbmQueryProfileResult,omitempty"` + PbmQueryProfileResult []PbmQueryProfileResult `xml:"PbmQueryProfileResult,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmQueryProfileResult", reflect.TypeOf((*ArrayOfPbmQueryProfileResult)(nil)).Elem()) } +// A boxed array of `PbmQueryReplicationGroupResult`. To be used in `Any` placeholders. type ArrayOfPbmQueryReplicationGroupResult struct { - PbmQueryReplicationGroupResult []PbmQueryReplicationGroupResult `xml:"PbmQueryReplicationGroupResult,omitempty"` + PbmQueryReplicationGroupResult []PbmQueryReplicationGroupResult `xml:"PbmQueryReplicationGroupResult,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmQueryReplicationGroupResult", reflect.TypeOf((*ArrayOfPbmQueryReplicationGroupResult)(nil)).Elem()) } +// A boxed array of `PbmRollupComplianceResult`. To be used in `Any` placeholders. type ArrayOfPbmRollupComplianceResult struct { - PbmRollupComplianceResult []PbmRollupComplianceResult `xml:"PbmRollupComplianceResult,omitempty"` + PbmRollupComplianceResult []PbmRollupComplianceResult `xml:"PbmRollupComplianceResult,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmRollupComplianceResult", reflect.TypeOf((*ArrayOfPbmRollupComplianceResult)(nil)).Elem()) } +// A boxed array of `PbmServerObjectRef`. To be used in `Any` placeholders. type ArrayOfPbmServerObjectRef struct { - PbmServerObjectRef []PbmServerObjectRef `xml:"PbmServerObjectRef,omitempty"` + PbmServerObjectRef []PbmServerObjectRef `xml:"PbmServerObjectRef,omitempty" json:"_value"` } func init() { types.Add("pbm:ArrayOfPbmServerObjectRef", reflect.TypeOf((*ArrayOfPbmServerObjectRef)(nil)).Elem()) } +// The `PbmAboutInfo` data object stores identifying data +// about the Storage Policy Server. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmAboutInfo struct { types.DynamicData - Name string `xml:"name"` - Version string `xml:"version"` - InstanceUuid string `xml:"instanceUuid"` + // Name of the server. + Name string `xml:"name" json:"name"` + // Version number. + Version string `xml:"version" json:"version"` + // Globally unique identifier associated with this server instance. + InstanceUuid string `xml:"instanceUuid" json:"instanceUuid"` } func init() { types.Add("pbm:PbmAboutInfo", reflect.TypeOf((*PbmAboutInfo)(nil)).Elem()) } +// An AlreadyExists fault is thrown when an attempt is made to add an element to +// a collection, if the element's key, name, or identifier already exists in +// that collection. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmAlreadyExists struct { PbmFault - Name string `xml:"name,omitempty"` + Name string `xml:"name,omitempty" json:"name,omitempty"` } func init() { @@ -281,10 +339,13 @@ func init() { types.Add("pbm:PbmAssignDefaultRequirementProfile", reflect.TypeOf((*PbmAssignDefaultRequirementProfile)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmAssignDefaultRequirementProfile`. type PbmAssignDefaultRequirementProfileRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Profile PbmProfileId `xml:"profile"` - Datastores []PbmPlacementHub `xml:"datastores"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // The profile that needs to be made default profile. + Profile PbmProfileId `xml:"profile" json:"profile"` + // The datastores for which the profile needs to be made as default profile. + Datastores []PbmPlacementHub `xml:"datastores" json:"datastores"` } func init() { @@ -294,16 +355,26 @@ func init() { type PbmAssignDefaultRequirementProfileResponse struct { } +// Constraints on the properties for a single occurrence of a capability. +// +// All properties must satisfy their respective constraints to be compliant. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityConstraintInstance struct { types.DynamicData - PropertyInstance []PbmCapabilityPropertyInstance `xml:"propertyInstance"` + // Property instance array for this constraint + PropertyInstance []PbmCapabilityPropertyInstance `xml:"propertyInstance" json:"propertyInstance"` } func init() { types.Add("pbm:PbmCapabilityConstraintInstance", reflect.TypeOf((*PbmCapabilityConstraintInstance)(nil)).Elem()) } +// The `PbmCapabilityConstraints` data object is the base +// object for capability subprofile constraints. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityConstraints struct { types.DynamicData } @@ -312,69 +383,161 @@ func init() { types.Add("pbm:PbmCapabilityConstraints", reflect.TypeOf((*PbmCapabilityConstraints)(nil)).Elem()) } +// A property value with description. +// +// It can be repeated under DiscreteSet. +// E.g., set of tags, each with description and tag name. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityDescription struct { types.DynamicData - Description PbmExtendedElementDescription `xml:"description"` - Value types.AnyType `xml:"value,typeattr"` + // Description of the property value + Description PbmExtendedElementDescription `xml:"description" json:"description"` + // Values for the set. + // + // must be one of the supported datatypes as + // defined in `PbmBuiltinType_enum` + // Must only contain unique values to comply with the Set semantics + Value types.AnyType `xml:"value,typeattr" json:"value"` } func init() { types.Add("pbm:PbmCapabilityDescription", reflect.TypeOf((*PbmCapabilityDescription)(nil)).Elem()) } +// The `PbmCapabilityDiscreteSet` data object defines a set of values +// for storage profile property instances (`PbmCapabilityPropertyInstance`). +// +// Use the discrete set type to define a set of values of a supported builtin type +// (`PbmBuiltinType_enum`), for example a set of integers +// (XSD\_INT) or a set of unsigned long values (XSD\_LONG). +// See `PbmBuiltinGenericType_enum*.*VMW_SET`. +// +// A discrete set of values is declared as an array of xsd:anyType values. +// - When you define a property instance for a storage profile requirement +// and pass an array of values to the Server, you must set the array elements +// to values of the appropriate datatype. +// - When you read a discrete set from a property instance for a storage profile +// capability, you must cast the xsd:anyType array element values +// to the appropriate datatype. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityDiscreteSet struct { types.DynamicData - Values []types.AnyType `xml:"values,typeattr"` + // Array of values for the set. + // + // The values must be one of the supported datatypes + // as defined in `PbmBuiltinType_enum` or `PbmBuiltinGenericType_enum`. + Values []types.AnyType `xml:"values,typeattr" json:"values"` } func init() { types.Add("pbm:PbmCapabilityDiscreteSet", reflect.TypeOf((*PbmCapabilityDiscreteSet)(nil)).Elem()) } +// Generic type definition for capabilities. +// +// Indicates how a collection of values of a specific datatype +// (`PbmCapabilityTypeInfo.typeName`) +// will be interpreted. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityGenericTypeInfo struct { PbmCapabilityTypeInfo - GenericTypeName string `xml:"genericTypeName"` + // Name of the generic type. + // + // Must correspond to one of the values defined in + // `PbmBuiltinGenericType_enum`. + GenericTypeName string `xml:"genericTypeName" json:"genericTypeName"` } func init() { types.Add("pbm:PbmCapabilityGenericTypeInfo", reflect.TypeOf((*PbmCapabilityGenericTypeInfo)(nil)).Elem()) } +// The `PbmCapabilityInstance` data object defines a storage capability instance. +// +// Metadata for the capability is described in `PbmCapabilityMetadata`. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityInstance struct { types.DynamicData - Id PbmCapabilityMetadataUniqueId `xml:"id"` - Constraint []PbmCapabilityConstraintInstance `xml:"constraint"` + // Identifier for the capability. + // + // The identifier value corresponds to + // `PbmCapabilityMetadata*.*PbmCapabilityMetadata.id`. + Id PbmCapabilityMetadataUniqueId `xml:"id" json:"id"` + // Constraints on the properties that comprise this capability. + // + // Each entry represents a constraint on one or more of the properties that + // constitute this capability. A datum must meet one of the + // constraints to be compliant. + Constraint []PbmCapabilityConstraintInstance `xml:"constraint" json:"constraint"` } func init() { types.Add("pbm:PbmCapabilityInstance", reflect.TypeOf((*PbmCapabilityInstance)(nil)).Elem()) } +// Metadata for a single unique setting defined by a provider. +// +// A simple setting is a setting with one property. +// A complex setting contains more than one property. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityMetadata struct { types.DynamicData - Id PbmCapabilityMetadataUniqueId `xml:"id"` - Summary PbmExtendedElementDescription `xml:"summary"` - Mandatory *bool `xml:"mandatory"` - Hint *bool `xml:"hint"` - KeyId string `xml:"keyId,omitempty"` - AllowMultipleConstraints *bool `xml:"allowMultipleConstraints"` - PropertyMetadata []PbmCapabilityPropertyMetadata `xml:"propertyMetadata"` + // Unique identifier for the capability. + Id PbmCapabilityMetadataUniqueId `xml:"id" json:"id"` + // Capability name and description + Summary PbmExtendedElementDescription `xml:"summary" json:"summary"` + // Indicates whether incorporating given capability is mandatory during creation of + // profile. + Mandatory *bool `xml:"mandatory" json:"mandatory,omitempty"` + // The flag hint dictates the interpretation of constraints specified for this capability + // in a storage policy profile. + // + // If hint is false, then constraints will affect placement. + // If hint is true, constraints will not affect placement, + // but will still be passed to provisioning operations if the provider understands the + // relevant namespace. Optional property, false if not set. + Hint *bool `xml:"hint" json:"hint,omitempty"` + // Property Id of the key property, if this capability represents a key + // value pair. + // + // Value is empty string if not set. + KeyId string `xml:"keyId,omitempty" json:"keyId,omitempty"` + // Flag to indicate if multiple constraints are allowed in the capability + // instance. + // + // False if not set. + AllowMultipleConstraints *bool `xml:"allowMultipleConstraints" json:"allowMultipleConstraints,omitempty"` + // Metadata for the properties that comprise this capability. + PropertyMetadata []PbmCapabilityPropertyMetadata `xml:"propertyMetadata" json:"propertyMetadata"` } func init() { types.Add("pbm:PbmCapabilityMetadata", reflect.TypeOf((*PbmCapabilityMetadata)(nil)).Elem()) } +// The `PbmCapabilityMetadataPerCategory` +// data object defines capability metadata for a profile subcategory. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityMetadataPerCategory struct { types.DynamicData - SubCategory string `xml:"subCategory"` - CapabilityMetadata []PbmCapabilityMetadata `xml:"capabilityMetadata"` + // Profile subcategory to which the capability metadata belongs. + // + // The subcategory is specified by the storage provider. + SubCategory string `xml:"subCategory" json:"subCategory"` + // Capability metadata for this category + CapabilityMetadata []PbmCapabilityMetadata `xml:"capabilityMetadata" json:"capabilityMetadata"` } func init() { @@ -384,60 +547,162 @@ func init() { type PbmCapabilityMetadataUniqueId struct { types.DynamicData - Namespace string `xml:"namespace"` - Id string `xml:"id"` + // Namespace to which this capability belongs. + // + // Must be the same as + // { @link CapabilityObjectSchema#namespace } defined for this + // capability + Namespace string `xml:"namespace" json:"namespace"` + // unique identifier for this capability within given namespace + Id string `xml:"id" json:"id"` } func init() { types.Add("pbm:PbmCapabilityMetadataUniqueId", reflect.TypeOf((*PbmCapabilityMetadataUniqueId)(nil)).Elem()) } +// Name space information for the capability metadata schema. +// +// NOTE: Name spaces are required to be globally unique across resource types. +// A same vendor can register multiple name spaces for same resource type or +// for different resource type, but the schema namespace URL must be unique +// for each of these cases. +// A CapabilityMetadata object is uniquely identified based on the namespace +// it belongs to and it's unique identifier within that namespace. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityNamespaceInfo struct { types.DynamicData - Version string `xml:"version"` - Namespace string `xml:"namespace"` - Info *PbmExtendedElementDescription `xml:"info,omitempty"` + // Schema version + Version string `xml:"version" json:"version"` + // Schema namespace. + Namespace string `xml:"namespace" json:"namespace"` + Info *PbmExtendedElementDescription `xml:"info,omitempty" json:"info,omitempty"` } func init() { types.Add("pbm:PbmCapabilityNamespaceInfo", reflect.TypeOf((*PbmCapabilityNamespaceInfo)(nil)).Elem()) } +// The `PbmCapabilityProfile` data object defines +// capability-based profiles. +// +// A capability-based profile is derived +// from tag-based storage capabilities or from vSAN storage capabilities. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityProfile struct { PbmProfile - ProfileCategory string `xml:"profileCategory"` - ResourceType PbmProfileResourceType `xml:"resourceType"` - Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr"` - GenerationId int64 `xml:"generationId,omitempty"` - IsDefault bool `xml:"isDefault"` - SystemCreatedProfileType string `xml:"systemCreatedProfileType,omitempty"` - LineOfService string `xml:"lineOfService,omitempty"` + // Indicates whether the profile is requirement + // profile, a resource profile or a data service profile. + // + // The profileCategory + // is a string value that corresponds to one of the + // `PbmProfileCategoryEnum_enum` values. + // - REQUIREMENT profile - Defines the storage constraints applied + // to virtual machine placement. Requirements are defined by + // the user and can be associated with virtual machines and virtual + // disks. During provisioning, you can use a requirements profile + // for compliance and placement checking to support + // selection and configuration of resources. + // - RESOURCE profile - Specifies system-defined storage capabilities. + // You cannot modify a resource profile. You cannot associate a resource + // profile with vSphere entities, use it during provisioning, or target + // entities for resource selection or configuration. + // This type of profile gives the user visibility into the capabilities + // supported by the storage provider. + // + // DATA\_SERVICE\_POLICY - Indicates a data service policy that can + // be embedded into another storage policy. Policies of this type can't + // be assigned to Virtual Machines or Virtual Disks. This policy cannot + // be used for compliance checking. + ProfileCategory string `xml:"profileCategory" json:"profileCategory"` + // Type of the target resource to which the capability information applies. + // + // A fixed enum that defines resource types for which capabilities can be defined + // see `PbmProfileResourceType`, `PbmProfileResourceTypeEnum_enum` + ResourceType PbmProfileResourceType `xml:"resourceType" json:"resourceType"` + // Subprofiles that describe storage requirements or storage provider capabilities, + // depending on the profile category (REQUIREMENT or RESOURCE). + Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr" json:"constraints"` + // Generation ID is used to communicate the current version of the profile to VASA + // providers. + // + // It is only applicable to REQUIREMENT profile types. Every time a + // requirement profile is edited, the Server will increment the generationId. You + // do not need to set the generationID. When an object is created (or + // reconfigured), the Server will send the requirement profile content, profile ID and + // the generationID to VASA provider. + GenerationId int64 `xml:"generationId,omitempty" json:"generationId,omitempty"` + // Deprecated since it is not supported. + // + // Not supported in this release. + IsDefault bool `xml:"isDefault" json:"isDefault"` + // Indicates the type of system pre-created default profile. + // + // This will be set only for system pre-created default profiles. And + // this is not set for RESOURCE profiles. + SystemCreatedProfileType string `xml:"systemCreatedProfileType,omitempty" json:"systemCreatedProfileType,omitempty"` + // This property is set only for data service policy. + // + // Indicates the line of service + // `PbmLineOfServiceInfoLineOfServiceEnum_enum` of the data service policy. + LineOfService string `xml:"lineOfService,omitempty" json:"lineOfService,omitempty"` } func init() { types.Add("pbm:PbmCapabilityProfile", reflect.TypeOf((*PbmCapabilityProfile)(nil)).Elem()) } +// The `PbmCapabilityProfileCreateSpec` describes storage requirements. +// +// Use this data object to create a `PbmCapabilityProfile`. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityProfileCreateSpec struct { types.DynamicData - Name string `xml:"name"` - Description string `xml:"description,omitempty"` - Category string `xml:"category,omitempty"` - ResourceType PbmProfileResourceType `xml:"resourceType"` - Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr"` + // Name of the capability based profile to be created. + // + // The maximum length of the name is 80 characters. + Name string `xml:"name" json:"name"` + // Text description associated with the profile. + Description string `xml:"description,omitempty" json:"description,omitempty"` + // Category specifies the type of policy to be created. + // + // This can be REQUIREMENT from + // `PbmProfileCategoryEnum_enum` + // or null when creating a storage policy. And it can be DATA\_SERVICE\_POLICY from + // `PbmProfileCategoryEnum_enum` + // when creating a data service policy. RESOURCE from `PbmProfileCategoryEnum_enum` + // is not allowed as resource profile is created by the system. + Category string `xml:"category,omitempty" json:"category,omitempty"` + // Deprecated as of vSphere API 6.5. + // + // Specifies the type of resource to which the profile applies. + // + // The only legal value is STORAGE - deprecated. + ResourceType PbmProfileResourceType `xml:"resourceType" json:"resourceType"` + // Set of subprofiles that define the storage requirements. + // + // A subprofile corresponds to a rule set in the vSphere Web Client. + Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr" json:"constraints"` } func init() { types.Add("pbm:PbmCapabilityProfileCreateSpec", reflect.TypeOf((*PbmCapabilityProfileCreateSpec)(nil)).Elem()) } +// Fault used when a datastore doesnt match the capability profile property instance in requirements profile. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityProfilePropertyMismatchFault struct { PbmPropertyMismatchFault - ResourcePropertyInstance PbmCapabilityPropertyInstance `xml:"resourcePropertyInstance"` + // The property instance in the resource profile that does not match. + ResourcePropertyInstance PbmCapabilityPropertyInstance `xml:"resourcePropertyInstance" json:"resourcePropertyInstance"` } func init() { @@ -450,118 +715,347 @@ func init() { types.Add("pbm:PbmCapabilityProfilePropertyMismatchFaultFault", reflect.TypeOf((*PbmCapabilityProfilePropertyMismatchFaultFault)(nil)).Elem()) } +// The `PbmCapabilityProfileUpdateSpec` data object +// contains data that you use to update a storage profile. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityProfileUpdateSpec struct { types.DynamicData - Name string `xml:"name,omitempty"` - Description string `xml:"description,omitempty"` - Constraints BasePbmCapabilityConstraints `xml:"constraints,omitempty,typeattr"` + // Specifies a new profile name. + Name string `xml:"name,omitempty" json:"name,omitempty"` + // Specifies a new profile description. + Description string `xml:"description,omitempty" json:"description,omitempty"` + // Specifies one or more subprofiles. + // + // A subprofile defines one or more + // storage requirements. + Constraints BasePbmCapabilityConstraints `xml:"constraints,omitempty,typeattr" json:"constraints,omitempty"` } func init() { types.Add("pbm:PbmCapabilityProfileUpdateSpec", reflect.TypeOf((*PbmCapabilityProfileUpdateSpec)(nil)).Elem()) } +// The `PbmCapabilityPropertyInstance` data object describes a virtual machine +// storage requirement. +// +// A storage requirement is based on the storage capability +// described in the `PbmCapabilityPropertyMetadata` and in the +// datastore profile property instance. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityPropertyInstance struct { types.DynamicData - Id string `xml:"id"` - Operator string `xml:"operator,omitempty"` - Value types.AnyType `xml:"value,typeattr"` + // Requirement property identifier. + // + // This identifier corresponds to the + // storage capability metadata identifier + // (`PbmCapabilityPropertyMetadata*.*PbmCapabilityPropertyMetadata.id`). + Id string `xml:"id" json:"id"` + // Operator for the values. + // + // Currently only support NOT operator for + // tag namespace + // See operator definition in (`PbmCapabilityOperator_enum`). + Operator string `xml:"operator,omitempty" json:"operator,omitempty"` + // Property value. + // + // You must specify the value. + // A property value is one value or a collection of values. + // - A single property value is expressed as a scalar value. + // - A collection of values is expressed as a `PbmCapabilityDiscreteSet` + // or a `PbmCapabilityRange` of values. + // + // The datatype of each value must be one of the + // `PbmBuiltinType_enum` datatypes. + // If the property consists of a collection of values, + // the interpretation of those values is determined by the + // `PbmCapabilityGenericTypeInfo`. + // + // Type information for a property instance is described in the property metadata + // (`PbmCapabilityPropertyMetadata*.*PbmCapabilityPropertyMetadata.type`). + Value types.AnyType `xml:"value,typeattr" json:"value"` } func init() { types.Add("pbm:PbmCapabilityPropertyInstance", reflect.TypeOf((*PbmCapabilityPropertyInstance)(nil)).Elem()) } +// The `PbmCapabilityPropertyMetadata` data object describes storage capability. +// +// An instance of property metadata may apply to many property instances +// (`PbmCapabilityPropertyInstance`). +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityPropertyMetadata struct { types.DynamicData - Id string `xml:"id"` - Summary PbmExtendedElementDescription `xml:"summary"` - Mandatory bool `xml:"mandatory"` - Type BasePbmCapabilityTypeInfo `xml:"type,omitempty,typeattr"` - DefaultValue types.AnyType `xml:"defaultValue,omitempty,typeattr"` - AllowedValue types.AnyType `xml:"allowedValue,omitempty,typeattr"` - RequirementsTypeHint string `xml:"requirementsTypeHint,omitempty"` + // Property identifier. + // + // Should be unique within the definition of the + // capability. Property instances refer to this identifier + // (`PbmCapabilityPropertyInstance*.*PbmCapabilityPropertyInstance.id`). + Id string `xml:"id" json:"id"` + // Property name and description. + // - The summary.label property + // (`PbmExtendedElementDescription.label`) + // contains property 'name' in server locale. + // - The summary.summary property + // (`PbmExtendedElementDescription.summary`) + // contains property 'description' in server locale. + // - The summary.messageCatalogKeyPrefix property + // (`PbmExtendedElementDescription.messageCatalogKeyPrefix`) + // contains unique prefix for this property within given message catalog. + // Prefix format: <capability\_unique\_identifier.<property\_id + // capability\_unique\_identifier -- string representation of + // `PbmCapabilityMetadataUniqueId` which globally identifies given + // capability metadata definition uniquely. + // property\_id -- 'id' of this property `PbmCapabilityPropertyMetadata.id` + // Eg www.emc.com.storage.Recovery.Recovery\_site + // www.emc.com.storage.Recovery.RPO + // www.emc.com.storage.Recovery.RTO + Summary PbmExtendedElementDescription `xml:"summary" json:"summary"` + // Indicates whether incorporating given capability is mandatory during creation of + // profile. + Mandatory bool `xml:"mandatory" json:"mandatory"` + // Type information for the capability. + // + // The type of a property value + // (`PbmCapabilityPropertyInstance*.*PbmCapabilityPropertyInstance.value`) + // is specified as a builtin datatype and may also specify the interpretation of a + // collection of values of that datatype. + // - `PbmCapabilityPropertyMetadata.type*.*PbmCapabilityTypeInfo.typeName` + // specifies the `PbmBuiltinType_enum`. + // - `PbmCapabilityPropertyMetadata.type*.*PbmCapabilityGenericTypeInfo.genericTypeName` + // indicates how a collection of values of the specified datatype will be interpreted + // (`PbmBuiltinGenericType_enum`). + Type BasePbmCapabilityTypeInfo `xml:"type,omitempty,typeattr" json:"type,omitempty"` + // Default value, if any, that the property will assume when not + // constrained by requirements. + // + // This object must be of the + // `PbmCapabilityPropertyMetadata.type` + // defined for the property. + DefaultValue types.AnyType `xml:"defaultValue,omitempty,typeattr" json:"defaultValue,omitempty"` + // All legal values that the property may take on, across all + // implementations of the property. + // + // This definition of legal values is not + // determined by any particular resource configuration; rather it is + // inherent to the definition of the property. If undefined, then any value + // of the correct type is legal. This object must be a generic container for + // the `PbmCapabilityPropertyMetadata.type` + // defined for the property; + // see `PbmBuiltinGenericType_enum` + // for the supported generic container types. + AllowedValue types.AnyType `xml:"allowedValue,omitempty,typeattr" json:"allowedValue,omitempty"` + // A hint for data-driven systems that assist in authoring requirements + // constraints. + // + // Acceptable values defined by + // `PbmBuiltinGenericType_enum`. + // A property will typically only have constraints of a given type in + // requirement profiles, even if it is likely to use constraints of + // different types across capability profiles. This value, if specified, + // specifies the expected kind of constraint used in requirement profiles. + // Considerations for using this information: + // - This is only a hint; any properly formed constraint + // (see `PbmCapabilityPropertyInstance.value`) + // is still valid for a requirement profile. + // - If VMW\_SET is hinted, then a single value matching the property metadata type is + // also an expected form of constraint, as the latter is an allowed convenience + // for expressing a single-member set. + // - If this hint is not specified, then the authoring system may default to a form of + // constraint determined by its own criteria. + RequirementsTypeHint string `xml:"requirementsTypeHint,omitempty" json:"requirementsTypeHint,omitempty"` } func init() { types.Add("pbm:PbmCapabilityPropertyMetadata", reflect.TypeOf((*PbmCapabilityPropertyMetadata)(nil)).Elem()) } +// The `PbmCapabilityRange` data object defines a range of values for storage property +// instances (`PbmCapabilityPropertyInstance`). +// +// Use the range type to define a range of values of a supported builtin type, +// for example range<int>, range<long>, or range<timespan>. +// You can specify a partial range by omitting one of the properties, min or max. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityRange struct { types.DynamicData - Min types.AnyType `xml:"min,typeattr"` - Max types.AnyType `xml:"max,typeattr"` + // Minimum value of range. + // + // Must be one of the supported + // datatypes as defined in `PbmBuiltinType_enum`. + // Must be the same datatype as min. + Min types.AnyType `xml:"min,typeattr" json:"min"` + // Maximum value of range. + // + // Must be one of the supported + // datatypes as defined in `PbmBuiltinType_enum`. + // Must be the same datatype as max. + Max types.AnyType `xml:"max,typeattr" json:"max"` } func init() { types.Add("pbm:PbmCapabilityRange", reflect.TypeOf((*PbmCapabilityRange)(nil)).Elem()) } +// Capability Schema information +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilitySchema struct { types.DynamicData - VendorInfo PbmCapabilitySchemaVendorInfo `xml:"vendorInfo"` - NamespaceInfo PbmCapabilityNamespaceInfo `xml:"namespaceInfo"` - LineOfService BasePbmLineOfServiceInfo `xml:"lineOfService,omitempty,typeattr"` - CapabilityMetadataPerCategory []PbmCapabilityMetadataPerCategory `xml:"capabilityMetadataPerCategory"` + VendorInfo PbmCapabilitySchemaVendorInfo `xml:"vendorInfo" json:"vendorInfo"` + NamespaceInfo PbmCapabilityNamespaceInfo `xml:"namespaceInfo" json:"namespaceInfo"` + // Service type for the schema. + // + // Do not use Category as each service needs to have its own schema version. + // + // If omitted, this schema specifies persistence capabilities. + LineOfService BasePbmLineOfServiceInfo `xml:"lineOfService,omitempty,typeattr" json:"lineOfService,omitempty"` + // Capability metadata organized by category + CapabilityMetadataPerCategory []PbmCapabilityMetadataPerCategory `xml:"capabilityMetadataPerCategory" json:"capabilityMetadataPerCategory"` } func init() { types.Add("pbm:PbmCapabilitySchema", reflect.TypeOf((*PbmCapabilitySchema)(nil)).Elem()) } +// Information about vendor/owner of the capability metadata schema +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilitySchemaVendorInfo struct { types.DynamicData - VendorUuid string `xml:"vendorUuid"` - Info PbmExtendedElementDescription `xml:"info"` + // Unique identifier for the vendor who owns the given capability + // schema definition + VendorUuid string `xml:"vendorUuid" json:"vendorUuid"` + // Captures name and description information about the vendor/owner of + // the schema. + // - The summary.label property + // (`PbmExtendedElementDescription.label`) + // contains vendor name information in server locale. + // - The summary.summary property + // (`PbmExtendedElementDescription.summary`) + // contains vendor description string in server locale. + // - The summary.messageCatalogKeyPrefix property + // (`PbmExtendedElementDescription.messageCatalogKeyPrefix`) + // contains unique prefix for the vendor information within given message + // catalog. + Info PbmExtendedElementDescription `xml:"info" json:"info"` } func init() { types.Add("pbm:PbmCapabilitySchemaVendorInfo", reflect.TypeOf((*PbmCapabilitySchemaVendorInfo)(nil)).Elem()) } +// A `PbmCapabilitySubProfile` +// is a section within a profile that aggregates one or more capability +// instances. +// +// Capability instances define storage constraints. +// +// All constraints within a subprofile are ANDed by default. +// When you perform compliance checking on a virtual machine or virtual +// disk, all of the constraints must be satisfied by the storage capabilities. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilitySubProfile struct { types.DynamicData - Name string `xml:"name"` - Capability []PbmCapabilityInstance `xml:"capability"` - ForceProvision *bool `xml:"forceProvision"` + // Subprofile name. + Name string `xml:"name" json:"name"` + // List of capability instances. + Capability []PbmCapabilityInstance `xml:"capability" json:"capability"` + // Indicates whether the source policy profile allows creating a virtual machine + // or virtual disk that may be non-compliant. + ForceProvision *bool `xml:"forceProvision" json:"forceProvision,omitempty"` } func init() { types.Add("pbm:PbmCapabilitySubProfile", reflect.TypeOf((*PbmCapabilitySubProfile)(nil)).Elem()) } +// The `PbmCapabilitySubProfileConstraints` data object defines a group +// of storage subprofiles. +// +// Subprofile usage depends on the type of profile +// (`PbmCapabilityProfile*.*PbmCapabilityProfile.profileCategory`). +// - For a REQUIREMENTS profile, each subprofile defines storage requirements. +// A Storage Policy API requirements subprofile corresponds to a vSphere Web Client +// rule set. +// - For a RESOURCE profile, each subprofile defines storage capabilities. +// Storage capabilities are read-only. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilitySubProfileConstraints struct { PbmCapabilityConstraints - SubProfiles []PbmCapabilitySubProfile `xml:"subProfiles"` + // Aggregation of one or more subprofiles. + // + // The relationship among all subprofiles is "OR". When you perform + // compliance checking on a profile that contains more than one subprofile, + // a non-compliant result for any one of the subprofiles will produce a + // non-compliant result for the operation. + SubProfiles []PbmCapabilitySubProfile `xml:"subProfiles" json:"subProfiles"` } func init() { types.Add("pbm:PbmCapabilitySubProfileConstraints", reflect.TypeOf((*PbmCapabilitySubProfileConstraints)(nil)).Elem()) } +// The `PbmCapabilityTimeSpan` data object defines a time value and time unit, +// for example 10 hours or 5 minutes. +// +// See +// `PbmBuiltinType_enum*.*VMW_TIMESPAN`. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityTimeSpan struct { types.DynamicData - Value int32 `xml:"value"` - Unit string `xml:"unit"` + // Time value. + // + // Must be a positive integer. + Value int32 `xml:"value" json:"value"` + // Unit value for time. + // + // The string value must correspond + // to one of the `PbmCapabilityTimeUnitType_enum` values. + Unit string `xml:"unit" json:"unit"` } func init() { types.Add("pbm:PbmCapabilityTimeSpan", reflect.TypeOf((*PbmCapabilityTimeSpan)(nil)).Elem()) } +// The `PbmCapabilityTypeInfo` data object defines the datatype for a requirement +// or capability property. +// +// See `PbmCapabilityPropertyMetadata`. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCapabilityTypeInfo struct { types.DynamicData - TypeName string `xml:"typeName"` + // Datatype for a property. + // + // Must be one of the types defined + // in `PbmBuiltinType_enum`. + // + // A property value might consist of a collection of values of the specified + // datatype. The interpretation of the collection is determined by the + // generic type (`PbmCapabilityGenericTypeInfo.genericTypeName`). + // The generic type indicates how a collection of values + // of the specified datatype will be interpreted. See the descriptions of the + // `PbmBuiltinType_enum` definitions. + TypeName string `xml:"typeName" json:"typeName"` } func init() { @@ -571,8 +1065,8 @@ func init() { type PbmCapabilityVendorNamespaceInfo struct { types.DynamicData - VendorInfo PbmCapabilitySchemaVendorInfo `xml:"vendorInfo"` - NamespaceInfo PbmCapabilityNamespaceInfo `xml:"namespaceInfo"` + VendorInfo PbmCapabilitySchemaVendorInfo `xml:"vendorInfo" json:"vendorInfo"` + NamespaceInfo PbmCapabilityNamespaceInfo `xml:"namespaceInfo" json:"namespaceInfo"` } func init() { @@ -582,8 +1076,14 @@ func init() { type PbmCapabilityVendorResourceTypeInfo struct { types.DynamicData - ResourceType string `xml:"resourceType"` - VendorNamespaceInfo []PbmCapabilityVendorNamespaceInfo `xml:"vendorNamespaceInfo"` + // Resource type for which given vendor has registered given namespace + // along with capability metadata that belongs to the namespace. + // + // Must match one of the values for enum `PbmProfileResourceTypeEnum_enum` + ResourceType string `xml:"resourceType" json:"resourceType"` + // List of all vendorInfo -- namespaceInfo tuples that are registered for + // given resource type + VendorNamespaceInfo []PbmCapabilityVendorNamespaceInfo `xml:"vendorNamespaceInfo" json:"vendorNamespaceInfo"` } func init() { @@ -596,10 +1096,16 @@ func init() { types.Add("pbm:PbmCheckCompatibility", reflect.TypeOf((*PbmCheckCompatibility)(nil)).Elem()) } +// The parameters of `PbmPlacementSolver.PbmCheckCompatibility`. type PbmCheckCompatibilityRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"` - Profile PbmProfileId `xml:"profile"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Candidate list of hubs, either datastores or storage pods or a + // mix. If this parameter is not specified, the Server uses all + // of the datastores and storage pods for placement compatibility + // checking. + HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty" json:"hubsToSearch,omitempty"` + // Storage requirement profile. + Profile PbmProfileId `xml:"profile" json:"profile"` } func init() { @@ -607,7 +1113,7 @@ func init() { } type PbmCheckCompatibilityResponse struct { - Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty"` + Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmCheckCompatibilityWithSpec PbmCheckCompatibilityWithSpecRequestType @@ -616,10 +1122,15 @@ func init() { types.Add("pbm:PbmCheckCompatibilityWithSpec", reflect.TypeOf((*PbmCheckCompatibilityWithSpec)(nil)).Elem()) } +// The parameters of `PbmPlacementSolver.PbmCheckCompatibilityWithSpec`. type PbmCheckCompatibilityWithSpecRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"` - ProfileSpec PbmCapabilityProfileCreateSpec `xml:"profileSpec"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Candidate list of hubs, either datastores or storage pods + // or a mix. If this parameter is not specified, the Server uses all of the + // datastores and storage pods for placement compatibility checking. + HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty" json:"hubsToSearch,omitempty"` + // Specification for a capability based profile. + ProfileSpec PbmCapabilityProfileCreateSpec `xml:"profileSpec" json:"profileSpec"` } func init() { @@ -627,7 +1138,7 @@ func init() { } type PbmCheckCompatibilityWithSpecResponse struct { - Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty"` + Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmCheckCompliance PbmCheckComplianceRequestType @@ -636,10 +1147,31 @@ func init() { types.Add("pbm:PbmCheckCompliance", reflect.TypeOf((*PbmCheckCompliance)(nil)).Elem()) } +// The parameters of `PbmComplianceManager.PbmCheckCompliance`. type PbmCheckComplianceRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Entities []PbmServerObjectRef `xml:"entities"` - Profile *PbmProfileId `xml:"profile,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // One or more references to storage entities. + // You can specify virtual machines and virtual disks + // A maximum of 1000 virtual machines and/or virtual disks can be specified + // in a call. The results of calling the checkCompliance API with + // more than a 1000 entities is undefined. + // - If the list of entities also contains datastores, the Server + // will ignore the datastores. + // - If the list contains valid and invalid entities, the Server ignores + // the invalid entities and returns results for the valid entities. + // Invalid entities are entities that are not in the vCenter inventory. + // - If the list contains only datastores, the method throws + // an InvalidArgument fault. + // - If the list contains virtual machines and disks and the entities + // are invalid or have been deleted by the time of the request, the method + // throws an InvalidArgument fault. + // + // If an entity does not have an associated storage profile, the entity + // is removed from the list. + Entities []PbmServerObjectRef `xml:"entities" json:"entities"` + // Not used. If specified, the Server ignores the value. + // The Server uses the profiles associated with the specified entities. + Profile *PbmProfileId `xml:"profile,omitempty" json:"profile,omitempty"` } func init() { @@ -647,7 +1179,7 @@ func init() { } type PbmCheckComplianceResponse struct { - Returnval []PbmComplianceResult `xml:"returnval,omitempty"` + Returnval []PbmComplianceResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmCheckRequirements PbmCheckRequirementsRequestType @@ -656,11 +1188,27 @@ func init() { types.Add("pbm:PbmCheckRequirements", reflect.TypeOf((*PbmCheckRequirements)(nil)).Elem()) } +// The parameters of `PbmPlacementSolver.PbmCheckRequirements`. type PbmCheckRequirementsRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"` - PlacementSubjectRef *PbmServerObjectRef `xml:"placementSubjectRef,omitempty"` - PlacementSubjectRequirement []BasePbmPlacementRequirement `xml:"placementSubjectRequirement,omitempty,typeattr"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Candidate list of hubs, either datastores or storage pods + // or a mix. If this parameter is not specified, the Server uses all of the + // datastores and storage pods for placement compatibility checking. + HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty" json:"hubsToSearch,omitempty"` + // reference to the object being placed. Should be null when a new + // object is being provisioned. Should be specified when placement compatibility is being checked + // for an existing object. Supported objects are + // `virtualMachine`, + // `virtualMachineAndDisks`, + // `virtualDiskId`, + // `virtualDiskUUID` + PlacementSubjectRef *PbmServerObjectRef `xml:"placementSubjectRef,omitempty" json:"placementSubjectRef,omitempty"` + // Requirements including the policy requirements, compute + // requirements and capacity requirements. It is invalid to specify no requirements. It is also + // invalid to specify duplicate requirements or multiple conflicting requirements such as + // specifying both `PbmPlacementCapabilityConstraintsRequirement` and + // `PbmPlacementCapabilityProfileRequirement`. + PlacementSubjectRequirement []BasePbmPlacementRequirement `xml:"placementSubjectRequirement,omitempty,typeattr" json:"placementSubjectRequirement,omitempty"` } func init() { @@ -668,7 +1216,7 @@ func init() { } type PbmCheckRequirementsResponse struct { - Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty"` + Returnval []PbmPlacementCompatibilityResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmCheckRollupCompliance PbmCheckRollupComplianceRequestType @@ -677,9 +1225,14 @@ func init() { types.Add("pbm:PbmCheckRollupCompliance", reflect.TypeOf((*PbmCheckRollupCompliance)(nil)).Elem()) } +// The parameters of `PbmComplianceManager.PbmCheckRollupCompliance`. type PbmCheckRollupComplianceRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Entity []PbmServerObjectRef `xml:"entity"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // One or more references to virtual machines. + // A maximum of 1000 virtual machines can be specified + // in a call. The results of calling the checkRollupCompliance API with + // more than a 1000 entities is undefined. + Entity []PbmServerObjectRef `xml:"entity" json:"entity"` } func init() { @@ -687,13 +1240,17 @@ func init() { } type PbmCheckRollupComplianceResponse struct { - Returnval []PbmRollupComplianceResult `xml:"returnval,omitempty"` + Returnval []PbmRollupComplianceResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } +// Super class for all compatibility check faults. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCompatibilityCheckFault struct { PbmFault - Hub PbmPlacementHub `xml:"hub"` + // Placement Hub + Hub PbmPlacementHub `xml:"hub" json:"hub"` } func init() { @@ -706,43 +1263,124 @@ func init() { types.Add("pbm:PbmCompatibilityCheckFaultFault", reflect.TypeOf((*PbmCompatibilityCheckFaultFault)(nil)).Elem()) } +// Additional information on the effects of backend resources and +// operations on the storage object. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmComplianceOperationalStatus struct { types.DynamicData - Healthy *bool `xml:"healthy"` - OperationETA *time.Time `xml:"operationETA"` - OperationProgress int64 `xml:"operationProgress,omitempty"` - Transitional *bool `xml:"transitional"` + // Whether the object is currently affected by the failure of backend + // storage resources. + // + // Optional property. + Healthy *bool `xml:"healthy" json:"healthy,omitempty"` + // Estimated completion time of a backend operation affecting the object. + // + // If set, then "transitional" will be true. + // Optional property. + OperationETA *time.Time `xml:"operationETA" json:"operationETA,omitempty"` + // Percent progress of a backend operation affecting the object. + // + // If set, then "transitional" will be true. + // Optional property. + OperationProgress int64 `xml:"operationProgress,omitempty" json:"operationProgress,omitempty"` + // Whether an object is undergoing a backend operation that may affect + // its performance. + // + // This may be a rebalancing the resources of a healthy + // object or recovery tasks for an unhealthy object. + // Optional property. + Transitional *bool `xml:"transitional" json:"transitional,omitempty"` } func init() { types.Add("pbm:PbmComplianceOperationalStatus", reflect.TypeOf((*PbmComplianceOperationalStatus)(nil)).Elem()) } +// The `PbmCompliancePolicyStatus` data object provides information +// when compliance checking produces non-compliant results. +// +// See +// `PbmComplianceResult*.*PbmComplianceResult.violatedPolicies`. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmCompliancePolicyStatus struct { types.DynamicData - ExpectedValue PbmCapabilityInstance `xml:"expectedValue"` - CurrentValue *PbmCapabilityInstance `xml:"currentValue,omitempty"` + // Expected storage capability values of profile policies defined + // by a storage provider. + ExpectedValue PbmCapabilityInstance `xml:"expectedValue" json:"expectedValue"` + // Current storage requirement values of the profile policies + // specified for the virtual machine or virtual disk. + CurrentValue *PbmCapabilityInstance `xml:"currentValue,omitempty" json:"currentValue,omitempty"` } func init() { types.Add("pbm:PbmCompliancePolicyStatus", reflect.TypeOf((*PbmCompliancePolicyStatus)(nil)).Elem()) } +// The `PbmComplianceResult` data object describes the results of profile compliance +// checking for a virtual machine or virtual disk. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmComplianceResult struct { types.DynamicData - CheckTime time.Time `xml:"checkTime"` - Entity PbmServerObjectRef `xml:"entity"` - Profile *PbmProfileId `xml:"profile,omitempty"` - ComplianceTaskStatus string `xml:"complianceTaskStatus,omitempty"` - ComplianceStatus string `xml:"complianceStatus"` - Mismatch bool `xml:"mismatch"` - ViolatedPolicies []PbmCompliancePolicyStatus `xml:"violatedPolicies,omitempty"` - ErrorCause []types.LocalizedMethodFault `xml:"errorCause,omitempty"` - OperationalStatus *PbmComplianceOperationalStatus `xml:"operationalStatus,omitempty"` - Info *PbmExtendedElementDescription `xml:"info,omitempty"` + // Time when the compliance was checked. + CheckTime time.Time `xml:"checkTime" json:"checkTime"` + // Virtual machine or virtual disk for which compliance was checked. + Entity PbmServerObjectRef `xml:"entity" json:"entity"` + // Requirement profile with which the compliance was checked. + Profile *PbmProfileId `xml:"profile,omitempty" json:"profile,omitempty"` + // Status of the current running compliance operation. + // + // If there is no + // compliance check operation triggered, this indicates the last compliance + // task status. complianceTaskStatus is a string value that + // corresponds to one of the + // `PbmComplianceResultComplianceTaskStatus_enum` values. + ComplianceTaskStatus string `xml:"complianceTaskStatus,omitempty" json:"complianceTaskStatus,omitempty"` + // Status of the compliance operation. + // + // complianceStatus is a + // string value that corresponds to one of the + // `PbmComplianceStatus_enum` values. + // + // When you perform compliance checking on an entity whose associated profile + // contains more than one subprofile ( + // `PbmCapabilityProfile` . + // `PbmCapabilityProfile.constraints`), a compliant + // result for any one of the subprofiles will produce a compliant result + // for the operation. + ComplianceStatus string `xml:"complianceStatus" json:"complianceStatus"` + // Deprecated as of vSphere 2016, use + // `PbmComplianceStatus_enum` to + // know if a mismatch has occurred. If + // `PbmComplianceResult.complianceStatus` value + // is outOfDate, mismatch has occurred. + // + // Set to true if there is a profile version mismatch between the Storage + // Profile Server and the storage provider. + // + // If you receive a result that + // indicates a mismatch, you must use the vSphere API to update the profile + // associated with the virtual machine or virtual disk. + Mismatch bool `xml:"mismatch" json:"mismatch"` + // Values for capabilities that are known to be non-compliant with the specified constraints. + ViolatedPolicies []PbmCompliancePolicyStatus `xml:"violatedPolicies,omitempty" json:"violatedPolicies,omitempty"` + // This property is set if the compliance task fails with errors. + // + // There can be + // more than one error since a policy containing multiple blobs can return + // multiple failures, one for each blob. + ErrorCause []types.LocalizedMethodFault `xml:"errorCause,omitempty" json:"errorCause,omitempty"` + // Additional information on the effects of backend resources and + // operations on the storage object. + OperationalStatus *PbmComplianceOperationalStatus `xml:"operationalStatus,omitempty" json:"operationalStatus,omitempty"` + // Informational localized messages provided by the VASA provider in + // addition to the violatedPolicy. + Info *PbmExtendedElementDescription `xml:"info,omitempty" json:"info,omitempty"` } func init() { @@ -755,9 +1393,11 @@ func init() { types.Add("pbm:PbmCreate", reflect.TypeOf((*PbmCreate)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmCreate`. type PbmCreateRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - CreateSpec PbmCapabilityProfileCreateSpec `xml:"createSpec"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Capability-based profile specification. + CreateSpec PbmCapabilityProfileCreateSpec `xml:"createSpec" json:"createSpec"` } func init() { @@ -765,48 +1405,87 @@ func init() { } type PbmCreateResponse struct { - Returnval PbmProfileId `xml:"returnval"` + Returnval PbmProfileId `xml:"returnval" json:"returnval"` } +// DataServiceToProfilesMap maps the data service policy to the parent storage policies +// if referred. +// +// This is returned from the API call +// `ProfileManager#queryParentStoragePolicies(ProfileId[])` +// +// This structure may be used only with operations rendered under `/pbm`. type PbmDataServiceToPoliciesMap struct { types.DynamicData - DataServicePolicy PbmProfileId `xml:"dataServicePolicy"` - ParentStoragePolicies []PbmProfileId `xml:"parentStoragePolicies,omitempty"` - Fault *types.LocalizedMethodFault `xml:"fault,omitempty"` + // Denotes a Data Service Policy Id. + DataServicePolicy PbmProfileId `xml:"dataServicePolicy" json:"dataServicePolicy"` + // Storage Policies that refer to the Data Service Policy given by + // `PbmDataServiceToPoliciesMap.dataServicePolicy`. + ParentStoragePolicies []PbmProfileId `xml:"parentStoragePolicies,omitempty" json:"parentStoragePolicies,omitempty"` + // The fault is set in case of error conditions and this property will + // have the reason. + Fault *types.LocalizedMethodFault `xml:"fault,omitempty" json:"fault,omitempty"` } func init() { types.Add("pbm:PbmDataServiceToPoliciesMap", reflect.TypeOf((*PbmDataServiceToPoliciesMap)(nil)).Elem()) } +// Space stats for datastore +// +// This structure may be used only with operations rendered under `/pbm`. type PbmDatastoreSpaceStatistics struct { types.DynamicData - ProfileId string `xml:"profileId,omitempty"` - PhysicalTotalInMB int64 `xml:"physicalTotalInMB"` - PhysicalFreeInMB int64 `xml:"physicalFreeInMB"` - PhysicalUsedInMB int64 `xml:"physicalUsedInMB"` - LogicalLimitInMB int64 `xml:"logicalLimitInMB,omitempty"` - LogicalFreeInMB int64 `xml:"logicalFreeInMB"` - LogicalUsedInMB int64 `xml:"logicalUsedInMB"` + // Capability profile id. + // + // It is null when the statistics are for the entire + // datastore. + ProfileId string `xml:"profileId,omitempty" json:"profileId,omitempty"` + // Total physical space in MB. + PhysicalTotalInMB int64 `xml:"physicalTotalInMB" json:"physicalTotalInMB"` + // Total physical free space in MB. + PhysicalFreeInMB int64 `xml:"physicalFreeInMB" json:"physicalFreeInMB"` + // Used physical storage space in MB. + PhysicalUsedInMB int64 `xml:"physicalUsedInMB" json:"physicalUsedInMB"` + // Logical space limit set by the storage admin in MB. + // + // Omitted if there is no Logical space limit. + LogicalLimitInMB int64 `xml:"logicalLimitInMB,omitempty" json:"logicalLimitInMB,omitempty"` + // Free logical storage space in MB. + LogicalFreeInMB int64 `xml:"logicalFreeInMB" json:"logicalFreeInMB"` + // Used logical storage space in MB. + LogicalUsedInMB int64 `xml:"logicalUsedInMB" json:"logicalUsedInMB"` } func init() { types.Add("pbm:PbmDatastoreSpaceStatistics", reflect.TypeOf((*PbmDatastoreSpaceStatistics)(nil)).Elem()) } +// Not supported in this release. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmDefaultCapabilityProfile struct { PbmCapabilityProfile - VvolType []string `xml:"vvolType"` - ContainerId string `xml:"containerId"` + // Not supported in this release. + VvolType []string `xml:"vvolType" json:"vvolType"` + // Not supported in this release. + ContainerId string `xml:"containerId" json:"containerId"` } func init() { types.Add("pbm:PbmDefaultCapabilityProfile", reflect.TypeOf((*PbmDefaultCapabilityProfile)(nil)).Elem()) } +// Warning fault used to indicate that the vendor specific datastore matches the tag in the +// requirements profile that does not have a vendor specific rule set. +// +// In such case, +// an empty blob is sent to the vendor specific datastore and the default profile would apply. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmDefaultProfileAppliesFault struct { PbmCompatibilityCheckFault } @@ -821,11 +1500,20 @@ func init() { types.Add("pbm:PbmDefaultProfileAppliesFaultFault", reflect.TypeOf((*PbmDefaultProfileAppliesFaultFault)(nil)).Elem()) } +// Data structure that stores the default profile for datastores. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmDefaultProfileInfo struct { types.DynamicData - Datastores []PbmPlacementHub `xml:"datastores"` - DefaultProfile BasePbmProfile `xml:"defaultProfile,omitempty,typeattr"` + // Datastores + Datastores []PbmPlacementHub `xml:"datastores" json:"datastores"` + // Default requirements profile. + // + // It is set to null if the datastores are not associated with any default profile. + DefaultProfile BasePbmProfile `xml:"defaultProfile,omitempty,typeattr" json:"defaultProfile,omitempty"` + // NoPermission fault if default profile is not permitted. + MethodFault *types.LocalizedMethodFault `xml:"methodFault,omitempty" json:"methodFault,omitempty"` } func init() { @@ -838,9 +1526,11 @@ func init() { types.Add("pbm:PbmDelete", reflect.TypeOf((*PbmDelete)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmDelete`. type PbmDeleteRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - ProfileId []PbmProfileId `xml:"profileId"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Array of profile identifiers. + ProfileId []PbmProfileId `xml:"profileId" json:"profileId"` } func init() { @@ -848,13 +1538,18 @@ func init() { } type PbmDeleteResponse struct { - Returnval []PbmProfileOperationOutcome `xml:"returnval,omitempty"` + Returnval []PbmProfileOperationOutcome `xml:"returnval,omitempty" json:"returnval,omitempty"` } +// A DuplicateName exception is thrown because a name already exists +// in the same name space. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmDuplicateName struct { PbmFault - Name string `xml:"name"` + // The name that is already bound in the name space. + Name string `xml:"name" json:"name"` } func init() { @@ -870,17 +1565,38 @@ func init() { type PbmExtendedElementDescription struct { types.DynamicData - Label string `xml:"label"` - Summary string `xml:"summary"` - Key string `xml:"key"` - MessageCatalogKeyPrefix string `xml:"messageCatalogKeyPrefix"` - MessageArg []types.KeyAnyValue `xml:"messageArg,omitempty"` + // Display label. + Label string `xml:"label" json:"label"` + // Summary description. + Summary string `xml:"summary" json:"summary"` + // Enumeration or literal ID being described. + Key string `xml:"key" json:"key"` + // Key to the localized message string in the catalog. + // + // If the localized string contains parameters, values to the + // parameters will be provided in #messageArg. + // E.g: If the message in the catalog is + // "IP address is {address}", value for "address" + // will be provided by #messageArg. + // Both summary and label in ElementDescription will have a corresponding + // entry in the message catalog with the keys + // .summary and .label + // respectively. + // ElementDescription.summary and ElementDescription.label will contain + // the strings in server locale. + MessageCatalogKeyPrefix string `xml:"messageCatalogKeyPrefix" json:"messageCatalogKeyPrefix"` + // Provides named arguments that can be used to localize the + // message in the catalog. + MessageArg []types.KeyAnyValue `xml:"messageArg,omitempty" json:"messageArg,omitempty"` } func init() { types.Add("pbm:PbmExtendedElementDescription", reflect.TypeOf((*PbmExtendedElementDescription)(nil)).Elem()) } +// The super class for all pbm faults. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmFault struct { types.MethodFault } @@ -895,6 +1611,10 @@ func init() { types.Add("pbm:PbmFaultFault", reflect.TypeOf((*PbmFaultFault)(nil)).Elem()) } +// Thrown when login fails due to token not provided or token could not be +// validated. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmFaultInvalidLogin struct { PbmFault } @@ -909,17 +1629,51 @@ func init() { types.Add("pbm:PbmFaultInvalidLoginFault", reflect.TypeOf((*PbmFaultInvalidLoginFault)(nil)).Elem()) } +// Thrown when an operation is denied because of a privilege +// not held on a storage profile. +// +// This structure may be used only with operations rendered under `/pbm`. +type PbmFaultNoPermission struct { + types.SecurityError + + // List of profile ids and missing privileges for each profile + MissingPrivileges []PbmFaultNoPermissionEntityPrivileges `xml:"missingPrivileges,omitempty" json:"missingPrivileges,omitempty"` +} + +func init() { + types.Add("pbm:PbmFaultNoPermission", reflect.TypeOf((*PbmFaultNoPermission)(nil)).Elem()) +} + type PbmFaultNoPermissionEntityPrivileges struct { types.DynamicData - ProfileId *PbmProfileId `xml:"profileId,omitempty"` - PrivilegeIds []string `xml:"privilegeIds,omitempty"` + ProfileId *PbmProfileId `xml:"profileId,omitempty" json:"profileId,omitempty"` + PrivilegeIds []string `xml:"privilegeIds,omitempty" json:"privilegeIds,omitempty"` } func init() { types.Add("pbm:PbmFaultNoPermissionEntityPrivileges", reflect.TypeOf((*PbmFaultNoPermissionEntityPrivileges)(nil)).Elem()) } +type PbmFaultNoPermissionFault PbmFaultNoPermission + +func init() { + types.Add("pbm:PbmFaultNoPermissionFault", reflect.TypeOf((*PbmFaultNoPermissionFault)(nil)).Elem()) +} + +// A NotFound error occurs when a referenced component of a managed +// object cannot be found. +// +// The referenced component can be a data +// object type (such as a role or permission) or a primitive +// (such as a string). +// +// For example, if the missing referenced component is a data object, such as +// VirtualSwitch, the NotFound error is +// thrown. The NotFound error is also thrown if the data object is found, but the referenced name +// (for example, "vswitch0") is not. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmFaultNotFound struct { PbmFault } @@ -954,10 +1708,19 @@ func init() { types.Add("pbm:PbmFetchCapabilityMetadata", reflect.TypeOf((*PbmFetchCapabilityMetadata)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmFetchCapabilityMetadata`. type PbmFetchCapabilityMetadataRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - ResourceType *PbmProfileResourceType `xml:"resourceType,omitempty"` - VendorUuid string `xml:"vendorUuid,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Type of profile resource. The Server supports the "STORAGE" resource + // type only. If not specified, this method will return capability metadata for the storage + // resources. Any other resourceType is considered invalid. + ResourceType *PbmProfileResourceType `xml:"resourceType,omitempty" json:"resourceType,omitempty"` + // Unique identifier for the vendor/owner of capability + // metadata. The specified vendor ID must match + // `PbmCapabilitySchemaVendorInfo*.*PbmCapabilitySchemaVendorInfo.vendorUuid`. + // If omitted, the Server searchs all capability metadata registered with the system. If a + // vendorUuid unknown to the Server is specified, empty results will be returned. + VendorUuid string `xml:"vendorUuid,omitempty" json:"vendorUuid,omitempty"` } func init() { @@ -965,7 +1728,7 @@ func init() { } type PbmFetchCapabilityMetadataResponse struct { - Returnval []PbmCapabilityMetadataPerCategory `xml:"returnval,omitempty"` + Returnval []PbmCapabilityMetadataPerCategory `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmFetchCapabilitySchema PbmFetchCapabilitySchemaRequestType @@ -974,10 +1737,20 @@ func init() { types.Add("pbm:PbmFetchCapabilitySchema", reflect.TypeOf((*PbmFetchCapabilitySchema)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmFetchCapabilitySchema`. type PbmFetchCapabilitySchemaRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - VendorUuid string `xml:"vendorUuid,omitempty"` - LineOfService []string `xml:"lineOfService,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Unique identifier for the vendor/owner of capability metadata. + // If omitted, the server searchs all capability metadata registered + // with the system. The specified vendor ID must match + // `PbmCapabilitySchemaVendorInfo*.*PbmCapabilitySchemaVendorInfo.vendorUuid`. + VendorUuid string `xml:"vendorUuid,omitempty" json:"vendorUuid,omitempty"` + // Optional line of service that must match `PbmLineOfServiceInfoLineOfServiceEnum_enum`. + // If specified, the capability schema objects + // are returned for the given lineOfServices. If null, then all + // capability schema objects that may or may not have data service capabilities + // are returned. + LineOfService []string `xml:"lineOfService,omitempty" json:"lineOfService,omitempty"` } func init() { @@ -985,7 +1758,7 @@ func init() { } type PbmFetchCapabilitySchemaResponse struct { - Returnval []PbmCapabilitySchema `xml:"returnval,omitempty"` + Returnval []PbmCapabilitySchema `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmFetchComplianceResult PbmFetchComplianceResultRequestType @@ -994,10 +1767,24 @@ func init() { types.Add("pbm:PbmFetchComplianceResult", reflect.TypeOf((*PbmFetchComplianceResult)(nil)).Elem()) } +// The parameters of `PbmComplianceManager.PbmFetchComplianceResult`. type PbmFetchComplianceResultRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Entities []PbmServerObjectRef `xml:"entities"` - Profile *PbmProfileId `xml:"profile,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // One or more references to storage entities. + // A maximum of 1000 virtual machines and/or virtual disks can be specified + // in a call. The results of calling the fetchComplianceResult API with + // more than a 1000 entities is undefined. + // - If the list of entities also contains datastores, the Server + // will ignore the datastores. + // - If the list contains valid and invalid entities, the Server ignores + // the invalid entities and returns results for the valid entities. + // Invalid entities are entities that are not in the vCenter inventory. + // - If the list contains only datastores, the method throws + // an InvalidArgument fault. + Entities []PbmServerObjectRef `xml:"entities" json:"entities"` + // Not used. if specified, the Server ignores the value. + // The Server uses the profiles associated with the specified entities. + Profile *PbmProfileId `xml:"profile,omitempty" json:"profile,omitempty"` } func init() { @@ -1005,14 +1792,22 @@ func init() { } type PbmFetchComplianceResultResponse struct { - Returnval []PbmComplianceResult `xml:"returnval,omitempty"` + Returnval []PbmComplianceResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } +// The `PbmFetchEntityHealthStatusSpec` data object contains +// the arguments required for +// `PbmComplianceManager.PbmFetchEntityHealthStatusExt`. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmFetchEntityHealthStatusSpec struct { types.DynamicData - ObjectRef PbmServerObjectRef `xml:"objectRef"` - BackingId string `xml:"backingId,omitempty"` + // `PbmServerObjectRef` for which the healthStatus is required + ObjectRef PbmServerObjectRef `xml:"objectRef" json:"objectRef"` + // BackingId for the ServerObjectRef + // BackingId is mandatory for FCD on vSAN + BackingId string `xml:"backingId,omitempty" json:"backingId,omitempty"` } func init() { @@ -1026,7 +1821,7 @@ func init() { } type PbmFetchResourceTypeRequestType struct { - This types.ManagedObjectReference `xml:"_this"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` } func init() { @@ -1034,7 +1829,7 @@ func init() { } type PbmFetchResourceTypeResponse struct { - Returnval []PbmProfileResourceType `xml:"returnval,omitempty"` + Returnval []PbmProfileResourceType `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmFetchRollupComplianceResult PbmFetchRollupComplianceResultRequestType @@ -1043,9 +1838,14 @@ func init() { types.Add("pbm:PbmFetchRollupComplianceResult", reflect.TypeOf((*PbmFetchRollupComplianceResult)(nil)).Elem()) } +// The parameters of `PbmComplianceManager.PbmFetchRollupComplianceResult`. type PbmFetchRollupComplianceResultRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Entity []PbmServerObjectRef `xml:"entity"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // One or more virtual machines. + // A maximum of 1000 virtual machines can be specified + // in a call. The results of calling the fetchRollupComplianceResult API with + // more than a 1000 entity objects is undefined. + Entity []PbmServerObjectRef `xml:"entity" json:"entity"` } func init() { @@ -1053,7 +1853,7 @@ func init() { } type PbmFetchRollupComplianceResultResponse struct { - Returnval []PbmRollupComplianceResult `xml:"returnval,omitempty"` + Returnval []PbmRollupComplianceResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmFetchVendorInfo PbmFetchVendorInfoRequestType @@ -1062,9 +1862,13 @@ func init() { types.Add("pbm:PbmFetchVendorInfo", reflect.TypeOf((*PbmFetchVendorInfo)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmFetchVendorInfo`. type PbmFetchVendorInfoRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - ResourceType *PbmProfileResourceType `xml:"resourceType,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Specifies the resource type. The Server supports the STORAGE resource + // type only. If not specified, server defaults to STORAGE resource type. Any other + // resourceType is considered invalid. + ResourceType *PbmProfileResourceType `xml:"resourceType,omitempty" json:"resourceType,omitempty"` } func init() { @@ -1072,7 +1876,7 @@ func init() { } type PbmFetchVendorInfoResponse struct { - Returnval []PbmCapabilityVendorResourceTypeInfo `xml:"returnval,omitempty"` + Returnval []PbmCapabilityVendorResourceTypeInfo `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmFindApplicableDefaultProfile PbmFindApplicableDefaultProfileRequestType @@ -1081,9 +1885,12 @@ func init() { types.Add("pbm:PbmFindApplicableDefaultProfile", reflect.TypeOf((*PbmFindApplicableDefaultProfile)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmFindApplicableDefaultProfile`. type PbmFindApplicableDefaultProfileRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Datastores []PbmPlacementHub `xml:"datastores"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Datastores for which the default profile is found out. Note that + // the datastore pods/clusters are not supported. + Datastores []PbmPlacementHub `xml:"datastores" json:"datastores"` } func init() { @@ -1091,9 +1898,13 @@ func init() { } type PbmFindApplicableDefaultProfileResponse struct { - Returnval []BasePbmProfile `xml:"returnval,omitempty,typeattr"` + Returnval []BasePbmProfile `xml:"returnval,omitempty,typeattr" json:"returnval,omitempty"` } +// Warning fault used to indicate that the vendor specific datastore matches the tag in the +// requirements profile but doesnt match the vendor specific rule set in the requirements profile. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmIncompatibleVendorSpecificRuleSet struct { PbmCapabilityProfilePropertyMismatchFault } @@ -1108,10 +1919,19 @@ func init() { types.Add("pbm:PbmIncompatibleVendorSpecificRuleSetFault", reflect.TypeOf((*PbmIncompatibleVendorSpecificRuleSetFault)(nil)).Elem()) } +// LegacyHubsNotSupported fault is thrown to indicate the legacy hubs that are not supported. +// +// For storage, legacy hubs or datastores are VMFS and NFS datastores. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmLegacyHubsNotSupported struct { PbmFault - Hubs []PbmPlacementHub `xml:"hubs"` + // Legacy hubs that are not supported. + // + // Only datastores will be populated in this fault. Datastore clusters + // are not allowed. + Hubs []PbmPlacementHub `xml:"hubs" json:"hubs"` } func init() { @@ -1124,12 +1944,21 @@ func init() { types.Add("pbm:PbmLegacyHubsNotSupportedFault", reflect.TypeOf((*PbmLegacyHubsNotSupportedFault)(nil)).Elem()) } +// Describes Line of Service of a capability provider. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmLineOfServiceInfo struct { types.DynamicData - LineOfService string `xml:"lineOfService"` - Name PbmExtendedElementDescription `xml:"name"` - Description *PbmExtendedElementDescription `xml:"description,omitempty"` + // `PbmLineOfServiceInfoLineOfServiceEnum_enum` - must be one of the values + // for enum `PbmLineOfServiceInfoLineOfServiceEnum_enum`. + LineOfService string `xml:"lineOfService" json:"lineOfService"` + // Name of the service - for informational + // purposes only. + Name PbmExtendedElementDescription `xml:"name" json:"name"` + // Description of the service - for informational + // purposes only. + Description *PbmExtendedElementDescription `xml:"description,omitempty" json:"description,omitempty"` } func init() { @@ -1139,18 +1968,22 @@ func init() { type PbmLoggingConfiguration struct { types.DynamicData - Component string `xml:"component"` - LogLevel string `xml:"logLevel"` + Component string `xml:"component" json:"component"` + LogLevel string `xml:"logLevel" json:"logLevel"` } func init() { types.Add("pbm:PbmLoggingConfiguration", reflect.TypeOf((*PbmLoggingConfiguration)(nil)).Elem()) } +// NonExistentHubs is thrown to indicate that some non existent datastores are used. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmNonExistentHubs struct { PbmFault - Hubs []PbmPlacementHub `xml:"hubs"` + // Legacy hubs that do not exist. + Hubs []PbmPlacementHub `xml:"hubs" json:"hubs"` } func init() { @@ -1163,72 +1996,140 @@ func init() { types.Add("pbm:PbmNonExistentHubsFault", reflect.TypeOf((*PbmNonExistentHubsFault)(nil)).Elem()) } +// Describes the data services provided by the storage arrays. +// +// In addition to storing bits, some VASA providers may also want to separate +// their capabilities into lines of service to let vSphere manage finer grain +// policies. For example an array may support replication natively, and may +// want vSphere policies to be defined for the replication aspect separately +// and compose them with persistence related policies. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPersistenceBasedDataServiceInfo struct { PbmLineOfServiceInfo - CompatiblePersistenceSchemaNamespace []string `xml:"compatiblePersistenceSchemaNamespace,omitempty"` + // This property should be set with compatible schema namespaces exposed by + // the vendor provider. + // + // If not specified, vSphere assumes all Data Service + // provider schemas are compatible with all persistence provider namespaces + // advertised by the VASA provider. + CompatiblePersistenceSchemaNamespace []string `xml:"compatiblePersistenceSchemaNamespace,omitempty" json:"compatiblePersistenceSchemaNamespace,omitempty"` } func init() { types.Add("pbm:PbmPersistenceBasedDataServiceInfo", reflect.TypeOf((*PbmPersistenceBasedDataServiceInfo)(nil)).Elem()) } +// Requirement type containing capability constraints +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPlacementCapabilityConstraintsRequirement struct { PbmPlacementRequirement - Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr"` + // Capability constraints + Constraints BasePbmCapabilityConstraints `xml:"constraints,typeattr" json:"constraints"` } func init() { types.Add("pbm:PbmPlacementCapabilityConstraintsRequirement", reflect.TypeOf((*PbmPlacementCapabilityConstraintsRequirement)(nil)).Elem()) } +// A Requirement for a particular `PbmCapabilityProfile`. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPlacementCapabilityProfileRequirement struct { PbmPlacementRequirement - ProfileId PbmProfileId `xml:"profileId"` + // Reference to the capability profile being used as a requirement + ProfileId PbmProfileId `xml:"profileId" json:"profileId"` } func init() { types.Add("pbm:PbmPlacementCapabilityProfileRequirement", reflect.TypeOf((*PbmPlacementCapabilityProfileRequirement)(nil)).Elem()) } +// The `PbmPlacementCompatibilityResult` data object +// contains the compatibility result of a placement request. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPlacementCompatibilityResult struct { types.DynamicData - Hub PbmPlacementHub `xml:"hub"` - MatchingResources []BasePbmPlacementMatchingResources `xml:"matchingResources,omitempty,typeattr"` - HowMany int64 `xml:"howMany,omitempty"` - Utilization []PbmPlacementResourceUtilization `xml:"utilization,omitempty"` - Warning []types.LocalizedMethodFault `xml:"warning,omitempty"` - Error []types.LocalizedMethodFault `xml:"error,omitempty"` + // The Datastore or StoragePod under consideration + // as a location for virtual machine files. + Hub PbmPlacementHub `xml:"hub" json:"hub"` + // Resources that match the policy. + // + // If populated, signifies that there are + // specific resources that match the policy for `PbmPlacementCompatibilityResult.hub`. If null, + // signifies that all resources (for example, hosts connected to the + // datastore or storage pod) are compatible. + MatchingResources []BasePbmPlacementMatchingResources `xml:"matchingResources,omitempty,typeattr" json:"matchingResources,omitempty"` + // How many objects of the kind requested can be provisioned on this + // `PbmPlacementCompatibilityResult.hub`. + HowMany int64 `xml:"howMany,omitempty" json:"howMany,omitempty"` + // This field is not populated if there is no size in the query, i.e. + // + // if the request carries only policy and no size requirements, this + // will not be populated. + Utilization []PbmPlacementResourceUtilization `xml:"utilization,omitempty" json:"utilization,omitempty"` + // Array of faults that describe issues that may affect profile compatibility. + // + // Users should consider these issues before using this Datastore + // or StoragePod and a connected Hosts. + Warning []types.LocalizedMethodFault `xml:"warning,omitempty" json:"warning,omitempty"` + // Array of faults that prevent this datastore or storage pod from being compatible with the + // specified profile, including if no host connected to this `PbmPlacementCompatibilityResult.hub` is compatible. + Error []types.LocalizedMethodFault `xml:"error,omitempty" json:"error,omitempty"` } func init() { types.Add("pbm:PbmPlacementCompatibilityResult", reflect.TypeOf((*PbmPlacementCompatibilityResult)(nil)).Elem()) } +// A `PbmPlacementHub` data object identifies a storage location +// where virtual machine files can be placed. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPlacementHub struct { types.DynamicData - HubType string `xml:"hubType"` - HubId string `xml:"hubId"` + // Type of the hub. + // + // Currently ManagedObject is the only supported type. + HubType string `xml:"hubType" json:"hubType"` + // Hub identifier; a ManagedObjectReference to a datastore or a storage pod. + HubId string `xml:"hubId" json:"hubId"` } func init() { types.Add("pbm:PbmPlacementHub", reflect.TypeOf((*PbmPlacementHub)(nil)).Elem()) } +// Describes the collection of replication related resources that satisfy a +// policy, for a specific datastore. +// +// This class is returned only when the policy contains replication capabilities. +// For a storage pod, only those replication groups that are common across +// all datastores in the storage pod are considered compatible. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPlacementMatchingReplicationResources struct { PbmPlacementMatchingResources - ReplicationGroup []types.ReplicationGroupId `xml:"replicationGroup,omitempty"` + // Replication groups that match the policy. + ReplicationGroup []types.ReplicationGroupId `xml:"replicationGroup,omitempty" json:"replicationGroup,omitempty"` } func init() { types.Add("pbm:PbmPlacementMatchingReplicationResources", reflect.TypeOf((*PbmPlacementMatchingReplicationResources)(nil)).Elem()) } +// Describes the collection of resources (for example, hosts) that satisfy a +// policy, for a specific datastore. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPlacementMatchingResources struct { types.DynamicData } @@ -1237,6 +2138,9 @@ func init() { types.Add("pbm:PbmPlacementMatchingResources", reflect.TypeOf((*PbmPlacementMatchingResources)(nil)).Elem()) } +// Defines a constraint for placing objects onto `PbmPlacementHub`s. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPlacementRequirement struct { types.DynamicData } @@ -1245,82 +2149,156 @@ func init() { types.Add("pbm:PbmPlacementRequirement", reflect.TypeOf((*PbmPlacementRequirement)(nil)).Elem()) } +// Describes the resource utilization metrics of a datastore. +// +// These results are not to be treated as a guaranteed availability, +// they are useful to estimate the effects of a change of policy +// or the effects of a provisioning action. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPlacementResourceUtilization struct { types.DynamicData - Name PbmExtendedElementDescription `xml:"name"` - Description PbmExtendedElementDescription `xml:"description"` - AvailableBefore int64 `xml:"availableBefore,omitempty"` - AvailableAfter int64 `xml:"availableAfter,omitempty"` - Total int64 `xml:"total,omitempty"` + // Name of the resource. + Name PbmExtendedElementDescription `xml:"name" json:"name"` + // Description of the resource. + Description PbmExtendedElementDescription `xml:"description" json:"description"` + // Currently available (i.e. + // + // before the provisioning step). + AvailableBefore int64 `xml:"availableBefore,omitempty" json:"availableBefore,omitempty"` + // Available after the provisioning step. + AvailableAfter int64 `xml:"availableAfter,omitempty" json:"availableAfter,omitempty"` + // Total resource availability + Total int64 `xml:"total,omitempty" json:"total,omitempty"` } func init() { types.Add("pbm:PbmPlacementResourceUtilization", reflect.TypeOf((*PbmPlacementResourceUtilization)(nil)).Elem()) } +// The `PbmProfile` data object is the base object +// for storage capability profiles. +// +// This object defines metadata +// for the profile. The derived capability profile represents the +// user's intent for selection and configuration of storage resources +// and/or services that support deployment of virtual machines +// and virtual disks. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmProfile struct { types.DynamicData - ProfileId PbmProfileId `xml:"profileId"` - Name string `xml:"name"` - Description string `xml:"description,omitempty"` - CreationTime time.Time `xml:"creationTime"` - CreatedBy string `xml:"createdBy"` - LastUpdatedTime time.Time `xml:"lastUpdatedTime"` - LastUpdatedBy string `xml:"lastUpdatedBy"` + // Unique identifier for the profile. + ProfileId PbmProfileId `xml:"profileId" json:"profileId"` + Name string `xml:"name" json:"name"` + // Profile description. + Description string `xml:"description,omitempty" json:"description,omitempty"` + // Time stamp of profile creation. + CreationTime time.Time `xml:"creationTime" json:"creationTime"` + // User name of the profile creator. + // + // Set during creation time. + CreatedBy string `xml:"createdBy" json:"createdBy"` + // Time stamp of latest modification to the profile. + LastUpdatedTime time.Time `xml:"lastUpdatedTime" json:"lastUpdatedTime"` + // Name of the user performing the latest modification of the profile. + LastUpdatedBy string `xml:"lastUpdatedBy" json:"lastUpdatedBy"` } func init() { types.Add("pbm:PbmProfile", reflect.TypeOf((*PbmProfile)(nil)).Elem()) } +// Profile unique identifier. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmProfileId struct { types.DynamicData - UniqueId string `xml:"uniqueId"` + // Unique identifier of the profile. + UniqueId string `xml:"uniqueId" json:"uniqueId"` } func init() { types.Add("pbm:PbmProfileId", reflect.TypeOf((*PbmProfileId)(nil)).Elem()) } +// The `PbmProfileOperationOutcome` data object describes the result +// of a `PbmProfileProfileManager` operation. +// +// If there was an +// error during the operation, the object identifies the fault. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmProfileOperationOutcome struct { types.DynamicData - ProfileId PbmProfileId `xml:"profileId"` - Fault *types.LocalizedMethodFault `xml:"fault,omitempty"` + // Identifies the profile specified for the operation. + ProfileId PbmProfileId `xml:"profileId" json:"profileId"` + // One of the `PbmFault` objects. + Fault *types.LocalizedMethodFault `xml:"fault,omitempty" json:"fault,omitempty"` } func init() { types.Add("pbm:PbmProfileOperationOutcome", reflect.TypeOf((*PbmProfileOperationOutcome)(nil)).Elem()) } +// The `PbmProfileResourceType` data object defines the vSphere resource type +// that is supported for profile management. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmProfileResourceType struct { types.DynamicData - ResourceType string `xml:"resourceType"` + // Type of resource to which capability information applies. + // + // resourceType is a string value that corresponds to + // a `PbmProfileResourceTypeEnum_enum` enumeration value. + // Only the STORAGE resource type is supported. + ResourceType string `xml:"resourceType" json:"resourceType"` } func init() { types.Add("pbm:PbmProfileResourceType", reflect.TypeOf((*PbmProfileResourceType)(nil)).Elem()) } +// The `PbmProfileType` identifier is defined by storage providers +// to distinguish between different types of profiles plugged into the system. +// +// An example of a system supported profile type is "CapabilityBasedProfileType" +// which will be the type used for all capability-based profiles created by +// the system using capability metadata information published to the system. +// +// For internal use only. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmProfileType struct { types.DynamicData - UniqueId string `xml:"uniqueId"` + // Unique type identifier for this profile type. + // + // eg "CapabilityBased", or other. + UniqueId string `xml:"uniqueId" json:"uniqueId"` } func init() { types.Add("pbm:PbmProfileType", reflect.TypeOf((*PbmProfileType)(nil)).Elem()) } +// Fault used to indicate which property instance in requirements profile that does not +// match. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmPropertyMismatchFault struct { PbmCompatibilityCheckFault - CapabilityInstanceId PbmCapabilityMetadataUniqueId `xml:"capabilityInstanceId"` - RequirementPropertyInstance PbmCapabilityPropertyInstance `xml:"requirementPropertyInstance"` + // Id of the CapabilityInstance in requirements profile that + // does not match. + CapabilityInstanceId PbmCapabilityMetadataUniqueId `xml:"capabilityInstanceId" json:"capabilityInstanceId"` + // The property instance in requirement profile that does not match. + RequirementPropertyInstance PbmCapabilityPropertyInstance `xml:"requirementPropertyInstance" json:"requirementPropertyInstance"` } func init() { @@ -1339,9 +2317,11 @@ func init() { types.Add("pbm:PbmQueryAssociatedEntities", reflect.TypeOf((*PbmQueryAssociatedEntities)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmQueryAssociatedEntities`. type PbmQueryAssociatedEntitiesRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Profiles []PbmProfileId `xml:"profiles,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Storage policy array. + Profiles []PbmProfileId `xml:"profiles,omitempty" json:"profiles,omitempty"` } func init() { @@ -1349,7 +2329,7 @@ func init() { } type PbmQueryAssociatedEntitiesResponse struct { - Returnval []PbmQueryProfileResult `xml:"returnval,omitempty"` + Returnval []PbmQueryProfileResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQueryAssociatedEntity PbmQueryAssociatedEntityRequestType @@ -1358,10 +2338,16 @@ func init() { types.Add("pbm:PbmQueryAssociatedEntity", reflect.TypeOf((*PbmQueryAssociatedEntity)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmQueryAssociatedEntity`. type PbmQueryAssociatedEntityRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Profile PbmProfileId `xml:"profile"` - EntityType string `xml:"entityType,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Profile identifier. + Profile PbmProfileId `xml:"profile" json:"profile"` + // If specified, the method returns only those entities + // which match the type. The entityType string value must match + // one of the `PbmObjectType_enum` values. + // If not specified, the method returns all entities associated with the profile. + EntityType string `xml:"entityType,omitempty" json:"entityType,omitempty"` } func init() { @@ -1369,7 +2355,7 @@ func init() { } type PbmQueryAssociatedEntityResponse struct { - Returnval []PbmServerObjectRef `xml:"returnval,omitempty"` + Returnval []PbmServerObjectRef `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQueryAssociatedProfile PbmQueryAssociatedProfileRequestType @@ -1378,9 +2364,11 @@ func init() { types.Add("pbm:PbmQueryAssociatedProfile", reflect.TypeOf((*PbmQueryAssociatedProfile)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmQueryAssociatedProfile`. type PbmQueryAssociatedProfileRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Entity PbmServerObjectRef `xml:"entity"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Reference to a virtual machine, virtual disk, or datastore. + Entity PbmServerObjectRef `xml:"entity" json:"entity"` } func init() { @@ -1388,7 +2376,7 @@ func init() { } type PbmQueryAssociatedProfileResponse struct { - Returnval []PbmProfileId `xml:"returnval,omitempty"` + Returnval []PbmProfileId `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQueryAssociatedProfiles PbmQueryAssociatedProfilesRequestType @@ -1397,9 +2385,11 @@ func init() { types.Add("pbm:PbmQueryAssociatedProfiles", reflect.TypeOf((*PbmQueryAssociatedProfiles)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmQueryAssociatedProfiles`. type PbmQueryAssociatedProfilesRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Entities []PbmServerObjectRef `xml:"entities"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Array of server object references. + Entities []PbmServerObjectRef `xml:"entities" json:"entities"` } func init() { @@ -1407,7 +2397,7 @@ func init() { } type PbmQueryAssociatedProfilesResponse struct { - Returnval []PbmQueryProfileResult `xml:"returnval,omitempty"` + Returnval []PbmQueryProfileResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQueryByRollupComplianceStatus PbmQueryByRollupComplianceStatusRequestType @@ -1416,9 +2406,11 @@ func init() { types.Add("pbm:PbmQueryByRollupComplianceStatus", reflect.TypeOf((*PbmQueryByRollupComplianceStatus)(nil)).Elem()) } +// The parameters of `PbmComplianceManager.PbmQueryByRollupComplianceStatus`. type PbmQueryByRollupComplianceStatusRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Status string `xml:"status"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // `PbmComplianceStatus_enum` + Status string `xml:"status" json:"status"` } func init() { @@ -1426,7 +2418,7 @@ func init() { } type PbmQueryByRollupComplianceStatusResponse struct { - Returnval []PbmServerObjectRef `xml:"returnval,omitempty"` + Returnval []PbmServerObjectRef `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQueryDefaultRequirementProfile PbmQueryDefaultRequirementProfileRequestType @@ -1435,9 +2427,11 @@ func init() { types.Add("pbm:PbmQueryDefaultRequirementProfile", reflect.TypeOf((*PbmQueryDefaultRequirementProfile)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmQueryDefaultRequirementProfile`. type PbmQueryDefaultRequirementProfileRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Hub PbmPlacementHub `xml:"hub"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Placement hub (i.e. datastore). + Hub PbmPlacementHub `xml:"hub" json:"hub"` } func init() { @@ -1445,7 +2439,7 @@ func init() { } type PbmQueryDefaultRequirementProfileResponse struct { - Returnval *PbmProfileId `xml:"returnval,omitempty"` + Returnval *PbmProfileId `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQueryDefaultRequirementProfiles PbmQueryDefaultRequirementProfilesRequestType @@ -1454,9 +2448,13 @@ func init() { types.Add("pbm:PbmQueryDefaultRequirementProfiles", reflect.TypeOf((*PbmQueryDefaultRequirementProfiles)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmQueryDefaultRequirementProfiles`. type PbmQueryDefaultRequirementProfilesRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Datastores []PbmPlacementHub `xml:"datastores"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // The datastores for which the default profiles are requested. For + // legacy datastores we set + // `DefaultProfileInfo.defaultProfile` to `null`. + Datastores []PbmPlacementHub `xml:"datastores" json:"datastores"` } func init() { @@ -1464,7 +2462,7 @@ func init() { } type PbmQueryDefaultRequirementProfilesResponse struct { - Returnval []PbmDefaultProfileInfo `xml:"returnval"` + Returnval []PbmDefaultProfileInfo `xml:"returnval" json:"returnval"` } type PbmQueryMatchingHub PbmQueryMatchingHubRequestType @@ -1473,10 +2471,15 @@ func init() { types.Add("pbm:PbmQueryMatchingHub", reflect.TypeOf((*PbmQueryMatchingHub)(nil)).Elem()) } +// The parameters of `PbmPlacementSolver.PbmQueryMatchingHub`. type PbmQueryMatchingHubRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"` - Profile PbmProfileId `xml:"profile"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Candidate list of hubs, either datastores or storage pods or a + // mix. If this parameter is not specified, the Server uses all + // of the datastores and storage pods. + HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty" json:"hubsToSearch,omitempty"` + // Storage requirement profile. + Profile PbmProfileId `xml:"profile" json:"profile"` } func init() { @@ -1484,7 +2487,7 @@ func init() { } type PbmQueryMatchingHubResponse struct { - Returnval []PbmPlacementHub `xml:"returnval,omitempty"` + Returnval []PbmPlacementHub `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQueryMatchingHubWithSpec PbmQueryMatchingHubWithSpecRequestType @@ -1493,10 +2496,15 @@ func init() { types.Add("pbm:PbmQueryMatchingHubWithSpec", reflect.TypeOf((*PbmQueryMatchingHubWithSpec)(nil)).Elem()) } +// The parameters of `PbmPlacementSolver.PbmQueryMatchingHubWithSpec`. type PbmQueryMatchingHubWithSpecRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty"` - CreateSpec PbmCapabilityProfileCreateSpec `xml:"createSpec"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Candidate list of hubs, either datastores or storage + // pods or a mix. If this parameter is not specified, the Server uses + // all of the datastores and storage pods for placement compatibility checking. + HubsToSearch []PbmPlacementHub `xml:"hubsToSearch,omitempty" json:"hubsToSearch,omitempty"` + // Storage profile creation specification. + CreateSpec PbmCapabilityProfileCreateSpec `xml:"createSpec" json:"createSpec"` } func init() { @@ -1504,7 +2512,7 @@ func init() { } type PbmQueryMatchingHubWithSpecResponse struct { - Returnval []PbmPlacementHub `xml:"returnval,omitempty"` + Returnval []PbmPlacementHub `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQueryProfile PbmQueryProfileRequestType @@ -1513,10 +2521,16 @@ func init() { types.Add("pbm:PbmQueryProfile", reflect.TypeOf((*PbmQueryProfile)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmQueryProfile`. type PbmQueryProfileRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - ResourceType PbmProfileResourceType `xml:"resourceType"` - ProfileCategory string `xml:"profileCategory,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Type of resource. You can specify only STORAGE. + ResourceType PbmProfileResourceType `xml:"resourceType" json:"resourceType"` + // Profile category. The string value must correspond + // to one of the `PbmProfileCategoryEnum_enum` values. + // If you do not specify a profile category, the method returns profiles in all + // categories. + ProfileCategory string `xml:"profileCategory,omitempty" json:"profileCategory,omitempty"` } func init() { @@ -1524,27 +2538,48 @@ func init() { } type PbmQueryProfileResponse struct { - Returnval []PbmProfileId `xml:"returnval,omitempty"` + Returnval []PbmProfileId `xml:"returnval,omitempty" json:"returnval,omitempty"` } +// The `PbmQueryProfileResult` data object +// identifies a virtual machine, virtual disk, or datastore +// and it lists the identifier(s) for the associated profile(s). +// +// This structure may be used only with operations rendered under `/pbm`. type PbmQueryProfileResult struct { types.DynamicData - Object PbmServerObjectRef `xml:"object"` - ProfileId []PbmProfileId `xml:"profileId,omitempty"` - Fault *types.LocalizedMethodFault `xml:"fault,omitempty"` + // Reference to the virtual machine, virtual disk, or + // datastore on which the query was performed. + Object PbmServerObjectRef `xml:"object" json:"object"` + // Array of identifiers for profiles which are associated with object. + ProfileId []PbmProfileId `xml:"profileId,omitempty" json:"profileId,omitempty"` + // Fault associated with the query, if there is one. + Fault *types.LocalizedMethodFault `xml:"fault,omitempty" json:"fault,omitempty"` } func init() { types.Add("pbm:PbmQueryProfileResult", reflect.TypeOf((*PbmQueryProfileResult)(nil)).Elem()) } +// The `PbmQueryReplicationGroupResult` data object +// identifies a virtual machine, or a virtual disk and lists the identifier(s) for the associated +// replication group. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmQueryReplicationGroupResult struct { types.DynamicData - Object PbmServerObjectRef `xml:"object"` - ReplicationGroupId *types.ReplicationGroupId `xml:"replicationGroupId,omitempty"` - Fault *types.LocalizedMethodFault `xml:"fault,omitempty"` + // Reference to the virtual machine or virtual disk on which the query was performed. + // + // If the + // query was performed for a virtual machine and all it's disks, this will reference each disk + // and the virtual machine config individually. + Object PbmServerObjectRef `xml:"object" json:"object"` + // Replication group identifier which is associated with object. + ReplicationGroupId *types.ReplicationGroupId `xml:"replicationGroupId,omitempty" json:"replicationGroupId,omitempty"` + // Fault associated with the query, if there is one. + Fault *types.LocalizedMethodFault `xml:"fault,omitempty" json:"fault,omitempty"` } func init() { @@ -1557,9 +2592,15 @@ func init() { types.Add("pbm:PbmQueryReplicationGroups", reflect.TypeOf((*PbmQueryReplicationGroups)(nil)).Elem()) } +// The parameters of `PbmReplicationManager.PbmQueryReplicationGroups`. type PbmQueryReplicationGroupsRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Entities []PbmServerObjectRef `xml:"entities,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Array of server object references. Valid types are + // `virtualMachine`, + // `virtualMachineAndDisks`, + // `virtualDiskId`, + // `virtualDiskUUID` + Entities []PbmServerObjectRef `xml:"entities,omitempty" json:"entities,omitempty"` } func init() { @@ -1567,7 +2608,7 @@ func init() { } type PbmQueryReplicationGroupsResponse struct { - Returnval []PbmQueryReplicationGroupResult `xml:"returnval,omitempty"` + Returnval []PbmQueryReplicationGroupResult `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmQuerySpaceStatsForStorageContainer PbmQuerySpaceStatsForStorageContainerRequestType @@ -1576,10 +2617,15 @@ func init() { types.Add("pbm:PbmQuerySpaceStatsForStorageContainer", reflect.TypeOf((*PbmQuerySpaceStatsForStorageContainer)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmQuerySpaceStatsForStorageContainer`. type PbmQuerySpaceStatsForStorageContainerRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Datastore PbmServerObjectRef `xml:"datastore"` - CapabilityProfileId []PbmProfileId `xml:"capabilityProfileId,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Entity for which space statistics are being requested i.e datastore. + Datastore PbmServerObjectRef `xml:"datastore" json:"datastore"` + // \- capability profile Ids. + // If omitted, the statistics for the container + // as a whole would be returned. + CapabilityProfileId []PbmProfileId `xml:"capabilityProfileId,omitempty" json:"capabilityProfileId,omitempty"` } func init() { @@ -1587,7 +2633,7 @@ func init() { } type PbmQuerySpaceStatsForStorageContainerResponse struct { - Returnval []PbmDatastoreSpaceStatistics `xml:"returnval,omitempty"` + Returnval []PbmDatastoreSpaceStatistics `xml:"returnval,omitempty" json:"returnval,omitempty"` } type PbmResetDefaultRequirementProfile PbmResetDefaultRequirementProfileRequestType @@ -1596,9 +2642,11 @@ func init() { types.Add("pbm:PbmResetDefaultRequirementProfile", reflect.TypeOf((*PbmResetDefaultRequirementProfile)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmResetDefaultRequirementProfile`. type PbmResetDefaultRequirementProfileRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - Profile *PbmProfileId `xml:"profile,omitempty"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Profile to reset. + Profile *PbmProfileId `xml:"profile,omitempty" json:"profile,omitempty"` } func init() { @@ -1615,7 +2663,7 @@ func init() { } type PbmResetVSanDefaultProfileRequestType struct { - This types.ManagedObjectReference `xml:"_this"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` } func init() { @@ -1625,11 +2673,20 @@ func init() { type PbmResetVSanDefaultProfileResponse struct { } +// A ResourceInUse fault indicating that some error has occurred because a +// resource was in use. +// +// Information about the resource that is in use may +// be supplied. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmResourceInUse struct { PbmFault - Type string `xml:"type,omitempty"` - Name string `xml:"name,omitempty"` + // Type of resource that is in use. + Type string `xml:"type,omitempty" json:"type,omitempty"` + // Name of the instance of the resource that is in use. + Name string `xml:"name,omitempty" json:"name,omitempty"` } func init() { @@ -1648,9 +2705,11 @@ func init() { types.Add("pbm:PbmRetrieveContent", reflect.TypeOf((*PbmRetrieveContent)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmRetrieveContent`. type PbmRetrieveContentRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - ProfileIds []PbmProfileId `xml:"profileIds"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Array of storage profile identifiers. + ProfileIds []PbmProfileId `xml:"profileIds" json:"profileIds"` } func init() { @@ -1658,7 +2717,7 @@ func init() { } type PbmRetrieveContentResponse struct { - Returnval []BasePbmProfile `xml:"returnval,typeattr"` + Returnval []BasePbmProfile `xml:"returnval,typeattr" json:"returnval"` } type PbmRetrieveServiceContent PbmRetrieveServiceContentRequestType @@ -1668,7 +2727,7 @@ func init() { } type PbmRetrieveServiceContentRequestType struct { - This types.ManagedObjectReference `xml:"_this"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` } func init() { @@ -1676,47 +2735,154 @@ func init() { } type PbmRetrieveServiceContentResponse struct { - Returnval PbmServiceInstanceContent `xml:"returnval"` + Returnval PbmServiceInstanceContent `xml:"returnval" json:"returnval"` } +// The `PbmRollupComplianceResult` data object identifies the virtual machine +// for which rollup compliance was checked, and it contains the overall status +// and a list of compliance result objects. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmRollupComplianceResult struct { types.DynamicData - OldestCheckTime time.Time `xml:"oldestCheckTime"` - Entity PbmServerObjectRef `xml:"entity"` - OverallComplianceStatus string `xml:"overallComplianceStatus"` - OverallComplianceTaskStatus string `xml:"overallComplianceTaskStatus,omitempty"` - Result []PbmComplianceResult `xml:"result,omitempty"` - ErrorCause []types.LocalizedMethodFault `xml:"errorCause,omitempty"` - ProfileMismatch bool `xml:"profileMismatch"` + // Indicates the earliest time that compliance was checked for any + // of the entities in the rollup compliance check. + // + // The compliance + // check time for a single entity is represented in the + // `PbmComplianceResult*.*PbmComplianceResult.checkTime` + // property. If the `PbmComplianceResult.checkTime` + // property is unset for any of the objects in the results + // array, the oldestCheckTime property will be unset. + OldestCheckTime time.Time `xml:"oldestCheckTime" json:"oldestCheckTime"` + // Virtual machine for which the rollup compliance was checked. + Entity PbmServerObjectRef `xml:"entity" json:"entity"` + // Overall compliance status of the virtual machine and its virtual disks. + // + // overallComplianceStatus is a string value that + // corresponds to one of the + // `PbmComplianceResult*.*PbmComplianceResult.complianceStatus` + // values. + // + // The overall compliance status is determined by the following rules, applied in the order + // listed: + // - If all the entities are compliant, the overall status is + // compliant. + // - Else if any entity's status is outOfDate, the overall status is + // outOfDate. + // - Else if any entity's status is nonCompliant, the overall status is + // nonCompliant. + // - Else if any entity's status is unknown, the overall status is + // unknown. + // - Else if any entity's status is notApplicable, the overall status is + // notApplicable. + OverallComplianceStatus string `xml:"overallComplianceStatus" json:"overallComplianceStatus"` + // Overall compliance task status of the virtual machine and its virtual + // disks. + // + // overallComplianceTaskStatus is a string value that + // corresponds to one of the `PbmComplianceResult`. + // `PbmComplianceResult.complianceTaskStatus` values. + OverallComplianceTaskStatus string `xml:"overallComplianceTaskStatus,omitempty" json:"overallComplianceTaskStatus,omitempty"` + // Individual compliance results that make up the rollup. + Result []PbmComplianceResult `xml:"result,omitempty" json:"result,omitempty"` + // This property is set if the overall compliance task fails with some error. + // + // This + // property indicates the causes of error. If there are multiple failures, it stores + // these failure in this array. + ErrorCause []types.LocalizedMethodFault `xml:"errorCause,omitempty" json:"errorCause,omitempty"` + // Deprecated as of vSphere 2016, use + // `PbmRollupComplianceResult.overallComplianceStatus` + // to know if profile mismatch has occurred. If + // overallComplianceStatus value is outOfDate, it means + // profileMismatch has occurred. + // + // True if and only if `PbmComplianceResult`. + // + // `PbmComplianceResult.mismatch` is true for at least one + // entity in the rollup compliance check. + ProfileMismatch bool `xml:"profileMismatch" json:"profileMismatch"` } func init() { types.Add("pbm:PbmRollupComplianceResult", reflect.TypeOf((*PbmRollupComplianceResult)(nil)).Elem()) } +// The `PbmServerObjectRef` data object identifies +// a virtual machine, +// virtual disk attached to a virtual machine, +// a first class storage object +// or a datastore. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmServerObjectRef struct { types.DynamicData - ObjectType string `xml:"objectType"` - Key string `xml:"key"` - ServerUuid string `xml:"serverUuid,omitempty"` + // Type of vSphere Server object. + // + // The value of the objectType string + // corresponds to one of the `PbmObjectType_enum` + // enumerated type values. + ObjectType string `xml:"objectType" json:"objectType"` + // Unique identifier for the object. + // + // The value of key depends + // on the objectType. + // + // + // + // + // + // + // + // + // + //
`*PbmObjectType***`key value**
virtualMachine_virtual-machine-MOR_
virtualDiskId_virtual-disk-MOR_:_VirtualDisk.key_
datastore_datastore-MOR_
MOR = ManagedObjectReference
+ Key string `xml:"key" json:"key"` + // vCenter Server UUID; the ServiceContent.about.instanceUuid + // property in the vSphere API. + ServerUuid string `xml:"serverUuid,omitempty" json:"serverUuid,omitempty"` } func init() { types.Add("pbm:PbmServerObjectRef", reflect.TypeOf((*PbmServerObjectRef)(nil)).Elem()) } +// The `PbmServiceInstanceContent` data object defines properties for the +// `PbmServiceInstance` managed object. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmServiceInstanceContent struct { types.DynamicData - AboutInfo PbmAboutInfo `xml:"aboutInfo"` - SessionManager types.ManagedObjectReference `xml:"sessionManager"` - CapabilityMetadataManager types.ManagedObjectReference `xml:"capabilityMetadataManager"` - ProfileManager types.ManagedObjectReference `xml:"profileManager"` - ComplianceManager types.ManagedObjectReference `xml:"complianceManager"` - PlacementSolver types.ManagedObjectReference `xml:"placementSolver"` - ReplicationManager *types.ManagedObjectReference `xml:"replicationManager,omitempty"` + // Contains information that identifies the Storage Policy service. + AboutInfo PbmAboutInfo `xml:"aboutInfo" json:"aboutInfo"` + // For internal use. + // + // Refers instance of `PbmSessionManager`. + SessionManager types.ManagedObjectReference `xml:"sessionManager" json:"sessionManager"` + // For internal use. + // + // Refers instance of `PbmCapabilityMetadataManager`. + CapabilityMetadataManager types.ManagedObjectReference `xml:"capabilityMetadataManager" json:"capabilityMetadataManager"` + // Provides access to the Storage Policy ProfileManager. + // + // Refers instance of `PbmProfileProfileManager`. + ProfileManager types.ManagedObjectReference `xml:"profileManager" json:"profileManager"` + // Provides access to the Storage Policy ComplianceManager. + // + // Refers instance of `PbmComplianceManager`. + ComplianceManager types.ManagedObjectReference `xml:"complianceManager" json:"complianceManager"` + // Provides access to the Storage Policy PlacementSolver. + // + // Refers instance of `PbmPlacementSolver`. + PlacementSolver types.ManagedObjectReference `xml:"placementSolver" json:"placementSolver"` + // Provides access to the Storage Policy ReplicationManager. + // + // Refers instance of `PbmReplicationManager`. + ReplicationManager *types.ManagedObjectReference `xml:"replicationManager,omitempty" json:"replicationManager,omitempty"` } func init() { @@ -1729,10 +2895,13 @@ func init() { types.Add("pbm:PbmUpdate", reflect.TypeOf((*PbmUpdate)(nil)).Elem()) } +// The parameters of `PbmProfileProfileManager.PbmUpdate`. type PbmUpdateRequestType struct { - This types.ManagedObjectReference `xml:"_this"` - ProfileId PbmProfileId `xml:"profileId"` - UpdateSpec PbmCapabilityProfileUpdateSpec `xml:"updateSpec"` + This types.ManagedObjectReference `xml:"_this" json:"_this"` + // Profile identifier. + ProfileId PbmProfileId `xml:"profileId" json:"profileId"` + // Capability-based update specification. + UpdateSpec PbmCapabilityProfileUpdateSpec `xml:"updateSpec" json:"updateSpec"` } func init() { @@ -1742,6 +2911,10 @@ func init() { type PbmUpdateResponse struct { } +// Information about a supported data service provided using +// vSphere APIs for IO Filtering (VAIO) data service provider. +// +// This structure may be used only with operations rendered under `/pbm`. type PbmVaioDataServiceInfo struct { PbmLineOfServiceInfo } diff --git a/vendor/github.com/vmware/govmomi/property/collector.go b/vendor/github.com/vmware/govmomi/property/collector.go index 8798ceacbf1..16bf2226697 100644 --- a/vendor/github.com/vmware/govmomi/property/collector.go +++ b/vendor/github.com/vmware/govmomi/property/collector.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -31,7 +31,6 @@ import ( // // For more information, see: // http://pubs.vmware.com/vsphere-60/index.jsp?topic=%2Fcom.vmware.wssdk.apiref.doc%2Fvmodl.query.PropertyCollector.html -// type Collector struct { roundTripper soap.RoundTripper reference types.ManagedObjectReference diff --git a/vendor/github.com/vmware/govmomi/session/cache/session.go b/vendor/github.com/vmware/govmomi/session/cache/session.go new file mode 100644 index 00000000000..c6c3955c178 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/session/cache/session.go @@ -0,0 +1,365 @@ +/* +Copyright (c) 2020 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cache + +import ( + "context" + "crypto/sha1" + "encoding/json" + "fmt" + "net/url" + "os" + "os/user" + "path/filepath" + + "github.com/vmware/govmomi/session" + "github.com/vmware/govmomi/vapi/rest" + "github.com/vmware/govmomi/vim25" + "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" +) + +// Client interface to support client session caching +type Client interface { + json.Marshaler + json.Unmarshaler + + Valid() bool + Path() string +} + +// Session provides methods to cache authenticated vim25.Client and rest.Client sessions. +// Use of session cache avoids the expense of creating and deleting vSphere sessions. +// It also helps avoid the problem of "leaking sessions", as Session.Login will only +// create a new authenticated session if the cached session does not exist or is invalid. +// By default, username/password authentication is used to create new sessions. +// The Session.Login{SOAP,REST} fields can be set to use other methods, +// such as SAML token authentication (see govc session.login for example). +// +// When Reauth is set to true, Login skips loading file cache and performs username/password +// authentication, which is helpful in the case that the password in URL is different than +// previously cached session. Comparing to `Passthrough`, the file cache will be updated after +// authentication is done. +type Session struct { + URL *url.URL // URL of a vCenter or ESXi instance + DirSOAP string // DirSOAP cache directory. Defaults to "$HOME/.govmomi/sessions" + DirREST string // DirREST cache directory. Defaults to "$HOME/.govmomi/rest_sessions" + Insecure bool // Insecure param for soap.NewClient (tls.Config.InsecureSkipVerify) + Passthrough bool // Passthrough disables caching when set to true + Reauth bool // Reauth skips loading of cached sessions when set to true + + LoginSOAP func(context.Context, *vim25.Client) error // LoginSOAP defaults to session.Manager.Login() + LoginREST func(context.Context, *rest.Client) error // LoginREST defaults to rest.Client.Login() +} + +var ( + home = os.Getenv("GOVMOMI_HOME") +) + +func init() { + if home == "" { + dir, err := os.UserHomeDir() + if err != nil { + dir = os.Getenv("HOME") + } + home = filepath.Join(dir, ".govmomi") + } +} + +// Endpoint returns a copy of the Session.URL with Password, Query and Fragment removed. +func (s *Session) Endpoint() *url.URL { + if s.URL == nil { + return nil + } + p := &url.URL{ + Scheme: s.URL.Scheme, + Host: s.URL.Host, + Path: s.URL.Path, + } + if u := s.URL.User; u != nil { + p.User = url.User(u.Username()) // Remove password + } + return p +} + +// key is a digest of the URL scheme + username + host + Client.Path() +func (s *Session) key(path string) string { + p := s.Endpoint() + p.Path = path + + // Key session file off of full URI and insecure setting. + // Hash key to get a predictable, canonical format. + key := fmt.Sprintf("%s#insecure=%t", p.String(), s.Insecure) + return fmt.Sprintf("%040x", sha1.Sum([]byte(key))) +} + +func (s *Session) file(p string) string { + dir := "" + + switch p { + case rest.Path: + dir = s.DirREST + if dir == "" { + dir = filepath.Join(home, "rest_sessions") + } + default: + dir = s.DirSOAP + if dir == "" { + dir = filepath.Join(home, "sessions") + } + } + + return filepath.Join(dir, s.key(p)) +} + +// Save a Client in the file cache. +// Session will not be saved if Session.Passthrough is true. +func (s *Session) Save(c Client) error { + if s.Passthrough { + return nil + } + + p := s.file(c.Path()) + + err := os.MkdirAll(filepath.Dir(p), 0700) + if err != nil { + return err + } + + f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY, 0600) + if err != nil { + return err + } + + err = json.NewEncoder(f).Encode(c) + if err != nil { + _ = f.Close() + return err + } + + return f.Close() +} + +func (s *Session) get(c Client) (bool, error) { + f, err := os.Open(s.file(c.Path())) + if err != nil { + if os.IsNotExist(err) { + return false, nil + } + + return false, err + } + + dec := json.NewDecoder(f) + err = dec.Decode(c) + if err != nil { + _ = f.Close() + return false, err + } + + return c.Valid(), f.Close() +} + +func localTicket(ctx context.Context, m *session.Manager) (*url.Userinfo, error) { + name := os.Getenv("USER") + u, err := user.Current() + if err == nil { + name = u.Username + } + + ticket, err := m.AcquireLocalTicket(ctx, name) + if err != nil { + return nil, err + } + + password, err := os.ReadFile(ticket.PasswordFilePath) + if err != nil { + return nil, err + } + + return url.UserPassword(ticket.UserName, string(password)), nil +} + +func (s *Session) loginSOAP(ctx context.Context, c *vim25.Client) error { + m := session.NewManager(c) + u := s.URL.User + name := u.Username() + + if name == "" && !c.IsVC() { + // If no username is provided, try to acquire a local ticket. + // When invoked remotely, ESX returns an InvalidRequestFault. + // So, rather than return an error here, fallthrough to Login() with the original User to + // to avoid what would be a confusing error message. + luser, lerr := localTicket(ctx, m) + if lerr == nil { + // We are running directly on an ESX or Workstation host and can use the ticket with Login() + u = luser + name = u.Username() + } + } + if name == "" { + // ServiceContent does not require authentication + return nil + } + + return m.Login(ctx, u) +} + +func (s *Session) loginREST(ctx context.Context, c *rest.Client) error { + return c.Login(ctx, s.URL.User) +} + +func soapSessionValid(ctx context.Context, client *vim25.Client) (bool, error) { + m := session.NewManager(client) + u, err := m.UserSession(ctx) + if err != nil { + if soap.IsSoapFault(err) { + fault := soap.ToSoapFault(err).VimFault() + // If the PropertyCollector is not found, the saved session for this URL is not valid + if _, ok := fault.(types.ManagedObjectNotFound); ok { + return false, nil + } + } + + return false, err + } + + return u != nil, nil +} + +func restSessionValid(ctx context.Context, client *rest.Client) (bool, error) { + s, err := client.Session(ctx) + if err != nil { + return false, err + } + return s != nil, nil +} + +// Load a Client from the file cache. +// Returns false if no cache exists or is invalid. +// An error is returned if the file cannot be opened or is not json encoded. +// After loading the Client from the file: +// Returns true if the session is still valid, false otherwise indicating the client requires authentication. +// An error is returned if the session ID cannot be validated. +// Returns false if Session.Passthrough is true. +func (s *Session) Load(ctx context.Context, c Client, config func(*soap.Client) error) (bool, error) { + if s.Passthrough || s.Reauth { + return false, nil + } + + ok, err := s.get(c) + if err != nil { + return false, err + + } + if !ok { + return false, nil + } + + switch client := c.(type) { + case *vim25.Client: + if config != nil { + if err := config(client.Client); err != nil { + return false, err + } + } + return soapSessionValid(ctx, client) + case *rest.Client: + if config != nil { + if err := config(client.Client); err != nil { + return false, err + } + } + return restSessionValid(ctx, client) + default: + panic(fmt.Sprintf("unsupported client type=%T", client)) + } +} + +// Login returns a cached session via Load() if valid. +// Otherwise, creates a new authenticated session and saves to the cache. +// The config func can be used to apply soap.Client configuration, such as TLS settings. +// When Session.Passthrough is true, Login will always create a new session. +func (s *Session) Login(ctx context.Context, c Client, config func(*soap.Client) error) error { + ok, err := s.Load(ctx, c, config) + if err != nil { + return err + } + if ok { + return nil + } + + sc := soap.NewClient(s.URL, s.Insecure) + + if config != nil { + err = config(sc) + if err != nil { + return err + } + } + + switch client := c.(type) { + case *vim25.Client: + vc, err := vim25.NewClient(ctx, sc) + if err != nil { + return err + } + + login := s.loginSOAP + if s.LoginSOAP != nil { + login = s.LoginSOAP + } + if err = login(ctx, vc); err != nil { + return err + } + + *client = *vc + c = client + case *rest.Client: + client.Client = sc.NewServiceClient(rest.Path, "") + + login := s.loginREST + if s.LoginREST != nil { + login = s.LoginREST + } + if err = login(ctx, client); err != nil { + return err + } + + c = client + default: + panic(fmt.Sprintf("unsupported client type=%T", client)) + } + + return s.Save(c) +} + +// Login calls the Logout method for the given Client if Session.Passthrough is true. +// Otherwise returns nil. +func (s *Session) Logout(ctx context.Context, c Client) error { + if s.Passthrough { + switch client := c.(type) { + case *vim25.Client: + return session.NewManager(client).Logout(ctx) + case *rest.Client: + return client.Logout(ctx) + default: + panic(fmt.Sprintf("unsupported client type=%T", client)) + } + } + return nil +} diff --git a/vendor/github.com/vmware/govmomi/session/manager.go b/vendor/github.com/vmware/govmomi/session/manager.go index 8689acd504a..e2d70a2f60a 100644 --- a/vendor/github.com/vmware/govmomi/session/manager.go +++ b/vendor/github.com/vmware/govmomi/session/manager.go @@ -18,7 +18,6 @@ package session import ( "context" - "io/ioutil" "net/url" "os" "strings" @@ -47,7 +46,7 @@ func Secret(value string) (string, error) { if len(value) == 0 { return value, nil } - contents, err := ioutil.ReadFile(value) + contents, err := os.ReadFile(value) if err != nil { if os.IsPermission(err) { return "", err diff --git a/vendor/github.com/vmware/govmomi/simulator/cluster_compute_resource.go b/vendor/github.com/vmware/govmomi/simulator/cluster_compute_resource.go index 12f910b2e4c..cf992853698 100644 --- a/vendor/github.com/vmware/govmomi/simulator/cluster_compute_resource.go +++ b/vendor/github.com/vmware/govmomi/simulator/cluster_compute_resource.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -66,10 +66,11 @@ func (add *addHost) Run(task *Task) (types.AnyType, types.BaseMethodFault) { } host := NewHostSystem(template) - host.configure(spec, add.req.AsConnected) + host.configure(task.ctx, spec, add.req.AsConnected) task.ctx.Map.PutEntity(cr, task.ctx.Map.NewEntity(host)) host.Summary.Host = &host.Self + host.Config.Host = host.Self cr.Host = append(cr.Host, host.Reference()) addComputeResource(cr.Summary.GetComputeResourceSummary(), host) @@ -85,6 +86,24 @@ func (c *ClusterComputeResource) AddHostTask(ctx *Context, add *types.AddHost_Ta } } +func (c *ClusterComputeResource) update(cfg *types.ClusterConfigInfoEx, cspec *types.ClusterConfigSpecEx) types.BaseMethodFault { + if cspec.DasConfig != nil { + if val := cspec.DasConfig.Enabled; val != nil { + cfg.DasConfig.Enabled = val + } + if val := cspec.DasConfig.AdmissionControlEnabled; val != nil { + cfg.DasConfig.AdmissionControlEnabled = val + } + } + if cspec.DrsConfig != nil { + if val := cspec.DrsConfig.Enabled; val != nil { + cfg.DrsConfig.Enabled = val + } + } + + return nil +} + func (c *ClusterComputeResource) updateRules(cfg *types.ClusterConfigInfoEx, cspec *types.ClusterConfigSpecEx) types.BaseMethodFault { for _, spec := range cspec.RulesSpec { var i int @@ -327,6 +346,7 @@ func (c *ClusterComputeResource) ReconfigureComputeResourceTask(ctx *Context, re } updates := []func(*types.ClusterConfigInfoEx, *types.ClusterConfigSpecEx) types.BaseMethodFault{ + c.update, c.updateRules, c.updateGroups, c.updateOverridesDAS, @@ -350,6 +370,40 @@ func (c *ClusterComputeResource) ReconfigureComputeResourceTask(ctx *Context, re } } +func (c *ClusterComputeResource) MoveIntoTask(ctx *Context, req *types.MoveInto_Task) soap.HasFault { + task := CreateTask(c, "moveInto", func(*Task) (types.AnyType, types.BaseMethodFault) { + for _, ref := range req.Host { + host := ctx.Map.Get(ref).(*HostSystem) + + if *host.Parent == c.Self { + return nil, new(types.DuplicateName) // host already in this cluster + } + + switch parent := ctx.Map.Get(*host.Parent).(type) { + case *ClusterComputeResource: + if !host.Runtime.InMaintenanceMode { + return nil, new(types.InvalidState) + } + + RemoveReference(&parent.Host, ref) + case *mo.ComputeResource: + ctx.Map.Remove(ctx, parent.Self) + } + + c.Host = append(c.Host, ref) + host.Parent = &c.Self + } + + return nil, nil + }) + + return &methods.MoveInto_TaskBody{ + Res: &types.MoveInto_TaskResponse{ + Returnval: task.Run(ctx), + }, + } +} + func (c *ClusterComputeResource) PlaceVm(ctx *Context, req *types.PlaceVm) soap.HasFault { body := new(methods.PlaceVmBody) diff --git a/vendor/github.com/vmware/govmomi/simulator/container.go b/vendor/github.com/vmware/govmomi/simulator/container.go index 96f4fd10cc0..f39ef997029 100644 --- a/vendor/github.com/vmware/govmomi/simulator/container.go +++ b/vendor/github.com/vmware/govmomi/simulator/container.go @@ -18,29 +18,32 @@ package simulator import ( "archive/tar" + "bufio" "bytes" - "encoding/hex" + "context" "encoding/json" + "errors" "fmt" "io" "log" - "net/http" + "net" "os" "os/exec" "path" "regexp" - "strconv" "strings" + "sync" "time" - - "github.com/google/uuid" - - "github.com/vmware/govmomi/vim25/methods" - "github.com/vmware/govmomi/vim25/types" ) var ( - shell = "/bin/sh" + shell = "/bin/sh" + eventWatch eventWatcher +) + +const ( + deleteWithContainer = "lifecycle=container" + createdByVcsim = "createdBy=vcsim" ) func init() { @@ -49,10 +52,26 @@ func init() { } } +type eventWatcher struct { + sync.Mutex + + stdin io.WriteCloser + stdout io.ReadCloser + process *os.Process + + // watches is a map of container IDs to container objects + watches map[string]*container +} + // container provides methods to manage a container within a simulator VM lifecycle. type container struct { + sync.Mutex + id string name string + + cancelWatch context.CancelFunc + changes chan struct{} } type networkSettings struct { @@ -62,524 +81,753 @@ type networkSettings struct { MacAddress string } -// inspect applies container network settings to vm.Guest properties. -func (c *container) inspect(vm *VirtualMachine) error { - if c.id == "" { - return nil +type containerDetails struct { + State struct { + Running bool + Paused bool } + NetworkSettings struct { + networkSettings + Networks map[string]networkSettings + } +} - var objects []struct { - State struct { - Running bool - Paused bool - } - NetworkSettings struct { - networkSettings - Networks map[string]networkSettings - } +type unknownContainer error +type uninitializedContainer error + +var sanitizeNameRx = regexp.MustCompile(`[\(\)\s]`) + +func sanitizeName(name string) string { + return sanitizeNameRx.ReplaceAllString(name, "-") +} + +func constructContainerName(name, uid string) string { + return fmt.Sprintf("vcsim-%s-%s", sanitizeName(name), uid) +} + +func constructVolumeName(containerName, uid, volumeName string) string { + return constructContainerName(containerName, uid) + "--" + sanitizeName(volumeName) +} + +func extractNameAndUid(containerName string) (name string, uid string, err error) { + parts := strings.Split(strings.TrimPrefix(containerName, "vcsim-"), "-") + if len(parts) != 2 { + err = fmt.Errorf("container name does not match expected vcsim-name-uid format: %s", containerName) + return } - cmd := exec.Command("docker", "inspect", c.id) - out, err := cmd.Output() + return parts[0], parts[1], nil +} + +func prefixToMask(prefix int) string { + mask := net.CIDRMask(prefix, 32) + return fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]) +} + +type tarEntry struct { + header *tar.Header + content []byte +} + +// From https://docs.docker.com/engine/reference/commandline/cp/ : +// > It is not possible to copy certain system files such as resources under /proc, /sys, /dev, tmpfs, and mounts created by the user in the container. +// > However, you can still copy such files by manually running tar in docker exec. +func copyToGuest(id string, dest string, length int64, reader io.Reader) error { + cmd := exec.Command("docker", "exec", "-i", id, "tar", "Cxf", path.Dir(dest), "-") + cmd.Stderr = os.Stderr + stdin, err := cmd.StdinPipe() if err != nil { return err } - if err = json.NewDecoder(bytes.NewReader(out)).Decode(&objects); err != nil { + + err = cmd.Start() + if err != nil { return err } - vm.Config.Annotation = strings.Join(cmd.Args, " ") - vm.logPrintf("%s: %s", vm.Config.Annotation, string(out)) - - for _, o := range objects { - s := o.NetworkSettings.networkSettings + tw := tar.NewWriter(stdin) + _ = tw.WriteHeader(&tar.Header{ + Name: path.Base(dest), + Size: length, + Mode: 0444, + ModTime: time.Now(), + }) - for _, n := range o.NetworkSettings.Networks { - s = n - break - } + _, err = io.Copy(tw, reader) - if o.State.Paused { - vm.Runtime.PowerState = types.VirtualMachinePowerStateSuspended - } else if o.State.Running { - vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOn - } else { - vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff - } + twErr := tw.Close() + stdinErr := stdin.Close() - vm.Guest.IpAddress = s.IPAddress - vm.Summary.Guest.IpAddress = s.IPAddress - - if len(vm.Guest.Net) != 0 { - net := &vm.Guest.Net[0] - net.IpAddress = []string{s.IPAddress} - net.MacAddress = s.MacAddress - net.IpConfig = &types.NetIpConfigInfo{ - IpAddress: []types.NetIpConfigInfoIpAddress{{ - IpAddress: s.IPAddress, - PrefixLength: int32(s.IPPrefixLen), - State: string(types.NetIpConfigInfoIpAddressStatusPreferred), - }}, - } - } + waitErr := cmd.Wait() - for _, d := range vm.Config.Hardware.Device { - if eth, ok := d.(types.BaseVirtualEthernetCard); ok { - eth.GetVirtualEthernetCard().MacAddress = s.MacAddress - break - } - } + if err != nil || twErr != nil || stdinErr != nil || waitErr != nil { + return fmt.Errorf("copy: {%s}, tw: {%s}, stdin: {%s}, wait: {%s}", err, twErr, stdinErr, waitErr) } return nil } -func (c *container) prepareGuestOperation( - vm *VirtualMachine, - auth types.BaseGuestAuthentication) types.BaseMethodFault { - - if c.id == "" { - return new(types.GuestOperationsUnavailable) +func copyFromGuest(id string, src string, sink func(int64, io.Reader) error) error { + cmd := exec.Command("docker", "exec", id, "tar", "Ccf", path.Dir(src), "-", path.Base(src)) + cmd.Stderr = os.Stderr + stdout, err := cmd.StdoutPipe() + if err != nil { + return err } - if vm.Runtime.PowerState != types.VirtualMachinePowerStatePoweredOn { - return &types.InvalidPowerState{ - RequestedState: types.VirtualMachinePowerStatePoweredOn, - ExistingState: vm.Runtime.PowerState, - } + if err = cmd.Start(); err != nil { + return err } - switch creds := auth.(type) { - case *types.NamePasswordAuthentication: - if creds.Username == "" || creds.Password == "" { - return new(types.InvalidGuestLogin) - } - default: - return new(types.InvalidGuestLogin) + + tr := tar.NewReader(stdout) + header, err := tr.Next() + if err != nil { + return err } - return nil -} -var sanitizeNameRx = regexp.MustCompile(`[\(\)\s]`) + err = sink(header.Size, tr) + waitErr := cmd.Wait() -func sanitizeName(name string) string { - return sanitizeNameRx.ReplaceAllString(name, "-") + if err != nil || waitErr != nil { + return fmt.Errorf("err: {%s}, wait: {%s}", err, waitErr) + } + + return nil } -// createDMI writes BIOS UUID DMI files to a container volume -func (c *container) createDMI(vm *VirtualMachine, name string) error { +// createVolume creates a volume populated with the provided files +// If the header.Size is omitted or set to zero, then len(content+1) is used. +// Docker appears to treat this volume create command as idempotent so long as it's identical +// to an existing volume, so we can use this both for creating volumes inline in container create (for labelling) and +// for population after. +// returns: +// +// uid - string +// err - error or nil +func createVolume(volumeName string, labels []string, files []tarEntry) (string, error) { image := os.Getenv("VCSIM_BUSYBOX") if image == "" { image = "busybox" } - cmd := exec.Command("docker", "run", "--rm", "-i", "-v", name+":"+"/"+name, image, "tar", "-C", "/"+name, "-xf", "-") + name := sanitizeName(volumeName) + uid := "" + + // label the volume if specified - this requires the volume be created before use + if len(labels) > 0 { + run := []string{"volume", "create"} + for i := range labels { + run = append(run, "--label", labels[i]) + } + run = append(run, name) + cmd := exec.Command("docker", run...) + out, err := cmd.Output() + if err != nil { + return "", err + } + uid = strings.TrimSpace(string(out)) + + if name == "" { + name = uid + } + } + + run := []string{"run", "--rm", "-i"} + run = append(run, "-v", name+":/"+name) + run = append(run, image, "tar", "-C", "/"+name, "-xf", "-") + cmd := exec.Command("docker", run...) stdin, err := cmd.StdinPipe() if err != nil { - return err + return uid, err } err = cmd.Start() if err != nil { - return err + return uid, err } tw := tar.NewWriter(stdin) - dmi := []struct { - name string - val func(uuid.UUID) string - }{ - {"product_uuid", productUUID}, - {"product_serial", productSerial}, - } + for _, file := range files { + header := file.header - for _, file := range dmi { - val := file.val(vm.uid) - _ = tw.WriteHeader(&tar.Header{ - Name: file.name, - Size: int64(len(val) + 1), - Mode: 0444, - ModTime: time.Now(), - }) - _, _ = fmt.Fprintln(tw, val) + if header.Size == 0 && len(file.content) > 0 { + header.Size = int64(len(file.content)) + } + + if header.ModTime.IsZero() { + header.ModTime = time.Now() + } + + if header.Mode == 0 { + header.Mode = 0444 + } + + tarErr := tw.WriteHeader(header) + if tarErr == nil { + _, tarErr = tw.Write(file.content) + } } - _ = tw.Close() - _ = stdin.Close() + err = nil + twErr := tw.Close() + stdinErr := stdin.Close() + if twErr != nil || stdinErr != nil { + err = fmt.Errorf("tw: {%s}, stdin: {%s}", twErr, stdinErr) + } - if err := cmd.Wait(); err != nil { + if waitErr := cmd.Wait(); waitErr != nil { stderr := "" - if xerr, ok := err.(*exec.ExitError); ok { + if xerr, ok := waitErr.(*exec.ExitError); ok { stderr = string(xerr.Stderr) } - log.Printf("%s %s: %s %s", vm.Name, cmd.Args, err, stderr) - return err + log.Printf("%s %s: %s %s", name, cmd.Args, waitErr, stderr) + + err = fmt.Errorf("%s, wait: {%s}", err, waitErr) + return uid, err } - return nil + return uid, err } -var ( - toolsRunning = []types.PropertyChange{ - {Name: "guest.toolsStatus", Val: types.VirtualMachineToolsStatusToolsOk}, - {Name: "guest.toolsRunningStatus", Val: string(types.VirtualMachineToolsRunningStatusGuestToolsRunning)}, +func getBridge(bridgeName string) (string, error) { + // {"CreatedAt":"2023-07-11 19:22:25.45027052 +0000 UTC","Driver":"bridge","ID":"fe52c7502c5d","IPv6":"false","Internal":"false","Labels":"goodbye=,hello=","Name":"testnet","Scope":"local"} + // podman has distinctly different fields at v4.4.1 so commented out fields that don't match. We only actually care about ID + type bridgeNet struct { + // CreatedAt string + Driver string + ID string + // IPv6 string + // Internal string + // Labels string + Name string + // Scope string + } + + // if the underlay bridge already exists, return that + // we don't check for a specific label or similar so that it's possible to use a bridge created by other frameworks for composite testing + var bridge bridgeNet + cmd := exec.Command("docker", "network", "ls", "--format={{json .}}", "-f", fmt.Sprintf("name=%s$", bridgeName)) + out, err := cmd.Output() + if err != nil { + log.Printf("vcsim %s: %s, %s", cmd.Args, err, out) + return "", err } - toolsNotRunning = []types.PropertyChange{ - {Name: "guest.toolsStatus", Val: types.VirtualMachineToolsStatusToolsNotRunning}, - {Name: "guest.toolsRunningStatus", Val: string(types.VirtualMachineToolsRunningStatusGuestToolsNotRunning)}, + // unfortunately docker returns an empty string not an empty json doc and podman returns '[]' + // podman also returns an array of matches even when there's only one, so we normalize. + str := strings.TrimSpace(string(out)) + str = strings.TrimPrefix(str, "[") + str = strings.TrimSuffix(str, "]") + if len(str) == 0 { + return "", nil } -) -// start runs the container if specified by the RUN.container extraConfig property. -func (c *container) start(ctx *Context, vm *VirtualMachine) { - if c.id != "" { - start := "start" - if vm.Runtime.PowerState == types.VirtualMachinePowerStateSuspended { - start = "unpause" - } - cmd := exec.Command("docker", start, c.id) - err := cmd.Run() - if err != nil { - log.Printf("%s %s: %s", vm.Name, cmd.Args, err) - } else { - ctx.Map.Update(vm, toolsRunning) - } - return + err = json.Unmarshal([]byte(str), &bridge) + if err != nil { + log.Printf("vcsim %s: %s, %s", cmd.Args, err, str) + return "", err } - var args []string - var env []string + return bridge.ID, nil +} - for _, opt := range vm.Config.ExtraConfig { - val := opt.GetOptionValue() - if val.Key == "RUN.container" { - run := val.Value.(string) - err := json.Unmarshal([]byte(run), &args) - if err != nil { - args = []string{run} - } +// createBridge creates a bridge network if one does not already exist +// returns: +// +// uid - string +// err - error or nil +func createBridge(bridgeName string, labels ...string) (string, error) { - continue - } - if strings.HasPrefix(val.Key, "guestinfo.") { - key := strings.Replace(strings.ToUpper(val.Key), ".", "_", -1) - env = append(env, "--env", fmt.Sprintf("VMX_%s=%s", key, val.Value.(string))) - } + id, err := getBridge(bridgeName) + if err != nil { + return "", err } - if len(args) == 0 { - return + if id != "" { + return id, nil } - if len(env) != 0 { - // Configure env as the data access method for cloud-init-vmware-guestinfo - env = append(env, "--env", "VMX_GUESTINFO=true") + + run := []string{"network", "create", "--label", createdByVcsim} + for i := range labels { + run = append(run, "--label", labels[i]) } + run = append(run, bridgeName) - c.name = fmt.Sprintf("vcsim-%s-%s", sanitizeName(vm.Name), vm.uid) - run := append([]string{"docker", "run", "-d", "--name", c.name}, env...) + cmd := exec.Command("docker", run...) + out, err := cmd.Output() + if err != nil { + log.Printf("vcsim %s: %s: %s", cmd.Args, out, err) + return "", err + } - if err := c.createDMI(vm, c.name); err != nil { - return + // docker returns the ID regardless of whether you supply a name when creating the network, however + // podman returns the pretty name, so we have to normalize + id, err = getBridge(bridgeName) + if err != nil { + return "", err } - run = append(run, "-v", fmt.Sprintf("%s:%s:ro", c.name, "/sys/class/dmi/id")) - args = append(run, args...) - cmd := exec.Command(shell, "-c", strings.Join(args, " ")) + return id, nil +} + +// create +// - name - pretty name, eg. vm name +// - id - uuid or similar - this is merged into container name rather than dictating containerID +// - networks - set of bridges to connect the container to +// - volumes - colon separated tuple of volume name to mount path. Passed directly to docker via -v so mount options can be postfixed. +// - env - array of environment vairables in name=value form +// - optsAndImage - pass-though options and must include at least the container image to use, including tag if necessary +// - args - the command+args to pass to the container +func create(ctx *Context, name string, id string, networks []string, volumes []string, ports []string, env []string, image string, args []string) (*container, error) { + if len(image) == 0 { + return nil, errors.New("cannot create container backing without an image") + } + + var c container + c.name = constructContainerName(name, id) + c.changes = make(chan struct{}) + + for i := range volumes { + // we'll pre-create anonymous volumes, simply for labelling consistency + volName := strings.Split(volumes[i], ":") + createVolume(volName[0], []string{deleteWithContainer, "container=" + c.name}, nil) + } + + // assemble env + var dockerNet []string + var dockerVol []string + var dockerPort []string + var dockerEnv []string + + for i := range env { + dockerEnv = append(dockerEnv, "--env", env[i]) + } + + for i := range volumes { + dockerVol = append(dockerVol, "-v", volumes[i]) + } + + for i := range ports { + dockerPort = append(dockerPort, "-p", ports[i]) + } + + for i := range networks { + dockerNet = append(dockerNet, "--network", networks[i]) + } + + run := []string{"docker", "create", "--name", c.name} + run = append(run, dockerNet...) + run = append(run, dockerVol...) + run = append(run, dockerPort...) + run = append(run, dockerEnv...) + run = append(run, image) + run = append(run, args...) + + // this combines all the run options into a single string that's passed to /bin/bash -c as the single argument to force bash parsing. + // TODO: make this configurable behaviour so users also have the option of not escaping everything for bash + cmd := exec.Command(shell, "-c", strings.Join(run, " ")) out, err := cmd.Output() if err != nil { stderr := "" if xerr, ok := err.(*exec.ExitError); ok { stderr = string(xerr.Stderr) } - log.Printf("%s %s: %s %s", vm.Name, cmd.Args, err, stderr) - return + log.Printf("%s %s: %s %s", name, cmd.Args, err, stderr) + + return nil, err } - ctx.Map.Update(vm, toolsRunning) c.id = strings.TrimSpace(string(out)) - vm.logPrintf("%s %s: %s", cmd.Path, cmd.Args, c.id) - if err = c.inspect(vm); err != nil { - log.Printf("%s inspect %s: %s", vm.Name, c.id, err) - } - - // Start watching the container resource. - go c.watchContainer(vm) + return &c, nil } -// watchContainer monitors the underlying container and updates the VM -// properties based on the container status. This occurs until either -// the container or the VM is removed. -func (c *container) watchContainer(vm *VirtualMachine) { +// createVolume takes the specified files and writes them into a volume named for the container. +func (c *container) createVolume(name string, labels []string, files []tarEntry) (string, error) { + return createVolume(c.name+"--"+name, append(labels, "container="+c.name), files) +} - inspectInterval := time.Duration(5 * time.Second) - if d, err := time.ParseDuration(os.Getenv("VCSIM_INSPECT_INTERVAL")); err == nil { - inspectInterval = d +// inspect retrieves and parses container properties into directly usable struct +// returns: +// +// out - the stdout of the command +// detail - basic struct populated with container details +// err: +// * if c.id is empty, or docker returns "No such object", will return an uninitializedContainer error +// * err from either execution or parsing of json output +func (c *container) inspect() (out []byte, detail containerDetails, err error) { + c.Lock() + id := c.id + c.Unlock() + + if id == "" { + err = uninitializedContainer(errors.New("inspect of uninitialized container")) + return } - var ( - ctx = SpoofContext() - done = make(chan struct{}) - ticker = time.NewTicker(inspectInterval) - ) + var details []containerDetails - stopUpdatingVmFromContainer := func() { - ticker.Stop() - close(done) + cmd := exec.Command("docker", "inspect", c.id) + out, err = cmd.Output() + if eErr, ok := err.(*exec.ExitError); ok { + if strings.Contains(string(eErr.Stderr), "No such object") { + err = uninitializedContainer(errors.New("inspect of uninitialized container")) + } } - destroyVm := func() { - // If the container cannot be found then destroy this VM. - taskRef := vm.DestroyTask(ctx, &types.Destroy_Task{ - This: vm.Self, - }).(*methods.Destroy_TaskBody).Res.Returnval - task := ctx.Map.Get(taskRef).(*Task) + if err != nil { + return + } - // Wait for the task to complete and see if there is an error. - task.Wait() - if task.Info.Error != nil { - vm.logPrintf("failed to destroy vm: err=%v", *task.Info.Error) - } + if err = json.NewDecoder(bytes.NewReader(out)).Decode(&details); err != nil { + return } - updateVmFromContainer := func() { - // Exit the monitor loop if the VM was removed from the API side. - if c.id == "" { - stopUpdatingVmFromContainer() - return - } + if len(details) != 1 { + err = fmt.Errorf("multiple containers (%d) match ID: %s", len(details), c.id) + return + } - if err := c.inspect(vm); err != nil { - // If there is an error inspecting the container because it no - // longer exists, then destroy the VM as well. Please note the - // reason this logic does not invoke stopUpdatingVmFromContainer - // is because that will be handled the next time this function - // is entered and c.id is empty. - if err, ok := err.(*exec.ExitError); ok { - if strings.Contains(string(err.Stderr), "No such object") { - destroyVm() - } - } - } + detail = details[0] + return +} + +// start +// - if the container already exists, start it or unpause it. +func (c *container) start(ctx *Context) error { + c.Lock() + id := c.id + c.Unlock() + + if id == "" { + return uninitializedContainer(errors.New("start of uninitialized container")) } - // Update the VM from the container at regular intervals until the done - // channel is closed. - for { - select { - case <-ticker.C: - ctx.WithLock(vm, updateVmFromContainer) - case <-done: - return - } + start := "start" + _, detail, err := c.inspect() + if err != nil { + return err } -} -// stop the container (if any) for the given vm. -func (c *container) stop(ctx *Context, vm *VirtualMachine) { - if c.id == "" { - return + if detail.State.Paused { + start = "unpause" } - cmd := exec.Command("docker", "stop", c.id) - err := cmd.Run() + cmd := exec.Command("docker", start, c.id) + err = cmd.Run() if err != nil { - log.Printf("%s %s: %s", vm.Name, cmd.Args, err) - } else { - ctx.Map.Update(vm, toolsNotRunning) + log.Printf("%s %s: %s", c.name, cmd.Args, err) } + + return err } // pause the container (if any) for the given vm. -func (c *container) pause(ctx *Context, vm *VirtualMachine) { - if c.id == "" { - return +func (c *container) pause(ctx *Context) error { + c.Lock() + id := c.id + c.Unlock() + + if id == "" { + return uninitializedContainer(errors.New("pause of uninitialized container")) } cmd := exec.Command("docker", "pause", c.id) err := cmd.Run() if err != nil { - log.Printf("%s %s: %s", vm.Name, cmd.Args, err) - } else { - ctx.Map.Update(vm, toolsNotRunning) + log.Printf("%s %s: %s", c.name, cmd.Args, err) } + + return err } // restart the container (if any) for the given vm. -func (c *container) restart(ctx *Context, vm *VirtualMachine) { - if c.id == "" { - return +func (c *container) restart(ctx *Context) error { + c.Lock() + id := c.id + c.Unlock() + + if id == "" { + return uninitializedContainer(errors.New("restart of uninitialized container")) } cmd := exec.Command("docker", "restart", c.id) err := cmd.Run() if err != nil { - log.Printf("%s %s: %s", vm.Name, cmd.Args, err) - } else { - ctx.Map.Update(vm, toolsRunning) + log.Printf("%s %s: %s", c.name, cmd.Args, err) } + + return err } -// remove the container (if any) for the given vm. -func (c *container) remove(vm *VirtualMachine) { - if c.id == "" { - return - } +// stop the container (if any) for the given vm. +func (c *container) stop(ctx *Context) error { + c.Lock() + id := c.id + c.Unlock() - args := [][]string{ - {"rm", "-v", "-f", c.id}, - {"volume", "rm", "-f", c.name}, + if id == "" { + return uninitializedContainer(errors.New("stop of uninitialized container")) } - for i := range args { - cmd := exec.Command("docker", args[i]...) - err := cmd.Run() - if err != nil { - log.Printf("%s %s: %s", vm.Name, cmd.Args, err) - } + cmd := exec.Command("docker", "stop", c.id) + err := cmd.Run() + if err != nil { + log.Printf("%s %s: %s", c.name, cmd.Args, err) } - c.id = "" + return err } -func (c *container) exec(ctx *Context, vm *VirtualMachine, auth types.BaseGuestAuthentication, args []string) (string, types.BaseMethodFault) { - fault := vm.run.prepareGuestOperation(vm, auth) - if fault != nil { - return "", fault +// exec invokes the specified command, with executable being the first of the args, in the specified container +// returns +// +// string - combined stdout and stderr from command +// err +// * uninitializedContainer error - if c.id is empty +// * err from cmd execution +func (c *container) exec(ctx *Context, args []string) (string, error) { + c.Lock() + id := c.id + c.Unlock() + + if id == "" { + return "", uninitializedContainer(errors.New("exec into uninitialized container")) } - args = append([]string{"exec", vm.run.id}, args...) + args = append([]string{"exec", c.id}, args...) cmd := exec.Command("docker", args...) - res, err := cmd.CombinedOutput() if err != nil { - log.Printf("%s: %s (%s)", vm.Self, cmd.Args, string(res)) - return "", new(types.GuestOperationsFault) + log.Printf("%s: %s (%s)", c.name, cmd.Args, string(res)) + return "", err } return strings.TrimSpace(string(res)), nil } -// From https://docs.docker.com/engine/reference/commandline/cp/ : -// > It is not possible to copy certain system files such as resources under /proc, /sys, /dev, tmpfs, and mounts created by the user in the container. -// > However, you can still copy such files by manually running tar in docker exec. -func guestUpload(id string, file string, r *http.Request) error { - cmd := exec.Command("docker", "exec", "-i", id, "tar", "Cxf", path.Dir(file), "-") - cmd.Stderr = os.Stderr - stdin, err := cmd.StdinPipe() +// remove the container (if any) for the given vm. Considers removal of an uninitialized container success. +// Also removes volumes and networks that indicate they are lifecycle coupled with this container. +// returns: +// +// err - joined err from deletion of container and any volumes or networks that have coupled lifecycle +func (c *container) remove(ctx *Context) error { + c.Lock() + defer c.Unlock() + + if c.id == "" { + // consider absence success + return nil + } + + cmd := exec.Command("docker", "rm", "-v", "-f", c.id) + err := cmd.Run() if err != nil { + log.Printf("%s %s: %s", c.name, cmd.Args, err) return err } - if err = cmd.Start(); err != nil { - return err + + cmd = exec.Command("docker", "volume", "ls", "-q", "--filter", "label=container="+c.name, "--filter", "label="+deleteWithContainer) + volumesToReap, lsverr := cmd.Output() + if lsverr != nil { + log.Printf("%s %s: %s", c.name, cmd.Args, lsverr) } + log.Printf("%s volumes: %s", c.name, volumesToReap) - tw := tar.NewWriter(stdin) - _ = tw.WriteHeader(&tar.Header{ - Name: path.Base(file), - Size: r.ContentLength, - Mode: 0444, - ModTime: time.Now(), - }) + var rmverr error + if len(volumesToReap) > 0 { + run := []string{"volume", "rm", "-f"} + run = append(run, strings.Split(string(volumesToReap), "\n")...) + cmd = exec.Command("docker", run...) + out, rmverr := cmd.Output() + if rmverr != nil { + log.Printf("%s %s: %s, %s", c.name, cmd.Args, rmverr, out) + } + } + + cmd = exec.Command("docker", "network", "ls", "-q", "--filter", "label=container="+c.name, "--filter", "label="+deleteWithContainer) + networksToReap, lsnerr := cmd.Output() + if lsnerr != nil { + log.Printf("%s %s: %s", c.name, cmd.Args, lsnerr) + } - _, _ = io.Copy(tw, r.Body) + var rmnerr error + if len(networksToReap) > 0 { + run := []string{"network", "rm", "-f"} + run = append(run, strings.Split(string(volumesToReap), "\n")...) + cmd = exec.Command("docker", run...) + rmnerr = cmd.Run() + if rmnerr != nil { + log.Printf("%s %s: %s", c.name, cmd.Args, rmnerr) + } + } - _ = tw.Close() - _ = stdin.Close() - _ = r.Body.Close() + if err != nil || lsverr != nil || rmverr != nil || lsnerr != nil || rmnerr != nil { + return fmt.Errorf("err: {%s}, lsverr: {%s}, rmverr: {%s}, lsnerr:{%s}, rmerr: {%s}", err, lsverr, rmverr, lsnerr, rmnerr) + } - return cmd.Wait() + if c.cancelWatch != nil { + c.cancelWatch() + eventWatch.ignore(c) + } + c.id = "" + return nil } -func guestDownload(id string, file string, w http.ResponseWriter) error { - cmd := exec.Command("docker", "exec", id, "tar", "Ccf", path.Dir(file), "-", path.Base(file)) - cmd.Stderr = os.Stderr - stdout, err := cmd.StdoutPipe() - if err != nil { - return err +// updated is a simple trigger allowing a caller to indicate that something has likely changed about the container +// and interested parties should re-inspect as needed. +func (c *container) updated() { + consolidationWindow := 250 * time.Millisecond + if d, err := time.ParseDuration(os.Getenv("VCSIM_EVENT_CONSOLIDATION_WINDOW")); err == nil { + consolidationWindow = d } - if err = cmd.Start(); err != nil { - return err + + select { + case c.changes <- struct{}{}: + time.Sleep(consolidationWindow) + // as this is only a hint to avoid waiting for the full inspect interval, we don't care about accumulating + // multiple triggers. We do pause to allow large numbers of sequential updates to consolidate + default: } +} - tr := tar.NewReader(stdout) - header, err := tr.Next() - if err != nil { - return err +// watchContainer monitors the underlying container and updates +// properties based on the container status. This occurs until either +// the container or the VM is removed. +// returns: +// +// err - uninitializedContainer error - if c.id is empty +func (c *container) watchContainer(ctx context.Context, updateFn func(*containerDetails, *container) error) error { + c.Lock() + defer c.Unlock() + + if c.id == "" { + return uninitializedContainer(errors.New("Attempt to watch uninitialized container")) } - w.Header().Set("Content-Length", strconv.FormatInt(header.Size, 10)) - _, _ = io.Copy(w, tr) + eventWatch.watch(c) + + cancelCtx, cancelFunc := context.WithCancel(ctx) + c.cancelWatch = cancelFunc + + // Update the VM from the container at regular intervals until the done + // channel is closed. + go func() { + inspectInterval := 10 * time.Second + if d, err := time.ParseDuration(os.Getenv("VCSIM_INSPECT_INTERVAL")); err == nil { + inspectInterval = d + } + ticker := time.NewTicker(inspectInterval) + + update := func() { + _, details, err := c.inspect() + var rmErr error + var removing bool + if _, ok := err.(uninitializedContainer); ok { + removing = true + rmErr = c.remove(SpoofContext()) + } + + updateErr := updateFn(&details, c) + // if we don't succeed we want to re-try + if removing && rmErr == nil && updateErr == nil { + ticker.Stop() + return + } + if updateErr != nil { + log.Printf("vcsim container watch: %s %s", c.id, updateErr) + } + } + + for { + select { + case <-c.changes: + update() + case <-ticker.C: + update() + case <-cancelCtx.Done(): + return + } + } + }() - return cmd.Wait() + return nil } -const guestPrefix = "/guestFile/" +func (w *eventWatcher) watch(c *container) { + w.Lock() + defer w.Unlock() -// ServeGuest handles container guest file upload/download -func ServeGuest(w http.ResponseWriter, r *http.Request) { - // Real vCenter form: /guestFile?id=139&token=... - // vcsim form: /guestFile/tmp/foo/bar?id=ebc8837b8cb6&token=... + if w.watches == nil { + w.watches = make(map[string]*container) + } - id := r.URL.Query().Get("id") - file := strings.TrimPrefix(r.URL.Path, guestPrefix[:len(guestPrefix)-1]) - var err error + w.watches[c.id] = c - switch r.Method { - case http.MethodPut: - err = guestUpload(id, file, r) - case http.MethodGet: - err = guestDownload(id, file, w) - default: - w.WriteHeader(http.StatusMethodNotAllowed) - return + if w.stdin == nil { + cmd := exec.Command("docker", "events", "--format", "'{{.ID}}'", "--filter", "Type=container") + w.stdout, _ = cmd.StdoutPipe() + w.stdin, _ = cmd.StdinPipe() + err := cmd.Start() + if err != nil { + log.Printf("docker event watcher: %s %s", cmd.Args, err) + w.stdin = nil + w.stdout = nil + w.process = nil + + return + } + + w.process = cmd.Process + + go w.monitor() } +} - if err != nil { - log.Printf("%s %s: %s", r.Method, r.URL, err) - w.WriteHeader(http.StatusInternalServerError) +func (w *eventWatcher) ignore(c *container) { + w.Lock() + + delete(w.watches, c.id) + + if len(w.watches) == 0 && w.stdin != nil { + w.stop() } + + w.Unlock() } -// productSerial returns the uuid in /sys/class/dmi/id/product_serial format -func productSerial(id uuid.UUID) string { - var dst [len(id)*2 + len(id) - 1]byte - - j := 0 - for i := 0; i < len(id); i++ { - hex.Encode(dst[j:j+2], id[i:i+1]) - j += 3 - if j < len(dst) { - s := j - 1 - if s == len(dst)/2 { - dst[s] = '-' - } else { - dst[s] = ' ' - } - } +func (w *eventWatcher) monitor() { + w.Lock() + watches := len(w.watches) + w.Unlock() + + if watches == 0 { + return } - return fmt.Sprintf("VMware-%s", string(dst[:])) + scanner := bufio.NewScanner(w.stdout) + for scanner.Scan() { + id := strings.TrimSpace(scanner.Text()) + + w.Lock() + container := w.watches[id] + w.Unlock() + + if container != nil { + // this is called in a routine to allow an event consolidation window + go container.updated() + } + } } -// productUUID returns the uuid in /sys/class/dmi/id/product_uuid format -func productUUID(id uuid.UUID) string { - var dst [36]byte - - hex.Encode(dst[0:2], id[3:4]) - hex.Encode(dst[2:4], id[2:3]) - hex.Encode(dst[4:6], id[1:2]) - hex.Encode(dst[6:8], id[0:1]) - dst[8] = '-' - hex.Encode(dst[9:11], id[5:6]) - hex.Encode(dst[11:13], id[4:5]) - dst[13] = '-' - hex.Encode(dst[14:16], id[7:8]) - hex.Encode(dst[16:18], id[6:7]) - dst[18] = '-' - hex.Encode(dst[19:23], id[8:10]) - dst[23] = '-' - hex.Encode(dst[24:], id[10:]) - - return strings.ToUpper(string(dst[:])) +func (w *eventWatcher) stop() { + if w.stdin != nil { + w.stdin.Close() + w.stdin = nil + } + if w.stdout != nil { + w.stdout.Close() + w.stdout = nil + } + w.process.Kill() } diff --git a/vendor/github.com/vmware/govmomi/simulator/container_host_system.go b/vendor/github.com/vmware/govmomi/simulator/container_host_system.go new file mode 100644 index 00000000000..9d1511e60e6 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/simulator/container_host_system.go @@ -0,0 +1,353 @@ +/* +Copyright (c) 2023-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package simulator + +import ( + "fmt" + "strings" + + "github.com/vmware/govmomi/units" + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" +) + +const ( + advOptPrefixPnicToUnderlayPrefix = "RUN.underlay." + advOptContainerBackingImage = "RUN.container" + defaultUnderlayBridgeName = "vcsim-underlay" +) + +type simHost struct { + host *HostSystem + c *container +} + +// createSimHostMounts iterates over the provide filesystem mount info, creating docker volumes. It does _not_ delete volumes +// already created if creation of one fails. +// Returns: +// volume mounts: mount options suitable to pass directly to docker +// exec commands: a set of commands to run in the sim host after creation +// error: if construction of the above outputs fails +func createSimHostMounts(ctx *Context, containerName string, mounts []types.HostFileSystemMountInfo) ([]string, [][]string, error) { + var dockerVol []string + var symlinkCmds [][]string + + for i := range mounts { + info := &mounts[i] + name := info.Volume.GetHostFileSystemVolume().Name + + // NOTE: if we ever need persistence cross-invocation we can look at encoding the disk info as a label + labels := []string{"name=" + name, "container=" + containerName, deleteWithContainer} + dockerUuid, err := createVolume("", labels, nil) + if err != nil { + return nil, nil, err + } + + uuid := volumeIDtoHostVolumeUUID(dockerUuid) + name = strings.Replace(name, uuidToken, uuid, -1) + + switch vol := info.Volume.(type) { + case *types.HostVmfsVolume: + vol.BlockSizeMb = 1 + vol.BlockSize = units.KB + vol.UnmapGranularity = units.KB + vol.UnmapPriority = "low" + vol.MajorVersion = 6 + vol.Version = "6.82" + vol.Uuid = uuid + vol.HostFileSystemVolume.Name = name + for e := range vol.Extent { + vol.Extent[e].DiskName = "____simulated_volume_____" + if vol.Extent[e].Partition == 0 { + // HACK: this should be unique within the diskname, but for now this will suffice + // partitions start at 1 + vol.Extent[e].Partition = int32(e + 1) + } + } + vol.Ssd = types.NewBool(true) + vol.Local = types.NewBool(true) + case *types.HostVfatVolume: + vol.HostFileSystemVolume.Name = name + } + + info.VStorageSupport = "vStorageUnsupported" + + info.MountInfo.Path = "/vmfs/volumes/" + uuid + info.MountInfo.Mounted = types.NewBool(true) + info.MountInfo.Accessible = types.NewBool(true) + if info.MountInfo.AccessMode == "" { + info.MountInfo.AccessMode = "readWrite" + } + + opt := "rw" + if info.MountInfo.AccessMode == "readOnly" { + opt = "ro" + } + + dockerVol = append(dockerVol, fmt.Sprintf("%s:/vmfs/volumes/%s:%s", dockerUuid, uuid, opt)) + + // create symlinks from /vmfs/volumes/ for the Volume Name - the direct mount (path) is only the uuid + // ? can we do this via a script in the ESX image instead of via exec? + // ? are the volume names exposed in any manner inside the host? They must be because these mounts exist but where does that come from? Chicken and egg problem? ConfigStore? + symlinkCmds = append(symlinkCmds, []string{"ln", "-s", fmt.Sprintf("/vmfs/volumes/%s", uuid), fmt.Sprintf("/vmfs/volumes/%s", name)}) + if strings.HasPrefix(name, "OSDATA") { + symlinkCmds = append(symlinkCmds, []string{"mkdir", "-p", "/var/lib/vmware"}) + symlinkCmds = append(symlinkCmds, []string{"ln", "-s", fmt.Sprintf("/vmfs/volumes/%s", uuid), "/var/lib/vmware/osdata"}) + } + } + + return dockerVol, symlinkCmds, nil +} + +// createSimHostNetworks creates the networks for the host if not already created. Because we expect multiple hosts on the same network to act as a cluster +// it's likely that only the first host will create networks. +// This includes: +// * bridge network per-pNIC +// * bridge network per-DVS +// +// Returns: +// * array of networks to attach to +// * array of commands to run +// * error +// +// TODO: implement bridge network per DVS - not needed until container backed VMs are "created" on container backed "hosts" +func createSimHostNetworks(ctx *Context, containerName string, networkInfo *types.HostNetworkInfo, advOpts *OptionManager) ([]string, [][]string, error) { + var dockerNet []string + var cmds [][]string + + existingNets := make(map[string]string) + + // a pnic does not have an IP so this is purely a connectivity statement, not a network identity, however this is not how docker works + // so we're going to end up with a veth (our pnic) that does have an IP assigned. That IP will end up being used in a NetConfig structure associated + // with the pNIC. See HostSystem.getNetConfigInterface. + for i := range networkInfo.Pnic { + pnicName := networkInfo.Pnic[i].Device + + bridge := getPnicUnderlay(advOpts, pnicName) + + if pnic, attached := existingNets[bridge]; attached { + return nil, nil, fmt.Errorf("cannot attach multiple pNICs to the same underlay: %s and %s both attempting to connect to %s for %s", pnic, pnicName, bridge, containerName) + } + + _, err := createBridge(bridge) + if err != nil { + return nil, nil, err + } + + dockerNet = append(dockerNet, bridge) + existingNets[bridge] = pnicName + } + + return dockerNet, cmds, nil +} + +func getPnicUnderlay(advOpts *OptionManager, pnicName string) string { + queryRes := advOpts.QueryOptions(&types.QueryOptions{Name: advOptPrefixPnicToUnderlayPrefix + pnicName}).(*methods.QueryOptionsBody).Res + return queryRes.Returnval[0].GetOptionValue().Value.(string) +} + +// createSimulationHostcreates a simHost binding if the host.ConfigManager.AdvancedOption set contains a key "RUN.container". +// If the set does not contain that key, this returns nil. +// Methods on the simHost type are written to check for nil object so the return from this call can be blindly +// assigned and invoked without the caller caring about whether a binding for a backing container was warranted. +// +// The created simhost is based off of the details of the supplied host system. +// VMFS locations are created based on FileSystemMountInfo +// Bridge networks are created to simulate underlay networks - one per pNIC. You cannot connect two pNICs to the same underlay. +// +// On Network connectivity - initially this is using docker network constructs. This means we cannot easily use nested "ip netns" so we cannot +// have a perfect representation of the ESX structure: pnic(veth)->vswtich(bridge)->{vmk,vnic}(veth) +// Instead we have the following: +// * bridge network per underlay - everything connects directly to the underlay +// * VMs/CRXs connect to the underlay dictated by the Uplink pNIC attached to their vSwitch +// * hostd vmknic gets the "host" container IP - we don't currently support multiple vmknics with different IPs +// * no support for mocking VLANs +func createSimulationHost(ctx *Context, host *HostSystem) (*simHost, error) { + sh := &simHost{ + host: host, + } + + advOpts := ctx.Map.Get(host.ConfigManager.AdvancedOption.Reference()).(*OptionManager) + fault := advOpts.QueryOptions(&types.QueryOptions{Name: "RUN.container"}).(*methods.QueryOptionsBody).Fault() + if fault != nil { + if _, ok := fault.VimFault().(*types.InvalidName); ok { + return nil, nil + } + return nil, fmt.Errorf("errror retrieving container backing from host config manager: %+v", fault.VimFault()) + } + + // assemble env + var dockerEnv []string + + var execCmds [][]string + + var err error + + hName := host.Summary.Config.Name + hUuid := host.Summary.Hardware.Uuid + containerName := constructContainerName(hName, hUuid) + + // create volumes and mounts + dockerVol, volCmds, err := createSimHostMounts(ctx, containerName, host.Config.FileSystemVolume.MountInfo) + if err != nil { + return nil, err + } + execCmds = append(execCmds, volCmds...) + + // create networks + dockerNet, netCmds, err := createSimHostNetworks(ctx, containerName, host.Config.Network, advOpts) + if err != nil { + return nil, err + } + execCmds = append(execCmds, netCmds...) + + // create the container + sh.c, err = create(ctx, hName, hUuid, dockerNet, dockerVol, nil, dockerEnv, "alpine", []string{"sleep", "infinity"}) + if err != nil { + return nil, err + } + + // start the container + err = sh.c.start(ctx) + if err != nil { + return nil, err + } + + // run post-creation steps + for _, cmd := range execCmds { + _, err := sh.c.exec(ctx, cmd) + if err != nil { + return nil, err + } + } + + _, detail, err := sh.c.inspect() + if err != nil { + return nil, err + } + for i := range host.Config.Network.Pnic { + pnic := &host.Config.Network.Pnic[i] + bridge := getPnicUnderlay(advOpts, pnic.Device) + settings := detail.NetworkSettings.Networks[bridge] + + // it doesn't really make sense at an ESX level to set this information as IP bindings are associated with + // vnics (VMs) or vmknics (daemons such as hostd). + // However it's a useful location to stash this info in a manner that can be retrieved at a later date. + pnic.Spec.Ip.IpAddress = settings.IPAddress + pnic.Spec.Ip.SubnetMask = prefixToMask(settings.IPPrefixLen) + + pnic.Mac = settings.MacAddress + } + + // update the active "management" nicType with the container IP for vmnic0 + netconfig, err := host.getNetConfigInterface(ctx, "management") + if err != nil { + return nil, err + } + netconfig.vmk.Spec.Ip.IpAddress = netconfig.uplink.Spec.Ip.IpAddress + netconfig.vmk.Spec.Ip.SubnetMask = netconfig.uplink.Spec.Ip.SubnetMask + netconfig.vmk.Spec.Mac = netconfig.uplink.Mac + + return sh, nil +} + +// remove destroys the container associated with the host and any volumes with labels specifying their lifecycle +// is coupled with the container +func (sh *simHost) remove(ctx *Context) error { + if sh == nil { + return nil + } + + return sh.c.remove(ctx) +} + +// volumeIDtoHostVolumeUUID takes the 64 char docker uuid and converts it into a 32char ESX form of 8-8-4-12 +// Perhaps we should do this using an md5 rehash, but instead we just take the first 32char for ease of cross-reference. +func volumeIDtoHostVolumeUUID(id string) string { + return fmt.Sprintf("%s-%s-%s-%s", id[0:8], id[8:16], id[16:20], id[20:32]) +} + +// By reference to physical system, partition numbering tends to work out like this: +// 1. EFI System (100 MB) +// Free space (1.97 MB) +// 5. Basic Data (4 GB) (bootbank1) +// 6. Basic Data (4 GB) (bootbank2) +// 7. VMFSL (119.9 GB) (os-data) +// 8. VMFS (1 TB) (datastore1) +// I assume the jump from 1 -> 5 harks back to the primary/logical partitions from MBT days +const uuidToken = "%__UUID__%" + +var defaultSimVolumes = []types.HostFileSystemMountInfo{ + { + MountInfo: types.HostMountInfo{ + AccessMode: "readWrite", + }, + Volume: &types.HostVmfsVolume{ + HostFileSystemVolume: types.HostFileSystemVolume{ + Type: "VMFS", + Name: "datastore1", + Capacity: 1 * units.TB, + }, + Extent: []types.HostScsiDiskPartition{ + { + Partition: 8, + }, + }, + }, + }, + { + MountInfo: types.HostMountInfo{ + AccessMode: "readWrite", + }, + Volume: &types.HostVmfsVolume{ + HostFileSystemVolume: types.HostFileSystemVolume{ + Type: "OTHER", + Name: "OSDATA-%__UUID__%", + Capacity: 128 * units.GB, + }, + Extent: []types.HostScsiDiskPartition{ + { + Partition: 7, + }, + }, + }, + }, + { + MountInfo: types.HostMountInfo{ + AccessMode: "readOnly", + }, + Volume: &types.HostVfatVolume{ + HostFileSystemVolume: types.HostFileSystemVolume{ + Type: "OTHER", + Name: "BOOTBANK1", + Capacity: 4 * units.GB, + }, + }, + }, + { + MountInfo: types.HostMountInfo{ + AccessMode: "readOnly", + }, + Volume: &types.HostVfatVolume{ + HostFileSystemVolume: types.HostFileSystemVolume{ + Type: "OTHER", + Name: "BOOTBANK2", + Capacity: 4 * units.GB, + }, + }, + }, +} diff --git a/vendor/github.com/vmware/govmomi/simulator/container_virtual_machine.go b/vendor/github.com/vmware/govmomi/simulator/container_virtual_machine.go new file mode 100644 index 00000000000..a44ad8b9778 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/simulator/container_virtual_machine.go @@ -0,0 +1,511 @@ +/* +Copyright (c) 2023-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package simulator + +import ( + "archive/tar" + "context" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "io" + "log" + "net/http" + "strconv" + "strings" + + "github.com/google/uuid" + + "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/types" +) + +const ContainerBackingOptionKey = "RUN.container" + +var ( + toolsRunning = []types.PropertyChange{ + {Name: "guest.toolsStatus", Val: types.VirtualMachineToolsStatusToolsOk}, + {Name: "guest.toolsRunningStatus", Val: string(types.VirtualMachineToolsRunningStatusGuestToolsRunning)}, + } + + toolsNotRunning = []types.PropertyChange{ + {Name: "guest.toolsStatus", Val: types.VirtualMachineToolsStatusToolsNotRunning}, + {Name: "guest.toolsRunningStatus", Val: string(types.VirtualMachineToolsRunningStatusGuestToolsNotRunning)}, + } +) + +type simVM struct { + vm *VirtualMachine + c *container +} + +// createSimulationVM inspects the provided VirtualMachine and creates a simVM binding for it if +// the vm.Config.ExtraConfig set contains a key "RUN.container". +// If the ExtraConfig set does not contain that key, this returns nil. +// Methods on the simVM type are written to check for nil object so the return from this call can be blindly +// assigned and invoked without the caller caring about whether a binding for a backing container was warranted. +func createSimulationVM(vm *VirtualMachine) *simVM { + svm := &simVM{ + vm: vm, + } + + for _, opt := range vm.Config.ExtraConfig { + val := opt.GetOptionValue() + if val.Key == ContainerBackingOptionKey { + return svm + } + } + + return nil +} + +// applies container network settings to vm.Guest properties. +func (svm *simVM) syncNetworkConfigToVMGuestProperties() error { + if svm == nil { + return nil + } + + out, detail, err := svm.c.inspect() + if err != nil { + return err + } + + svm.vm.Config.Annotation = "inspect" + svm.vm.logPrintf("%s: %s", svm.vm.Config.Annotation, string(out)) + + netS := detail.NetworkSettings.networkSettings + + // ? Why is this valid - we're taking the first entry while iterating over a MAP + for _, n := range detail.NetworkSettings.Networks { + netS = n + break + } + + if detail.State.Paused { + svm.vm.Runtime.PowerState = types.VirtualMachinePowerStateSuspended + } else if detail.State.Running { + svm.vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOn + } else { + svm.vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff + } + + svm.vm.Guest.IpAddress = netS.IPAddress + svm.vm.Summary.Guest.IpAddress = netS.IPAddress + + if len(svm.vm.Guest.Net) != 0 { + net := &svm.vm.Guest.Net[0] + net.IpAddress = []string{netS.IPAddress} + net.MacAddress = netS.MacAddress + net.IpConfig = &types.NetIpConfigInfo{ + IpAddress: []types.NetIpConfigInfoIpAddress{{ + IpAddress: netS.IPAddress, + PrefixLength: int32(netS.IPPrefixLen), + State: string(types.NetIpConfigInfoIpAddressStatusPreferred), + }}, + } + } + + for _, d := range svm.vm.Config.Hardware.Device { + if eth, ok := d.(types.BaseVirtualEthernetCard); ok { + eth.GetVirtualEthernetCard().MacAddress = netS.MacAddress + break + } + } + + return nil +} + +func (svm *simVM) prepareGuestOperation(auth types.BaseGuestAuthentication) types.BaseMethodFault { + if svm == nil || svm.c == nil || svm.c.id == "" { + return new(types.GuestOperationsUnavailable) + } + + if svm.vm.Runtime.PowerState != types.VirtualMachinePowerStatePoweredOn { + return &types.InvalidPowerState{ + RequestedState: types.VirtualMachinePowerStatePoweredOn, + ExistingState: svm.vm.Runtime.PowerState, + } + } + + switch creds := auth.(type) { + case *types.NamePasswordAuthentication: + if creds.Username == "" || creds.Password == "" { + return new(types.InvalidGuestLogin) + } + default: + return new(types.InvalidGuestLogin) + } + + return nil +} + +// populateDMI writes BIOS UUID DMI files to a container volume +func (svm *simVM) populateDMI() error { + if svm.c == nil { + return nil + } + + files := []tarEntry{ + { + &tar.Header{ + Name: "product_uuid", + Mode: 0444, + }, + []byte(productUUID(svm.vm.uid)), + }, + { + &tar.Header{ + Name: "product_serial", + Mode: 0444, + }, + []byte(productSerial(svm.vm.uid)), + }, + } + + _, err := svm.c.createVolume("dmi", []string{deleteWithContainer}, files) + return err +} + +// start runs the container if specified by the RUN.container extraConfig property. +// lazily creates a container backing if specified by an ExtraConfig property with key "RUN.container" +func (svm *simVM) start(ctx *Context) error { + if svm == nil { + return nil + } + + if svm.c != nil && svm.c.id != "" { + err := svm.c.start(ctx) + if err != nil { + log.Printf("%s %s: %s", svm.vm.Name, "start", err) + } else { + ctx.Map.Update(svm.vm, toolsRunning) + } + + return err + } + + var args []string + var env []string + var ports []string + mountDMI := true + + for _, opt := range svm.vm.Config.ExtraConfig { + val := opt.GetOptionValue() + if val.Key == ContainerBackingOptionKey { + run := val.Value.(string) + err := json.Unmarshal([]byte(run), &args) + if err != nil { + args = []string{run} + } + + continue + } + + if val.Key == "RUN.mountdmi" { + var mount bool + err := json.Unmarshal([]byte(val.Value.(string)), &mount) + if err == nil { + mountDMI = mount + } + + continue + } + + if strings.HasPrefix(val.Key, "RUN.port.") { + // ? would this not make more sense as a set of tuples in the value? + // or inlined into the RUN.container freeform string as is the case with the nginx volume in the examples? + sKey := strings.Split(val.Key, ".") + containerPort := sKey[len(sKey)-1] + ports = append(ports, fmt.Sprintf("%s:%s", val.Value.(string), containerPort)) + + continue + } + + if strings.HasPrefix(val.Key, "RUN.env.") { + sKey := strings.Split(val.Key, ".") + envKey := sKey[len(sKey)-1] + env = append(env, fmt.Sprintf("%s=%s", envKey, val.Value.(string))) + } + + if strings.HasPrefix(val.Key, "guestinfo.") { + key := strings.Replace(strings.ToUpper(val.Key), ".", "_", -1) + env = append(env, fmt.Sprintf("VMX_%s=%s", key, val.Value.(string))) + + continue + } + } + + if len(args) == 0 { + // not an error - it's simply a simVM that shouldn't be backed by a container + return nil + } + + if len(env) != 0 { + // Configure env as the data access method for cloud-init-vmware-guestinfo + env = append(env, "VMX_GUESTINFO=true") + } + + volumes := []string{} + if mountDMI { + volumes = append(volumes, constructVolumeName(svm.vm.Name, svm.vm.uid.String(), "dmi")+":/sys/class/dmi/id") + } + + var err error + svm.c, err = create(ctx, svm.vm.Name, svm.vm.uid.String(), nil, volumes, ports, env, args[0], args[1:]) + if err != nil { + return err + } + + if mountDMI { + // not combined with the test assembling volumes because we want to have the container name first. + // cannot add a label to a volume after creation, so if we want to associate with the container ID the + // container must come first + err = svm.populateDMI() + if err != nil { + return err + } + } + + err = svm.c.start(ctx) + if err != nil { + log.Printf("%s %s: %s %s", svm.vm.Name, "start", args, err) + return err + } + + ctx.Map.Update(svm.vm, toolsRunning) + + svm.vm.logPrintf("%s: %s", args, svm.c.id) + + if err = svm.syncNetworkConfigToVMGuestProperties(); err != nil { + log.Printf("%s inspect %s: %s", svm.vm.Name, svm.c.id, err) + } + + callback := func(details *containerDetails, c *container) error { + spoofctx := SpoofContext() + + if c.id == "" && svm.vm != nil { + // If the container cannot be found then destroy this VM unless the VM is no longer configured for container backing (svm.vm == nil) + taskRef := svm.vm.DestroyTask(spoofctx, &types.Destroy_Task{This: svm.vm.Self}).(*methods.Destroy_TaskBody).Res.Returnval + task, ok := spoofctx.Map.Get(taskRef).(*Task) + if !ok { + panic(fmt.Sprintf("couldn't retrieve task for moref %+q while deleting VM %s", taskRef, svm.vm.Name)) + } + + // Wait for the task to complete and see if there is an error. + task.Wait() + if task.Info.Error != nil { + msg := fmt.Sprintf("failed to destroy vm: err=%v", *task.Info.Error) + svm.vm.logPrintf(msg) + + return errors.New(msg) + } + } + + return svm.syncNetworkConfigToVMGuestProperties() + } + + // Start watching the container resource. + err = svm.c.watchContainer(context.Background(), callback) + if _, ok := err.(uninitializedContainer); ok { + // the container has been deleted before we could watch, despite successful launch so clean up. + callback(nil, svm.c) + + // successful launch so nil the error + return nil + } + + return err +} + +// stop the container (if any) for the given vm. +func (svm *simVM) stop(ctx *Context) error { + if svm == nil || svm.c == nil { + return nil + } + + err := svm.c.stop(ctx) + if err != nil { + log.Printf("%s %s: %s", svm.vm.Name, "stop", err) + + return err + } + + ctx.Map.Update(svm.vm, toolsNotRunning) + + return nil +} + +// pause the container (if any) for the given vm. +func (svm *simVM) pause(ctx *Context) error { + if svm == nil || svm.c == nil { + return nil + } + + err := svm.c.pause(ctx) + if err != nil { + log.Printf("%s %s: %s", svm.vm.Name, "pause", err) + + return err + } + + ctx.Map.Update(svm.vm, toolsNotRunning) + + return nil +} + +// restart the container (if any) for the given vm. +func (svm *simVM) restart(ctx *Context) error { + if svm == nil || svm.c == nil { + return nil + } + + err := svm.c.restart(ctx) + if err != nil { + log.Printf("%s %s: %s", svm.vm.Name, "restart", err) + + return err + } + + ctx.Map.Update(svm.vm, toolsRunning) + + return nil +} + +// remove the container (if any) for the given vm. +func (svm *simVM) remove(ctx *Context) error { + if svm == nil || svm.c == nil { + return nil + } + + err := svm.c.remove(ctx) + if err != nil { + log.Printf("%s %s: %s", svm.vm.Name, "remove", err) + + return err + } + + return nil +} + +func (svm *simVM) exec(ctx *Context, auth types.BaseGuestAuthentication, args []string) (string, types.BaseMethodFault) { + if svm == nil || svm.c == nil { + return "", nil + } + + fault := svm.prepareGuestOperation(auth) + if fault != nil { + return "", fault + } + + out, err := svm.c.exec(ctx, args) + if err != nil { + log.Printf("%s: %s (%s)", svm.vm.Name, args, string(out)) + return "", new(types.GuestOperationsFault) + } + + return strings.TrimSpace(string(out)), nil +} + +func guestUpload(id string, file string, r *http.Request) error { + // TODO: decide behaviour for no container + err := copyToGuest(id, file, r.ContentLength, r.Body) + _ = r.Body.Close() + return err +} + +func guestDownload(id string, file string, w http.ResponseWriter) error { + // TODO: decide behaviour for no container + sink := func(len int64, r io.Reader) error { + w.Header().Set("Content-Length", strconv.FormatInt(len, 10)) + _, err := io.Copy(w, r) + return err + } + + err := copyFromGuest(id, file, sink) + return err +} + +const guestPrefix = "/guestFile/" + +// ServeGuest handles container guest file upload/download +func ServeGuest(w http.ResponseWriter, r *http.Request) { + // Real vCenter form: /guestFile?id=139&token=... + // vcsim form: /guestFile/tmp/foo/bar?id=ebc8837b8cb6&token=... + + id := r.URL.Query().Get("id") + file := strings.TrimPrefix(r.URL.Path, guestPrefix[:len(guestPrefix)-1]) + var err error + + switch r.Method { + case http.MethodPut: + err = guestUpload(id, file, r) + case http.MethodGet: + err = guestDownload(id, file, w) + default: + w.WriteHeader(http.StatusMethodNotAllowed) + return + } + + if err != nil { + log.Printf("%s %s: %s", r.Method, r.URL, err) + w.WriteHeader(http.StatusInternalServerError) + } +} + +// productSerial returns the uuid in /sys/class/dmi/id/product_serial format +func productSerial(id uuid.UUID) string { + var dst [len(id)*2 + len(id) - 1]byte + + j := 0 + for i := 0; i < len(id); i++ { + hex.Encode(dst[j:j+2], id[i:i+1]) + j += 3 + if j < len(dst) { + s := j - 1 + if s == len(dst)/2 { + dst[s] = '-' + } else { + dst[s] = ' ' + } + } + } + + return fmt.Sprintf("VMware-%s", string(dst[:])) +} + +// productUUID returns the uuid in /sys/class/dmi/id/product_uuid format +func productUUID(id uuid.UUID) string { + var dst [36]byte + + hex.Encode(dst[0:2], id[3:4]) + hex.Encode(dst[2:4], id[2:3]) + hex.Encode(dst[4:6], id[1:2]) + hex.Encode(dst[6:8], id[0:1]) + dst[8] = '-' + hex.Encode(dst[9:11], id[5:6]) + hex.Encode(dst[11:13], id[4:5]) + dst[13] = '-' + hex.Encode(dst[14:16], id[7:8]) + hex.Encode(dst[16:18], id[6:7]) + dst[18] = '-' + hex.Encode(dst[19:23], id[8:10]) + dst[23] = '-' + hex.Encode(dst[24:], id[10:]) + + return strings.ToUpper(string(dst[:])) +} diff --git a/vendor/github.com/vmware/govmomi/simulator/dataset.go b/vendor/github.com/vmware/govmomi/simulator/dataset.go new file mode 100644 index 00000000000..0a1b0627ee5 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/simulator/dataset.go @@ -0,0 +1,65 @@ +/* +Copyright (c) 2023-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package simulator + +import ( + "github.com/vmware/govmomi/vapi/vm/dataset" +) + +type DataSet struct { + *dataset.Info + ID string + Entries map[string]string +} + +func copyDataSetsForVmClone(src map[string]*DataSet) map[string]*DataSet { + copy := make(map[string]*DataSet, len(src)) + for k, v := range src { + if v.OmitFromSnapshotAndClone { + continue + } + copy[k] = copyDataSet(v) + } + return copy +} + +func copyDataSet(src *DataSet) *DataSet { + if src == nil { + return nil + } + copy := &DataSet{ + Info: &dataset.Info{ + Name: src.Name, + Description: src.Description, + Host: src.Host, + Guest: src.Guest, + Used: src.Used, + OmitFromSnapshotAndClone: src.OmitFromSnapshotAndClone, + }, + ID: src.ID, + Entries: copyEntries(src.Entries), + } + return copy +} + +func copyEntries(src map[string]string) map[string]string { + copy := make(map[string]string, len(src)) + for k, v := range src { + copy[k] = v + } + return copy +} diff --git a/vendor/github.com/vmware/govmomi/simulator/datastore.go b/vendor/github.com/vmware/govmomi/simulator/datastore.go index f341bdd1743..277674afefc 100644 --- a/vendor/github.com/vmware/govmomi/simulator/datastore.go +++ b/vendor/github.com/vmware/govmomi/simulator/datastore.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -83,6 +83,7 @@ func (ds *Datastore) RefreshDatastore(*types.RefreshDatastore) soap.HasFault { info.Timestamp = types.NewTime(time.Now()) + r.Res = &types.RefreshDatastoreResponse{} return r } diff --git a/vendor/github.com/vmware/govmomi/simulator/doc.go b/vendor/github.com/vmware/govmomi/simulator/doc.go index 441e9a0e7f4..61635c32c1e 100644 --- a/vendor/github.com/vmware/govmomi/simulator/doc.go +++ b/vendor/github.com/vmware/govmomi/simulator/doc.go @@ -17,6 +17,6 @@ limitations under the License. /* Package simulator is a mock framework for the vSphere API. -See also: https://github.com/vmware/govmomi/blob/master/vcsim/README.md +See also: https://github.com/vmware/govmomi/blob/main/vcsim/README.md */ package simulator diff --git a/vendor/github.com/vmware/govmomi/simulator/dvs.go b/vendor/github.com/vmware/govmomi/simulator/dvs.go index ec73f06edc9..9accd85b82a 100644 --- a/vendor/github.com/vmware/govmomi/simulator/dvs.go +++ b/vendor/github.com/vmware/govmomi/simulator/dvs.go @@ -35,6 +35,24 @@ type DistributedVirtualSwitch struct { types.FetchDVPortsResponse } +func (s *DistributedVirtualSwitch) eventArgument() *types.DvsEventArgument { + return &types.DvsEventArgument{ + EntityEventArgument: types.EntityEventArgument{ + Name: s.Name, + }, + Dvs: s.Self, + } +} + +func (s *DistributedVirtualSwitch) event() types.DvsEvent { + return types.DvsEvent{ + Event: types.Event{ + Datacenter: datacenterEventArgument(s), + Dvs: s.eventArgument(), + }, + } +} + func (s *DistributedVirtualSwitch) AddDVPortgroupTask(ctx *Context, c *types.AddDVPortgroup_Task) soap.HasFault { task := CreateTask(s, "addDVPortgroup", func(t *Task) (types.AnyType, types.BaseMethodFault) { f := ctx.Map.getEntityParent(s, "Folder").(*Folder) @@ -152,6 +170,10 @@ func (s *DistributedVirtualSwitch) AddDVPortgroupTask(ctx *Context, c *types.Add {Name: "network", Val: computeNetworks}, }) } + + ctx.postEvent(&types.DVPortgroupCreatedEvent{ + DVPortgroupEvent: pg.event(ctx), + }) } ctx.Map.Update(s, []types.PropertyChange{ @@ -215,6 +237,10 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(ctx *Context, req *types.R } } + ctx.postEvent(&types.DvsHostJoinedEvent{ + DvsEvent: s.event(), + HostJoined: *host.eventArgument(), + }) case types.ConfigSpecOperationRemove: for _, ref := range host.Vm { vm := ctx.Map.Get(ref).(*VirtualMachine) @@ -227,6 +253,11 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(ctx *Context, req *types.R } RemoveReference(&members, member.Host) + + ctx.postEvent(&types.DvsHostLeftEvent{ + DvsEvent: s.event(), + HostLeft: *host.eventArgument(), + }) case types.ConfigSpecOperationEdit: return nil, &types.NotSupported{} } @@ -236,6 +267,11 @@ func (s *DistributedVirtualSwitch) ReconfigureDvsTask(ctx *Context, req *types.R {Name: "summary.hostMember", Val: members}, }) + ctx.postEvent(&types.DvsReconfiguredEvent{ + DvsEvent: s.event(), + ConfigSpec: spec, + }) + return nil, nil }) @@ -256,8 +292,11 @@ func (s *DistributedVirtualSwitch) FetchDVPorts(req *types.FetchDVPorts) soap.Ha func (s *DistributedVirtualSwitch) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.HasFault { task := CreateTask(s, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) { + // TODO: should return ResourceInUse fault if any VM is using a port on this switch + // and past that, remove refs from each host.Network, etc f := ctx.Map.getEntityParent(s, "Folder").(*Folder) folderRemoveChild(ctx, &f.Folder, s.Reference()) + ctx.postEvent(&types.DvsDestroyedEvent{DvsEvent: s.event()}) return nil, nil }) diff --git a/vendor/github.com/vmware/govmomi/simulator/environment_browser.go b/vendor/github.com/vmware/govmomi/simulator/environment_browser.go index 4f8ba8ed9e6..31b50939ab5 100644 --- a/vendor/github.com/vmware/govmomi/simulator/environment_browser.go +++ b/vendor/github.com/vmware/govmomi/simulator/environment_browser.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2019 VMware, Inc. All Rights Reserved. +Copyright (c) 2019-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -29,7 +29,10 @@ import ( type EnvironmentBrowser struct { mo.EnvironmentBrowser - types.QueryConfigOptionResponse + QueryConfigTargetResponse types.QueryConfigTargetResponse + QueryConfigOptionResponse types.QueryConfigOptionResponse + QueryConfigOptionDescriptorResponse types.QueryConfigOptionDescriptorResponse + QueryTargetCapabilitiesResponse types.QueryTargetCapabilitiesResponse } func newEnvironmentBrowser() *types.ManagedObjectReference { @@ -135,7 +138,13 @@ func (b *EnvironmentBrowser) QueryConfigOptionEx(req *types.QueryConfigOptionEx) func (b *EnvironmentBrowser) QueryConfigOptionDescriptor(ctx *Context, req *types.QueryConfigOptionDescriptor) soap.HasFault { body := &methods.QueryConfigOptionDescriptorBody{ - Res: new(types.QueryConfigOptionDescriptorResponse), + Res: &types.QueryConfigOptionDescriptorResponse{ + Returnval: b.QueryConfigOptionDescriptorResponse.Returnval, + }, + } + + if body.Res.Returnval != nil { + return body } body.Res.Returnval = []types.VirtualMachineConfigOptionDescriptor{{ @@ -154,12 +163,18 @@ func (b *EnvironmentBrowser) QueryConfigOptionDescriptor(ctx *Context, req *type func (b *EnvironmentBrowser) QueryConfigTarget(ctx *Context, req *types.QueryConfigTarget) soap.HasFault { body := &methods.QueryConfigTargetBody{ Res: &types.QueryConfigTargetResponse{ - Returnval: &types.ConfigTarget{ - SmcPresent: types.NewBool(false), - }, + Returnval: b.QueryConfigTargetResponse.Returnval, }, } - target := body.Res.Returnval + + if body.Res.Returnval != nil { + return body + } + + target := &types.ConfigTarget{ + SmcPresent: types.NewBool(false), + } + body.Res.Returnval = target var hosts []types.ManagedObjectReference if req.Host == nil { @@ -233,3 +248,22 @@ func (b *EnvironmentBrowser) QueryConfigTarget(ctx *Context, req *types.QueryCon return body } + +func (b *EnvironmentBrowser) QueryTargetCapabilities(ctx *Context, req *types.QueryTargetCapabilities) soap.HasFault { + body := &methods.QueryTargetCapabilitiesBody{ + Res: &types.QueryTargetCapabilitiesResponse{ + Returnval: b.QueryTargetCapabilitiesResponse.Returnval, + }, + } + + if body.Res.Returnval != nil { + return body + } + + body.Res.Returnval = &types.HostCapability{ + VmotionSupported: true, + MaintenanceModeSupported: true, + } + + return body +} diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/authorization_manager.go b/vendor/github.com/vmware/govmomi/simulator/esx/authorization_manager.go index d76459be9ef..38cd244418a 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/authorization_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/authorization_manager.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,7 @@ import "github.com/vmware/govmomi/vim25/types" // RoleList is the default template for the AuthorizationManager roleList property. // Capture method: -// govc object.collect -s -dump AuthorizationManager:ha-authmgr roleList +// govc object.collect -s -dump AuthorizationManager:ha-authmgr roleList var RoleList = []types.AuthorizationRole{ { RoleId: -6, diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/datacenter.go b/vendor/github.com/vmware/govmomi/simulator/esx/datacenter.go index c0f95eff9c9..374cd9518ca 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/datacenter.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/datacenter.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -23,7 +23,7 @@ import ( // Datacenter is the default template for Datacenter properties. // Capture method: -// govc datacenter.info -dump +// govc datacenter.info -dump var Datacenter = mo.Datacenter{ ManagedEntity: mo.ManagedEntity{ ExtensibleManagedObject: mo.ExtensibleManagedObject{ diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/event_manager.go b/vendor/github.com/vmware/govmomi/simulator/esx/event_manager.go index 0a572770f77..17c54cafcea 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/event_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/event_manager.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2018 VMware, Inc. All Rights Reserved. +Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,7 @@ import "github.com/vmware/govmomi/vim25/types" // EventInfo is the default template for the EventManager description.eventInfo property. // Capture method: -// govc object.collect -s -dump EventManager:ha-eventmgr description.eventInfo +// govc object.collect -s -dump EventManager:ha-eventmgr description.eventInfo // The captured list has been manually pruned and FullFormat fields changed to use Go's template variable syntax. var EventInfo = []types.EventDescriptionEventDetail{ { @@ -263,4 +263,46 @@ var EventInfo = []types.EventDescriptionEventDetail{ Category: "info", FullFormat: "DRS powered On {{.Vm.Name}} on {{.Host.Name}} in {{.Datacenter.Name}}", }, + { + Key: "DvsCreatedEvent", + Description: "vSphere Distributed Switch created", + Category: "info", + FullFormat: "A vSphere Distributed Switch {{.Dvs.Name}} was created in {{.Datacenter.Name}}.", + }, + { + Key: "DvsDestroyedEvent", + Description: "vSphere Distributed Switch deleted", + Category: "info", + FullFormat: "vSphere Distributed Switch {{.Dvs.Name}} in {{.Datacenter.Name}} was deleted.", + }, + { + Key: "DvsReconfiguredEvent", + Description: "vSphere Distributed Switch reconfigured", + Category: "info", + FullFormat: "The vSphere Distributed Switch {{.Dvs.Name}} in {{.Datacenter.Name}} was reconfigured.", + }, + { + Key: "DvsHostJoinedEvent", + Description: "Host joined the vSphere Distributed Switch", + Category: "info", + FullFormat: "The host {{.HostJoined.Name}} joined the vSphere Distributed Switch {{.Dvs.Name}} in {{.Datacenter.Name}}.", + }, + { + Key: "DvsHostLeftEvent", + Description: "Host left vSphere Distributed Switch", + Category: "info", + FullFormat: "The host {{.HostLeft.Name}} left the vSphere Distributed Switch {{.Dvs.Name}} in {{.Datacenter.Name}}.", + }, + { + Key: "DVPortgroupCreatedEvent", + Description: "dvPort group created", + Category: "info", + FullFormat: "dvPort group {{.Net.Name}} in {{.Datacenter.Name}} was added to switch {{.Dvs.Name}}.", + }, + { + Key: "DVPortgroupDestroyedEvent", + Description: "dvPort group deleted", + Category: "info", + FullFormat: "dvPort group {{.Net.Name}} in {{.Datacenter.Name}} was deleted.", + }, } diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_config_filesystemvolume.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_config_filesystemvolume.go new file mode 100644 index 00000000000..01c62d0a485 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_config_filesystemvolume.go @@ -0,0 +1,144 @@ +/* +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package esx + +import ( + "github.com/vmware/govmomi/units" + "github.com/vmware/govmomi/vim25/types" +) + +// HostConfigInfo is the default template for the HostSystem config property. +// Capture method: +// govc object.collect -s -dump HostSystem:ha-host config.fileSystemVolume +// - slightly modified for uuids and DiskName +var HostFileSystemVolumeInfo = types.HostFileSystemVolumeInfo{ + VolumeTypeList: []string{"VMFS", "NFS", "NFS41", "vsan", "VVOL", "VFFS", "OTHER", "PMEM"}, + MountInfo: []types.HostFileSystemMountInfo{ + { + MountInfo: types.HostMountInfo{ + Path: "/vmfs/volumes/deadbeef-01234567-89ab-cdef00000003", + AccessMode: "readWrite", + Mounted: types.NewBool(true), + Accessible: types.NewBool(true), + InaccessibleReason: "", + MountFailedReason: "", + }, + Volume: &types.HostVmfsVolume{ + HostFileSystemVolume: types.HostFileSystemVolume{ + Type: "VMFS", + Name: "datastore1", + Capacity: 3.5 * units.TB, + }, + BlockSizeMb: 1, + BlockSize: units.KB, + UnmapGranularity: units.KB, + UnmapPriority: "low", + UnmapBandwidthSpec: (*types.VmfsUnmapBandwidthSpec)(nil), + MaxBlocks: 61 * units.MB, + MajorVersion: 6, + Version: "6.82", + Uuid: "deadbeef-01234567-89ab-cdef00000003", + Extent: []types.HostScsiDiskPartition{ + { + DiskName: "____simulated_volumes_____", + Partition: 8, + }, + }, + VmfsUpgradable: false, + ForceMountedInfo: (*types.HostForceMountedInfo)(nil), + Ssd: types.NewBool(true), + Local: types.NewBool(true), + ScsiDiskType: "", + }, + VStorageSupport: "vStorageUnsupported", + }, + { + MountInfo: types.HostMountInfo{ + Path: "/vmfs/volumes/deadbeef-01234567-89ab-cdef00000002", + AccessMode: "readWrite", + Mounted: types.NewBool(true), + Accessible: types.NewBool(true), + InaccessibleReason: "", + MountFailedReason: "", + }, + Volume: &types.HostVmfsVolume{ + HostFileSystemVolume: types.HostFileSystemVolume{ + Type: "OTHER", + Name: "OSDATA-deadbeef-01234567-89ab-cdef00000002", + Capacity: 128 * units.GB, + }, + BlockSizeMb: 1, + BlockSize: units.KB, + UnmapGranularity: 0, + UnmapPriority: "", + UnmapBandwidthSpec: (*types.VmfsUnmapBandwidthSpec)(nil), + MaxBlocks: 256 * units.KB, + MajorVersion: 1, + Version: "1.00", + Uuid: "deadbeef-01234567-89ab-cdef00000002", + Extent: []types.HostScsiDiskPartition{ + { + DiskName: "____simulated_volumes_____", + Partition: 7, + }, + }, + VmfsUpgradable: false, + ForceMountedInfo: (*types.HostForceMountedInfo)(nil), + Ssd: types.NewBool(true), + Local: types.NewBool(true), + ScsiDiskType: "", + }, + VStorageSupport: "vStorageUnsupported", + }, + { + MountInfo: types.HostMountInfo{ + Path: "/vmfs/volumes/deadbeef-01234567-89ab-cdef00000001", + AccessMode: "readOnly", + Mounted: types.NewBool(true), + Accessible: types.NewBool(true), + InaccessibleReason: "", + MountFailedReason: "", + }, + Volume: &types.HostVfatVolume{ + HostFileSystemVolume: types.HostFileSystemVolume{ + Type: "OTHER", + Name: "BOOTBANK1", + Capacity: 4 * units.GB, + }, + }, + VStorageSupport: "", + }, + { + MountInfo: types.HostMountInfo{ + Path: "/vmfs/volumes/deadbeef-01234567-89ab-cdef00000000", + AccessMode: "readOnly", + Mounted: types.NewBool(true), + Accessible: types.NewBool(true), + InaccessibleReason: "", + MountFailedReason: "", + }, + Volume: &types.HostVfatVolume{ + HostFileSystemVolume: types.HostFileSystemVolume{ + Type: "OTHER", + Name: "BOOTBANK2", + Capacity: 4 * units.GB, + }, + }, + VStorageSupport: "", + }, + }, +} diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_config_info.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_config_info.go index fd7877b28c9..d56c3b607b9 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/host_config_info.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_config_info.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,7 @@ import "github.com/vmware/govmomi/vim25/types" // HostConfigInfo is the default template for the HostSystem config property. // Capture method: -// govc object.collect -s -dump HostSystem:ha-host config +// govc object.collect -s -dump HostSystem:ha-host config var HostConfigInfo = types.HostConfigInfo{ Host: types.ManagedObjectReference{Type: "HostSystem", Value: "ha-host"}, Product: types.AboutInfo{ @@ -50,6 +50,7 @@ var HostConfigInfo = types.HostConfigInfo{ ConsoleReservation: (*types.ServiceConsoleReservationInfo)(nil), VirtualMachineReservation: (*types.VirtualMachineMemoryReservationInfo)(nil), StorageDevice: &HostStorageDeviceInfo, + FileSystemVolume: &HostFileSystemVolumeInfo, SystemFile: nil, Network: &types.HostNetworkInfo{ Vswitch: []types.HostVirtualSwitch{ diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_firewall_system.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_firewall_system.go index 11c1285aad7..46c5dea7e21 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/host_firewall_system.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_firewall_system.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,7 @@ import "github.com/vmware/govmomi/vim25/types" // HostFirewallInfo is the default template for the HostSystem config.firewall property. // Capture method: -// govc object.collect -s -dump HostSystem:ha-host config.firewall +// govc object.collect -s -dump HostSystem:ha-host config.firewall var HostFirewallInfo = types.HostFirewallInfo{ DynamicData: types.DynamicData{}, DefaultPolicy: types.HostFirewallDefaultPolicy{ diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_hardware_info.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_hardware_info.go index aa633ad34bd..a30303fa78e 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/host_hardware_info.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_hardware_info.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -24,7 +24,8 @@ import ( // HostHardwareInfo is the default template for the HostSystem hardware property. // Capture method: -// govc object.collect -s -dump HostSystem:ha-host hardware +// +// govc object.collect -s -dump HostSystem:ha-host hardware var HostHardwareInfo = &types.HostHardwareInfo{ SystemInfo: types.HostSystemInfo{ Vendor: "VMware, Inc.", diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_storage_device_info.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_storage_device_info.go index 9d1ae32dd40..79033344f42 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/host_storage_device_info.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_storage_device_info.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,8 @@ import "github.com/vmware/govmomi/vim25/types" // HostStorageDeviceInfo is the default template for the HostSystem config.storageDevice property. // Capture method: -// govc object.collect -s -dump HostSystem:ha-host config.storageDevice +// +// govc object.collect -s -dump HostSystem:ha-host config.storageDevice var HostStorageDeviceInfo = types.HostStorageDeviceInfo{ HostBusAdapter: []types.BaseHostHostBusAdapter{ &types.HostParallelScsiHba{ diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/host_system.go b/vendor/github.com/vmware/govmomi/simulator/esx/host_system.go index 26cd1962f64..2cd0c685d41 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/host_system.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/host_system.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -25,7 +25,8 @@ import ( // HostSystem is the default template for HostSystem properties. // Capture method: -// govc host.info -dump +// +// govc host.info -dump var HostSystem = mo.HostSystem{ ManagedEntity: mo.ManagedEntity{ ExtensibleManagedObject: mo.ExtensibleManagedObject{ @@ -52,7 +53,7 @@ var HostSystem = mo.HostSystem{ DynamicData: types.DynamicData{}, ConnectionState: "connected", PowerState: "poweredOn", - StandbyMode: "", + StandbyMode: "none", InMaintenanceMode: false, BootTime: (*time.Time)(nil), HealthSystemRuntime: &types.HealthSystemRuntime{ diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/performance_manager.go b/vendor/github.com/vmware/govmomi/simulator/esx/performance_manager.go index 532f0ad5b94..f749514d8ac 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/performance_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/performance_manager.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -18,9 +18,24 @@ package esx import "github.com/vmware/govmomi/vim25/types" +// HistoricalInterval is the default template for the PerformanceManager historicalInterval property. +// Capture method: +// +// govc object.collect -s -dump PerformanceManager:ha-perfmgr historicalInterval +var HistoricalInterval = []types.PerfInterval{ + { + Enabled: true, + Key: 1, + Length: 129600, + Name: "PastDay", + SamplingPeriod: 300, + }, +} + // PerfCounter is the default template for the PerformanceManager perfCounter property. // Capture method: -// govc object.collect -s -dump PerformanceManager:ha-perfmgr perfCounter +// +// govc object.collect -s -dump PerformanceManager:ha-perfmgr perfCounter var PerfCounter = []types.PerfCounterInfo{ { Key: 0, diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/performance_manager_data.go b/vendor/github.com/vmware/govmomi/simulator/esx/performance_manager_data.go index 8d0eaca304b..45c641e7f08 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/performance_manager_data.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/performance_manager_data.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/resource_pool.go b/vendor/github.com/vmware/govmomi/simulator/esx/resource_pool.go index 90382dd326b..2373311aaa0 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/resource_pool.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/resource_pool.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -25,7 +25,8 @@ import ( // ResourcePool is the default template for ResourcePool properties. // Capture method: -// govc pool.info "*" -dump +// +// govc pool.info "*" -dump var ResourcePool = mo.ResourcePool{ ManagedEntity: mo.ManagedEntity{ ExtensibleManagedObject: mo.ExtensibleManagedObject{ diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/root_folder.go b/vendor/github.com/vmware/govmomi/simulator/esx/root_folder.go index 3aefd1d812d..1541de11a61 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/root_folder.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/root_folder.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -23,7 +23,8 @@ import ( // RootFolder is the default template for the ServiceContent rootFolder property. // Capture method: -// govc folder.info -dump / +// +// govc folder.info -dump / var RootFolder = mo.Folder{ ManagedEntity: mo.ManagedEntity{ ExtensibleManagedObject: mo.ExtensibleManagedObject{ diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/service_content.go b/vendor/github.com/vmware/govmomi/simulator/esx/service_content.go index cc8938f8782..bb10eeaa553 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/service_content.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/service_content.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,8 @@ import "github.com/vmware/govmomi/vim25/types" // ServiceContent is the default template for the ServiceInstance content property. // Capture method: -// govc object.collect -s -dump - content +// +// govc object.collect -s -dump - content var ServiceContent = types.ServiceContent{ RootFolder: types.ManagedObjectReference{Type: "Folder", Value: "ha-folder-root"}, PropertyCollector: types.ManagedObjectReference{Type: "PropertyCollector", Value: "ha-property-collector"}, diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/setting.go b/vendor/github.com/vmware/govmomi/simulator/esx/setting.go index 757dfc039c9..54ec6ead07a 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/setting.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/setting.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -21,13 +21,20 @@ import "github.com/vmware/govmomi/vim25/types" // HardwareVersion is the default VirtualMachine.Config.Version var HardwareVersion = "vmx-13" -// Setting is captured from ESX's HostSystem.configManager.advancedOption +// AdvancedOptions is captured from ESX's HostSystem.configManager.advancedOption // Capture method: -// govc object.collect -s -dump $(govc object.collect -s HostSystem:ha-host configManager.advancedOption) setting -var Setting = []types.BaseOptionValue{ +// +// govc object.collect -s -dump $(govc object.collect -s HostSystem:ha-host configManager.advancedOption) setting +var AdvancedOptions = []types.BaseOptionValue{ // This list is currently pruned to include a single option for testing &types.OptionValue{ Key: "Config.HostAgent.log.level", Value: "info", }, } + +// Setting is captured from ESX's HostSystem.ServiceContent.setting +// Capture method: +// +// govc object.collect -s -dump OptionManager:HostAgentSettings setting +var Setting = []types.BaseOptionValue{} diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/task_manager.go b/vendor/github.com/vmware/govmomi/simulator/esx/task_manager.go index b429ad4902e..1b09aff0bd4 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/task_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/task_manager.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017-2018 VMware, Inc. All Rights Reserved. +Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,8 @@ import "github.com/vmware/govmomi/vim25/types" // Description is the default template for the TaskManager description property. // Capture method: -// govc object.collect -s -dump TaskManager:ha-taskmgr description +// +// govc object.collect -s -dump TaskManager:ha-taskmgr description var Description = types.TaskDescription{ MethodInfo: []types.BaseElementDescription{ &types.ElementDescription{ diff --git a/vendor/github.com/vmware/govmomi/simulator/esx/virtual_device.go b/vendor/github.com/vmware/govmomi/simulator/esx/virtual_device.go index 628d7e053d7..a229ddceb87 100644 --- a/vendor/github.com/vmware/govmomi/simulator/esx/virtual_device.go +++ b/vendor/github.com/vmware/govmomi/simulator/esx/virtual_device.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,8 +20,9 @@ import "github.com/vmware/govmomi/vim25/types" // VirtualDevice is the default set of VirtualDevice types created for a VirtualMachine // Capture method: -// govc vm.create foo -// govc object.collect -s -dump vm/foo config.hardware.device +// +// govc vm.create foo +// govc object.collect -s -dump vm/foo config.hardware.device var VirtualDevice = []types.BaseVirtualDevice{ &types.VirtualIDEController{ VirtualController: types.VirtualController{ diff --git a/vendor/github.com/vmware/govmomi/simulator/folder.go b/vendor/github.com/vmware/govmomi/simulator/folder.go index a30094383aa..74b9ac604d5 100644 --- a/vendor/github.com/vmware/govmomi/simulator/folder.go +++ b/vendor/github.com/vmware/govmomi/simulator/folder.go @@ -628,6 +628,15 @@ func (f *Folder) CreateDVSTask(ctx *Context, req *types.CreateDVS_Task) soap.Has }, } + if spec, ok := req.Spec.ConfigSpec.(*types.VMwareDVSConfigSpec); ok { + configInfo.LinkDiscoveryProtocolConfig = spec.LinkDiscoveryProtocolConfig + configInfo.MaxMtu = spec.MaxMtu + configInfo.IpfixConfig = spec.IpfixConfig + configInfo.LacpApiVersion = spec.LacpApiVersion + configInfo.MulticastFilteringMode = spec.MulticastFilteringMode + configInfo.NetworkOffloadSpecId = spec.NetworkOffloadSpecId + } + if spec.Contact != nil { configInfo.Contact = *spec.Contact } @@ -645,6 +654,11 @@ func (f *Folder) CreateDVSTask(ctx *Context, req *types.CreateDVS_Task) soap.Has } } + ctx.postEvent(&types.DvsCreatedEvent{ + DvsEvent: dvs.event(), + Parent: folderEventArgument(&f.Folder), + }) + dvs.AddDVPortgroupTask(ctx, &types.AddDVPortgroup_Task{ Spec: []types.DVPortgroupConfigSpec{{ Name: dvs.Name + "-DVUplinks" + strings.TrimPrefix(dvs.Self.Value, "dvs"), diff --git a/vendor/github.com/vmware/govmomi/simulator/guest_id.go b/vendor/github.com/vmware/govmomi/simulator/guest_id.go index 87cf4aaf835..ce107a81de0 100644 --- a/vendor/github.com/vmware/govmomi/simulator/guest_id.go +++ b/vendor/github.com/vmware/govmomi/simulator/guest_id.go @@ -53,9 +53,22 @@ var GuestID = []types.VirtualMachineGuestOsIdentifier{ types.VirtualMachineGuestOsIdentifierWindows9Guest, types.VirtualMachineGuestOsIdentifierWindows9_64Guest, types.VirtualMachineGuestOsIdentifierWindows9Server64Guest, + types.VirtualMachineGuestOsIdentifierWindows11_64Guest, + types.VirtualMachineGuestOsIdentifierWindows12_64Guest, types.VirtualMachineGuestOsIdentifierWindowsHyperVGuest, + types.VirtualMachineGuestOsIdentifierWindows2019srv_64Guest, + types.VirtualMachineGuestOsIdentifierWindows2019srvNext_64Guest, + types.VirtualMachineGuestOsIdentifierWindows2022srvNext_64Guest, types.VirtualMachineGuestOsIdentifierFreebsdGuest, types.VirtualMachineGuestOsIdentifierFreebsd64Guest, + types.VirtualMachineGuestOsIdentifierFreebsd11Guest, + types.VirtualMachineGuestOsIdentifierFreebsd11_64Guest, + types.VirtualMachineGuestOsIdentifierFreebsd12Guest, + types.VirtualMachineGuestOsIdentifierFreebsd12_64Guest, + types.VirtualMachineGuestOsIdentifierFreebsd13Guest, + types.VirtualMachineGuestOsIdentifierFreebsd13_64Guest, + types.VirtualMachineGuestOsIdentifierFreebsd14Guest, + types.VirtualMachineGuestOsIdentifierFreebsd14_64Guest, types.VirtualMachineGuestOsIdentifierRedhatGuest, types.VirtualMachineGuestOsIdentifierRhel2Guest, types.VirtualMachineGuestOsIdentifierRhel3Guest, @@ -68,18 +81,24 @@ var GuestID = []types.VirtualMachineGuestOsIdentifier{ types.VirtualMachineGuestOsIdentifierRhel6_64Guest, types.VirtualMachineGuestOsIdentifierRhel7Guest, types.VirtualMachineGuestOsIdentifierRhel7_64Guest, + types.VirtualMachineGuestOsIdentifierRhel8_64Guest, + types.VirtualMachineGuestOsIdentifierRhel9_64Guest, types.VirtualMachineGuestOsIdentifierCentosGuest, types.VirtualMachineGuestOsIdentifierCentos64Guest, types.VirtualMachineGuestOsIdentifierCentos6Guest, types.VirtualMachineGuestOsIdentifierCentos6_64Guest, types.VirtualMachineGuestOsIdentifierCentos7Guest, types.VirtualMachineGuestOsIdentifierCentos7_64Guest, + types.VirtualMachineGuestOsIdentifierCentos8_64Guest, + types.VirtualMachineGuestOsIdentifierCentos9_64Guest, types.VirtualMachineGuestOsIdentifierOracleLinuxGuest, types.VirtualMachineGuestOsIdentifierOracleLinux64Guest, types.VirtualMachineGuestOsIdentifierOracleLinux6Guest, types.VirtualMachineGuestOsIdentifierOracleLinux6_64Guest, types.VirtualMachineGuestOsIdentifierOracleLinux7Guest, types.VirtualMachineGuestOsIdentifierOracleLinux7_64Guest, + types.VirtualMachineGuestOsIdentifierOracleLinux8_64Guest, + types.VirtualMachineGuestOsIdentifierOracleLinux9_64Guest, types.VirtualMachineGuestOsIdentifierSuseGuest, types.VirtualMachineGuestOsIdentifierSuse64Guest, types.VirtualMachineGuestOsIdentifierSlesGuest, @@ -90,6 +109,8 @@ var GuestID = []types.VirtualMachineGuestOsIdentifier{ types.VirtualMachineGuestOsIdentifierSles11_64Guest, types.VirtualMachineGuestOsIdentifierSles12Guest, types.VirtualMachineGuestOsIdentifierSles12_64Guest, + types.VirtualMachineGuestOsIdentifierSles15_64Guest, + types.VirtualMachineGuestOsIdentifierSles16_64Guest, types.VirtualMachineGuestOsIdentifierNld9Guest, types.VirtualMachineGuestOsIdentifierOesGuest, types.VirtualMachineGuestOsIdentifierSjdsGuest, @@ -114,12 +135,18 @@ var GuestID = []types.VirtualMachineGuestOsIdentifier{ types.VirtualMachineGuestOsIdentifierDebian9_64Guest, types.VirtualMachineGuestOsIdentifierDebian10Guest, types.VirtualMachineGuestOsIdentifierDebian10_64Guest, + types.VirtualMachineGuestOsIdentifierDebian11Guest, + types.VirtualMachineGuestOsIdentifierDebian11_64Guest, + types.VirtualMachineGuestOsIdentifierDebian12Guest, + types.VirtualMachineGuestOsIdentifierDebian12_64Guest, types.VirtualMachineGuestOsIdentifierAsianux3Guest, types.VirtualMachineGuestOsIdentifierAsianux3_64Guest, types.VirtualMachineGuestOsIdentifierAsianux4Guest, types.VirtualMachineGuestOsIdentifierAsianux4_64Guest, types.VirtualMachineGuestOsIdentifierAsianux5_64Guest, types.VirtualMachineGuestOsIdentifierAsianux7_64Guest, + types.VirtualMachineGuestOsIdentifierAsianux8_64Guest, + types.VirtualMachineGuestOsIdentifierAsianux9_64Guest, types.VirtualMachineGuestOsIdentifierOpensuseGuest, types.VirtualMachineGuestOsIdentifierOpensuse64Guest, types.VirtualMachineGuestOsIdentifierFedoraGuest, @@ -130,10 +157,16 @@ var GuestID = []types.VirtualMachineGuestOsIdentifier{ types.VirtualMachineGuestOsIdentifierOther26xLinuxGuest, types.VirtualMachineGuestOsIdentifierOtherLinuxGuest, types.VirtualMachineGuestOsIdentifierOther3xLinuxGuest, + types.VirtualMachineGuestOsIdentifierOther4xLinuxGuest, + types.VirtualMachineGuestOsIdentifierOther5xLinuxGuest, + types.VirtualMachineGuestOsIdentifierOther6xLinuxGuest, types.VirtualMachineGuestOsIdentifierGenericLinuxGuest, types.VirtualMachineGuestOsIdentifierOther24xLinux64Guest, types.VirtualMachineGuestOsIdentifierOther26xLinux64Guest, types.VirtualMachineGuestOsIdentifierOther3xLinux64Guest, + types.VirtualMachineGuestOsIdentifierOther4xLinux64Guest, + types.VirtualMachineGuestOsIdentifierOther5xLinux64Guest, + types.VirtualMachineGuestOsIdentifierOther6xLinux64Guest, types.VirtualMachineGuestOsIdentifierOtherLinux64Guest, types.VirtualMachineGuestOsIdentifierSolaris6Guest, types.VirtualMachineGuestOsIdentifierSolaris7Guest, @@ -162,10 +195,24 @@ var GuestID = []types.VirtualMachineGuestOsIdentifier{ types.VirtualMachineGuestOsIdentifierDarwin14_64Guest, types.VirtualMachineGuestOsIdentifierDarwin15_64Guest, types.VirtualMachineGuestOsIdentifierDarwin16_64Guest, + types.VirtualMachineGuestOsIdentifierDarwin17_64Guest, + types.VirtualMachineGuestOsIdentifierDarwin18_64Guest, + types.VirtualMachineGuestOsIdentifierDarwin19_64Guest, + types.VirtualMachineGuestOsIdentifierDarwin20_64Guest, + types.VirtualMachineGuestOsIdentifierDarwin21_64Guest, + types.VirtualMachineGuestOsIdentifierDarwin22_64Guest, + types.VirtualMachineGuestOsIdentifierDarwin23_64Guest, types.VirtualMachineGuestOsIdentifierVmkernelGuest, types.VirtualMachineGuestOsIdentifierVmkernel5Guest, types.VirtualMachineGuestOsIdentifierVmkernel6Guest, types.VirtualMachineGuestOsIdentifierVmkernel65Guest, + types.VirtualMachineGuestOsIdentifierVmkernel7Guest, + types.VirtualMachineGuestOsIdentifierVmkernel8Guest, + types.VirtualMachineGuestOsIdentifierAmazonlinux2_64Guest, + types.VirtualMachineGuestOsIdentifierAmazonlinux3_64Guest, + types.VirtualMachineGuestOsIdentifierCrxPod1Guest, + types.VirtualMachineGuestOsIdentifierRockylinux_64Guest, + types.VirtualMachineGuestOsIdentifierAlmalinux_64Guest, types.VirtualMachineGuestOsIdentifierOtherGuest, types.VirtualMachineGuestOsIdentifierOtherGuest64, } diff --git a/vendor/github.com/vmware/govmomi/simulator/guest_operations_manager.go b/vendor/github.com/vmware/govmomi/simulator/guest_operations_manager.go index 780f44a040a..f058835808f 100644 --- a/vendor/github.com/vmware/govmomi/simulator/guest_operations_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/guest_operations_manager.go @@ -69,7 +69,7 @@ func guestURL(ctx *Context, vm *VirtualMachine, path string) string { Host: "*", // See guest.FileManager.TransferURL Path: guestPrefix + strings.TrimPrefix(path, "/"), RawQuery: url.Values{ - "id": []string{vm.run.id}, + "id": []string{vm.svm.c.id}, "token": []string{ctx.Session.Key}, }.Encode(), }).String() @@ -79,7 +79,7 @@ func (m *GuestFileManager) InitiateFileTransferToGuest(ctx *Context, req *types. body := new(methods.InitiateFileTransferToGuestBody) vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - err := vm.run.prepareGuestOperation(vm, req.Auth) + err := vm.svm.prepareGuestOperation(req.Auth) if err != nil { body.Fault_ = Fault("", err) return body @@ -96,7 +96,7 @@ func (m *GuestFileManager) InitiateFileTransferFromGuest(ctx *Context, req *type body := new(methods.InitiateFileTransferFromGuestBody) vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - err := vm.run.prepareGuestOperation(vm, req.Auth) + err := vm.svm.prepareGuestOperation(req.Auth) if err != nil { body.Fault_ = Fault("", err) return body @@ -126,7 +126,7 @@ func (m *GuestProcessManager) StartProgramInGuest(ctx *Context, req *types.Start vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - fault := vm.run.prepareGuestOperation(vm, auth) + fault := vm.svm.prepareGuestOperation(auth) if fault != nil { body.Fault_ = Fault("", fault) } @@ -141,7 +141,7 @@ func (m *GuestProcessManager) StartProgramInGuest(ctx *Context, req *types.Start args = append(args, "-e", e) } - args = append(args, vm.run.id, spec.ProgramPath, spec.Arguments) + args = append(args, vm.svm.c.id, spec.ProgramPath, spec.Arguments) spec.ProgramPath = "docker" spec.Arguments = strings.Join(args, " ") @@ -213,7 +213,7 @@ func (m *GuestFileManager) mktemp(ctx *Context, req *types.CreateTemporaryFileIn vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - return vm.run.exec(ctx, vm, req.Auth, args) + return vm.svm.exec(ctx, req.Auth, args) } func (m *GuestFileManager) CreateTemporaryFileInGuest(ctx *Context, req *types.CreateTemporaryFileInGuest) soap.HasFault { @@ -298,7 +298,7 @@ func (m *GuestFileManager) ListFilesInGuest(ctx *Context, req *types.ListFilesIn return body } - res, fault := vm.run.exec(ctx, vm, req.Auth, listFiles(req)) + res, fault := vm.svm.exec(ctx, req.Auth, listFiles(req)) if fault != nil { body.Fault_ = Fault("", fault) return body @@ -317,7 +317,7 @@ func (m *GuestFileManager) DeleteFileInGuest(ctx *Context, req *types.DeleteFile vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - _, fault := vm.run.exec(ctx, vm, req.Auth, args) + _, fault := vm.svm.exec(ctx, req.Auth, args) if fault != nil { body.Fault_ = Fault("", fault) return body @@ -338,7 +338,7 @@ func (m *GuestFileManager) DeleteDirectoryInGuest(ctx *Context, req *types.Delet vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - _, fault := vm.run.exec(ctx, vm, req.Auth, args) + _, fault := vm.svm.exec(ctx, req.Auth, args) if fault != nil { body.Fault_ = Fault("", fault) return body @@ -359,7 +359,7 @@ func (m *GuestFileManager) MakeDirectoryInGuest(ctx *Context, req *types.MakeDir vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - _, fault := vm.run.exec(ctx, vm, req.Auth, args) + _, fault := vm.svm.exec(ctx, req.Auth, args) if fault != nil { body.Fault_ = Fault("", fault) return body @@ -381,7 +381,7 @@ func (m *GuestFileManager) MoveFileInGuest(ctx *Context, req *types.MoveFileInGu vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - _, fault := vm.run.exec(ctx, vm, req.Auth, args) + _, fault := vm.svm.exec(ctx, req.Auth, args) if fault != nil { body.Fault_ = Fault("", fault) return body @@ -399,7 +399,7 @@ func (m *GuestFileManager) MoveDirectoryInGuest(ctx *Context, req *types.MoveDir vm := ctx.Map.Get(req.Vm).(*VirtualMachine) - _, fault := vm.run.exec(ctx, vm, req.Auth, args) + _, fault := vm.svm.exec(ctx, req.Auth, args) if fault != nil { body.Fault_ = Fault("", fault) return body @@ -424,7 +424,7 @@ func (m *GuestFileManager) ChangeFileAttributesInGuest(ctx *Context, req *types. if attr.Permissions != 0 { args := []string{"chmod", fmt.Sprintf("%#o", attr.Permissions), req.GuestFilePath} - _, fault := vm.run.exec(ctx, vm, req.Auth, args) + _, fault := vm.svm.exec(ctx, req.Auth, args) if fault != nil { body.Fault_ = Fault("", fault) return body @@ -443,7 +443,7 @@ func (m *GuestFileManager) ChangeFileAttributesInGuest(ctx *Context, req *types. if c.id != nil { args := []string{c.cmd, fmt.Sprintf("%d", *c.id), req.GuestFilePath} - _, fault := vm.run.exec(ctx, vm, req.Auth, args) + _, fault := vm.svm.exec(ctx, req.Auth, args) if fault != nil { body.Fault_ = Fault("", fault) return body diff --git a/vendor/github.com/vmware/govmomi/simulator/host_datastore_browser.go b/vendor/github.com/vmware/govmomi/simulator/host_datastore_browser.go index 185ebbd8533..47252031631 100644 --- a/vendor/github.com/vmware/govmomi/simulator/host_datastore_browser.go +++ b/vendor/github.com/vmware/govmomi/simulator/host_datastore_browser.go @@ -17,7 +17,6 @@ limitations under the License. package simulator import ( - "io/ioutil" "os" "path" "strings" @@ -149,7 +148,7 @@ func (s *searchDatastore) queryMatch(file os.FileInfo) bool { } func (s *searchDatastore) search(ds *types.ManagedObjectReference, folder string, dir string) error { - files, err := ioutil.ReadDir(dir) + files, err := os.ReadDir(dir) if err != nil { tracef("search %s: %s", dir, err) return err @@ -162,11 +161,11 @@ func (s *searchDatastore) search(ds *types.ManagedObjectReference, folder string for _, file := range files { name := file.Name() - - if s.queryMatch(file) { + info, _ := file.Info() + if s.queryMatch(info) { for _, m := range s.SearchSpec.MatchPattern { if ok, _ := path.Match(m, name); ok { - s.addFile(file, &res) + s.addFile(info, &res) break } } diff --git a/vendor/github.com/vmware/govmomi/simulator/host_network_system.go b/vendor/github.com/vmware/govmomi/simulator/host_network_system.go index 4afdda0a16b..351604f82bc 100644 --- a/vendor/github.com/vmware/govmomi/simulator/host_network_system.go +++ b/vendor/github.com/vmware/govmomi/simulator/host_network_system.go @@ -198,6 +198,12 @@ func (s *HostNetworkSystem) UpdateNetworkConfig(req *types.UpdateNetworkConfig) } func (s *HostNetworkSystem) QueryNetworkHint(req *types.QueryNetworkHint) soap.HasFault { + if s.Host.Runtime.ConnectionState != types.HostSystemConnectionStateConnected { + return &methods.QueryNetworkHintBody{ + Fault_: Fault("", &types.HostNotConnected{}), + } + } + return &methods.QueryNetworkHintBody{ Res: &types.QueryNetworkHintResponse{ Returnval: s.QueryNetworkHintResponse.Returnval, diff --git a/vendor/github.com/vmware/govmomi/simulator/host_system.go b/vendor/github.com/vmware/govmomi/simulator/host_system.go index f28101a8c3e..fd88cb4978c 100644 --- a/vendor/github.com/vmware/govmomi/simulator/host_system.go +++ b/vendor/github.com/vmware/govmomi/simulator/host_system.go @@ -17,8 +17,10 @@ limitations under the License. package simulator import ( + "fmt" "net" "os" + "sync" "time" "github.com/vmware/govmomi/simulator/esx" @@ -30,10 +32,16 @@ import ( var ( hostPortUnique = os.Getenv("VCSIM_HOST_PORT_UNIQUE") == "true" + + globalLock sync.Mutex + // globalHostCount is used to construct unique hostnames. Should be consumed under globalLock. + globalHostCount = 0 ) type HostSystem struct { mo.HostSystem + + sh *simHost } func asHostSystemMO(obj mo.Reference) (*mo.HostSystem, bool) { @@ -72,13 +80,23 @@ func NewHostSystem(host mo.HostSystem) *HostSystem { deepCopy(hs.Config, cfg) hs.Config = cfg + // copy over the reference advanced options so each host can have it's own, allowing hosts to be configured for + // container backing individually + deepCopy(esx.AdvancedOptions, &cfg.Option) + + // add a supported option to the AdvancedOption manager + simOption := types.OptionDef{ElementDescription: types.ElementDescription{Key: advOptContainerBackingImage}} + // TODO: how do we enter patterns here? Or should we stick to a list in the value? + // patterns become necessary if we want to enforce correctness on options for RUN.underlay. or allow RUN.port.xxx + hs.Config.OptionDef = append(hs.Config.OptionDef, simOption) + config := []struct { ref **types.ManagedObjectReference obj mo.Reference }{ {&hs.ConfigManager.DatastoreSystem, &HostDatastoreSystem{Host: &hs.HostSystem}}, {&hs.ConfigManager.NetworkSystem, NewHostNetworkSystem(&hs.HostSystem)}, - {&hs.ConfigManager.AdvancedOption, NewOptionManager(nil, esx.Setting)}, + {&hs.ConfigManager.AdvancedOption, NewOptionManager(nil, nil, &hs.Config.Option)}, {&hs.ConfigManager.FirewallSystem, NewHostFirewallSystem(&hs.HostSystem)}, {&hs.ConfigManager.StorageSystem, NewHostStorageSystem(&hs.HostSystem)}, } @@ -92,12 +110,23 @@ func NewHostSystem(host mo.HostSystem) *HostSystem { return hs } -func (h *HostSystem) configure(spec types.HostConnectSpec, connected bool) { +func (h *HostSystem) configure(ctx *Context, spec types.HostConnectSpec, connected bool) { h.Runtime.ConnectionState = types.HostSystemConnectionStateDisconnected if connected { h.Runtime.ConnectionState = types.HostSystemConnectionStateConnected } - if net.ParseIP(spec.HostName) != nil { + + // lets us construct non-conflicting hostname automatically if omitted + // does not use the unique port instead to avoid constraints on port, such as >1024 + + globalLock.Lock() + instanceID := globalHostCount + globalHostCount++ + globalLock.Unlock() + + if spec.HostName == "" { + spec.HostName = fmt.Sprintf("esx-%d", instanceID) + } else if net.ParseIP(spec.HostName) != nil { h.Config.Network.Vnic[0].Spec.Ip.IpAddress = spec.HostName } @@ -106,6 +135,241 @@ func (h *HostSystem) configure(spec types.HostConnectSpec, connected bool) { id := newUUID(h.Name) h.Summary.Hardware.Uuid = id h.Hardware.SystemInfo.Uuid = id + + var err error + h.sh, err = createSimulationHost(ctx, h) + if err != nil { + panic("failed to create simulation host and no path to return error: " + err.Error()) + } +} + +// configureContainerBacking sets up _this_ host for simulation using a container backing. +// Args: +// +// image - the container image with which to simulate the host +// mounts - array of mount info that should be translated into /vmfs/volumes/... mounts backed by container volumes +// networks - names of bridges to use for underlays. Will create a pNIC for each. The first will be treated as the management network. +// +// Restrictions adopted from createSimulationHost: +// * no mock of VLAN connectivity +// * only a single vmknic, used for "the management IP" +// * pNIC connectivity does not directly impact VMs/vmks using it as uplink +// +// The pnics will be named using standard pattern, ie. vmnic0, vmnic1, ... +// This will sanity check the NetConfig for "management" nicType to ensure that it maps through PortGroup->vSwitch->pNIC to vmnic0. +func (h *HostSystem) configureContainerBacking(ctx *Context, image string, mounts []types.HostFileSystemMountInfo, networks ...string) error { + option := &types.OptionValue{ + Key: advOptContainerBackingImage, + Value: image, + } + + advOpts := ctx.Map.Get(h.ConfigManager.AdvancedOption.Reference()).(*OptionManager) + fault := advOpts.UpdateOptions(&types.UpdateOptions{ChangedValue: []types.BaseOptionValue{option}}).Fault() + if fault != nil { + panic(fault) + } + + h.Config.FileSystemVolume = nil + if mounts != nil { + h.Config.FileSystemVolume = &types.HostFileSystemVolumeInfo{ + VolumeTypeList: []string{"VMFS", "OTHER"}, + MountInfo: mounts, + } + } + + // force at least a management network + if len(networks) == 0 { + networks = []string{defaultUnderlayBridgeName} + } + + // purge pNICs from the template - it makes no sense to keep them for a sim host + h.Config.Network.Pnic = make([]types.PhysicalNic, len(networks)) + + // purge any IPs and MACs associated with existing NetConfigs for the host + for cfgIdx := range h.Config.VirtualNicManagerInfo.NetConfig { + config := &h.Config.VirtualNicManagerInfo.NetConfig[cfgIdx] + for candidateIdx := range config.CandidateVnic { + candidate := &config.CandidateVnic[candidateIdx] + candidate.Spec.Ip.IpAddress = "0.0.0.0" + candidate.Spec.Ip.SubnetMask = "0.0.0.0" + candidate.Spec.Mac = "00:00:00:00:00:00" + } + } + + // The presence of a pNIC is used to indicate connectivity to a specific underlay. We construct an empty pNIC entry and specify the underly via + // host.ConfigManager.AdvancedOptions. The pNIC will be populated with the MAC (accurate) and IP (divergence - we need to stash it somewhere) for the veth. + // We create a NetConfig "management" entry for the first pNIC - this will be populated with the IP of the "host" container. + + // create a pNIC for each underlay + for i, net := range networks { + name := fmt.Sprintf("vmnic%d", i) + + // we don't have a natural field for annotating which pNIC is connected to which network, so stash it in an adv option. + option := &types.OptionValue{ + Key: advOptPrefixPnicToUnderlayPrefix + name, + Value: net, + } + fault = advOpts.UpdateOptions(&types.UpdateOptions{ChangedValue: []types.BaseOptionValue{option}}).Fault() + if fault != nil { + panic(fault) + } + + h.Config.Network.Pnic[i] = types.PhysicalNic{ + Key: "key-vim.host.PhysicalNic-" + name, + Device: name, + Pci: fmt.Sprintf("0000:%2d:00.0", i+1), + Driver: "vcsim-bridge", + DriverVersion: "1.2.10.0", + FirmwareVersion: "1.57, 0x80000185", + LinkSpeed: &types.PhysicalNicLinkInfo{ + SpeedMb: 10000, + Duplex: true, + }, + ValidLinkSpecification: []types.PhysicalNicLinkInfo{ + { + SpeedMb: 10000, + Duplex: true, + }, + }, + Spec: types.PhysicalNicSpec{ + Ip: &types.HostIpConfig{}, + LinkSpeed: (*types.PhysicalNicLinkInfo)(nil), + EnableEnhancedNetworkingStack: types.NewBool(false), + EnsInterruptEnabled: types.NewBool(false), + }, + WakeOnLanSupported: false, + Mac: "00:00:00:00:00:00", + FcoeConfiguration: &types.FcoeConfig{ + PriorityClass: 3, + SourceMac: "00:00:00:00:00:00", + VlanRange: []types.FcoeConfigVlanRange{ + {}, + }, + Capabilities: types.FcoeConfigFcoeCapabilities{}, + FcoeActive: false, + }, + VmDirectPathGen2Supported: types.NewBool(false), + VmDirectPathGen2SupportedMode: "", + ResourcePoolSchedulerAllowed: types.NewBool(false), + ResourcePoolSchedulerDisallowedReason: nil, + AutoNegotiateSupported: types.NewBool(true), + EnhancedNetworkingStackSupported: types.NewBool(false), + EnsInterruptSupported: types.NewBool(false), + RdmaDevice: "", + DpuId: "", + } + } + + // sanity check that everything's hung together sufficiently well + details, err := h.getNetConfigInterface(ctx, "management") + if err != nil { + return err + } + + if details.uplink == nil || details.uplink.Device != "vmnic0" { + return fmt.Errorf("Config provided for host %s does not result in a consistent 'management' NetConfig that's bound to 'vmnic0'", h.Name) + } + + return nil +} + +// netConfigDetails is used to packaged up all the related network entities associated with a NetConfig binding +type netConfigDetails struct { + nicType string + netconfig *types.VirtualNicManagerNetConfig + vmk *types.HostVirtualNic + netstack *types.HostNetStackInstance + portgroup *types.HostPortGroup + vswitch *types.HostVirtualSwitch + uplink *types.PhysicalNic +} + +// getNetConfigInterface returns the set of constructs active for a given nicType (eg. "management", "vmotion") +// This method is provided because the Config structure held by HostSystem is heavily interconnected but serialized and not cross-linked with pointers. +// As such there's a _lot_ of cross-referencing that needs to be done to navigate. +// The pNIC returned is the uplink associated with the vSwitch for the netconfig +func (h *HostSystem) getNetConfigInterface(ctx *Context, nicType string) (*netConfigDetails, error) { + details := &netConfigDetails{ + nicType: nicType, + } + + for i := range h.Config.VirtualNicManagerInfo.NetConfig { + if h.Config.VirtualNicManagerInfo.NetConfig[i].NicType == nicType { + details.netconfig = &h.Config.VirtualNicManagerInfo.NetConfig[i] + break + } + } + if details.netconfig == nil { + return nil, fmt.Errorf("no matching NetConfig for NicType=%s", nicType) + } + + if details.netconfig.SelectedVnic == nil { + return details, nil + } + + vnicKey := details.netconfig.SelectedVnic[0] + for i := range details.netconfig.CandidateVnic { + if details.netconfig.CandidateVnic[i].Key == vnicKey { + details.vmk = &details.netconfig.CandidateVnic[i] + break + } + } + if details.vmk == nil { + panic(fmt.Sprintf("NetConfig for host %s references non-existant vNIC key %s for %s nicType", h.Name, vnicKey, nicType)) + } + + portgroupName := details.vmk.Portgroup + netstackKey := details.vmk.Spec.NetStackInstanceKey + + for i := range h.Config.Network.NetStackInstance { + if h.Config.Network.NetStackInstance[i].Key == netstackKey { + details.netstack = &h.Config.Network.NetStackInstance[i] + break + } + } + if details.netstack == nil { + panic(fmt.Sprintf("NetConfig for host %s references non-existant NetStack key %s for %s nicType", h.Name, netstackKey, nicType)) + } + + for i := range h.Config.Network.Portgroup { + // TODO: confirm correctness of this - seems weird it references the Spec.Name instead of the key like everything else. + if h.Config.Network.Portgroup[i].Spec.Name == portgroupName { + details.portgroup = &h.Config.Network.Portgroup[i] + break + } + } + if details.portgroup == nil { + panic(fmt.Sprintf("NetConfig for host %s references non-existant PortGroup name %s for %s nicType", h.Name, portgroupName, nicType)) + } + + vswitchKey := details.portgroup.Vswitch + for i := range h.Config.Network.Vswitch { + if h.Config.Network.Vswitch[i].Key == vswitchKey { + details.vswitch = &h.Config.Network.Vswitch[i] + break + } + } + if details.vswitch == nil { + panic(fmt.Sprintf("NetConfig for host %s references non-existant vSwitch key %s for %s nicType", h.Name, vswitchKey, nicType)) + } + + if len(details.vswitch.Pnic) != 1 { + // to change this, look at the Active NIC in the NicTeamingPolicy, but for now not worth it + panic(fmt.Sprintf("vSwitch %s for host %s has multiple pNICs associated which is not supported.", vswitchKey, h.Name)) + } + + pnicKey := details.vswitch.Pnic[0] + for i := range h.Config.Network.Pnic { + if h.Config.Network.Pnic[i].Key == pnicKey { + details.uplink = &h.Config.Network.Pnic[i] + break + } + } + if details.uplink == nil { + panic(fmt.Sprintf("NetConfig for host %s references non-existant pNIC key %s for %s nicType", h.Name, pnicKey, nicType)) + } + + return details, nil } func (h *HostSystem) event() types.HostEvent { @@ -207,7 +471,7 @@ func CreateStandaloneHost(ctx *Context, f *Folder, spec types.HostConnectSpec) ( pool := NewResourcePool() host := NewHostSystem(template) - host.configure(spec, false) + host.configure(ctx, spec, false) summary := new(types.ComputeResourceSummary) addComputeResource(summary, host) @@ -222,6 +486,7 @@ func CreateStandaloneHost(ctx *Context, f *Folder, spec types.HostConnectSpec) ( ctx.Map.PutEntity(cr, ctx.Map.NewEntity(host)) host.Summary.Host = &host.Self + host.Config.Host = host.Self ctx.Map.PutEntity(cr, ctx.Map.NewEntity(pool)) @@ -247,6 +512,17 @@ func (h *HostSystem) DestroyTask(ctx *Context, req *types.Destroy_Task) soap.Has f := ctx.Map.getEntityParent(h, "Folder").(*Folder) folderRemoveChild(ctx, &f.Folder, h.Reference()) + err := h.sh.remove(ctx) + + if err != nil { + return nil, &types.RuntimeFault{ + MethodFault: types.MethodFault{ + FaultCause: &types.LocalizedMethodFault{ + Fault: &types.SystemErrorFault{Reason: err.Error()}, + LocalizedMessage: err.Error()}}} + } + + // TODO: should there be events on lifecycle operations as with VMs? return nil, nil }) diff --git a/vendor/github.com/vmware/govmomi/simulator/http_nfc_lease.go b/vendor/github.com/vmware/govmomi/simulator/http_nfc_lease.go index 26e0d299fc1..54d312caf1f 100644 --- a/vendor/github.com/vmware/govmomi/simulator/http_nfc_lease.go +++ b/vendor/github.com/vmware/govmomi/simulator/http_nfc_lease.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2019 VMware, Inc. All Rights Reserved. +Copyright (c) 2019-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -17,9 +17,11 @@ limitations under the License. package simulator import ( + "crypto/sha1" + "encoding/hex" "fmt" + "hash" "io" - "io/ioutil" "log" "net/http" "os" @@ -32,9 +34,15 @@ import ( "github.com/vmware/govmomi/vim25/types" ) +type metadata struct { + sha1 []byte + size int64 +} + type HttpNfcLease struct { mo.HttpNfcLease - files map[string]string + files map[string]string + metadata map[string]metadata } var ( @@ -62,12 +70,12 @@ func ServeNFC(w http.ResponseWriter, r *http.Request) { } status := http.StatusOK - var dst io.Writer + var dst hash.Hash var src io.ReadCloser switch r.Method { case http.MethodPut, http.MethodPost: - dst = ioutil.Discard + dst = sha1.New() src = r.Body case http.MethodGet: f, err := os.Open(file) @@ -82,6 +90,12 @@ func ServeNFC(w http.ResponseWriter, r *http.Request) { n, err := io.Copy(dst, src) _ = src.Close() + if dst != nil { + lease.metadata[name] = metadata{ + sha1: dst.Sum(nil), + size: n, + } + } msg := fmt.Sprintf("transferred %d bytes", n) if err != nil { @@ -92,16 +106,38 @@ func ServeNFC(w http.ResponseWriter, r *http.Request) { w.WriteHeader(status) } -func NewHttpNfcLease(ctx *Context, entity types.ManagedObjectReference) *HttpNfcLease { +func (l *HttpNfcLease) error(ctx *Context, err *types.LocalizedMethodFault) { + ctx.WithLock(l, func() { + ctx.Map.Update(l, []types.PropertyChange{ + {Name: "state", Val: types.HttpNfcLeaseStateError}, + {Name: "error", Val: err}, + }) + }) +} + +func (l *HttpNfcLease) ready(ctx *Context, entity types.ManagedObjectReference, urls []types.HttpNfcLeaseDeviceUrl) { + info := &types.HttpNfcLeaseInfo{ + Lease: l.Self, + Entity: entity, + DeviceUrl: urls, + LeaseTimeout: 300, + } + + ctx.WithLock(l, func() { + ctx.Map.Update(l, []types.PropertyChange{ + {Name: "state", Val: types.HttpNfcLeaseStateReady}, + {Name: "info", Val: info}, + }) + }) +} + +func newHttpNfcLease(ctx *Context) *HttpNfcLease { lease := &HttpNfcLease{ HttpNfcLease: mo.HttpNfcLease{ - Info: &types.HttpNfcLeaseInfo{ - Entity: entity, - LeaseTimeout: 30000, - }, - State: types.HttpNfcLeaseStateReady, + State: types.HttpNfcLeaseStateInitializing, }, - files: make(map[string]string), + files: make(map[string]string), + metadata: make(map[string]metadata), } ctx.Session.Put(lease) @@ -135,3 +171,28 @@ func (l *HttpNfcLease) HttpNfcLeaseProgress(ctx *Context, req *types.HttpNfcLeas Res: new(types.HttpNfcLeaseProgressResponse), } } + +func (l *HttpNfcLease) getDeviceKey(name string) string { + for _, devUrl := range l.Info.DeviceUrl { + if name == devUrl.TargetId { + return devUrl.Key + } + } + return "unknown" +} + +func (l *HttpNfcLease) HttpNfcLeaseGetManifest(ctx *Context, req *types.HttpNfcLeaseGetManifest) soap.HasFault { + entries := []types.HttpNfcLeaseManifestEntry{} + for name, md := range l.metadata { + entries = append(entries, types.HttpNfcLeaseManifestEntry{ + Key: l.getDeviceKey(name), + Sha1: hex.EncodeToString(md.sha1), + Size: md.size, + }) + } + return &methods.HttpNfcLeaseGetManifestBody{ + Res: &types.HttpNfcLeaseGetManifestResponse{ + Returnval: entries, + }, + } +} diff --git a/vendor/github.com/vmware/govmomi/simulator/internal/server.go b/vendor/github.com/vmware/govmomi/simulator/internal/server.go index 1f814dea29d..877eca0dcc0 100644 --- a/vendor/github.com/vmware/govmomi/simulator/internal/server.go +++ b/vendor/github.com/vmware/govmomi/simulator/internal/server.go @@ -286,15 +286,18 @@ func (s *Server) wrap() { s.Config.ConnState = func(c net.Conn, cs http.ConnState) { s.mu.Lock() defer s.mu.Unlock() + switch cs { case http.StateNew: - s.wg.Add(1) if _, exists := s.conns[c]; exists { panic("invalid state transition") } if s.conns == nil { s.conns = make(map[net.Conn]http.ConnState) } + // Add c to the set of tracked conns and increment it to the + // waitgroup. + s.wg.Add(1) s.conns[c] = cs if s.closed { // Probably just a socket-late-binding dial from @@ -321,7 +324,14 @@ func (s *Server) wrap() { s.closeConn(c) } case http.StateHijacked, http.StateClosed: - s.forgetConn(c) + // Remove c from the set of tracked conns and decrement it from the + // waitgroup, unless it was previously removed. + if _, ok := s.conns[c]; ok { + delete(s.conns, c) + // Keep Close from returning until the user's ConnState hook + // (if any) finishes. + defer s.wg.Done() + } } if oldHook != nil { oldHook(c, cs) @@ -341,13 +351,3 @@ func (s *Server) closeConnChan(c net.Conn, done chan<- struct{}) { done <- struct{}{} } } - -// forgetConn removes c from the set of tracked conns and decrements it from the -// waitgroup, unless it was previously removed. -// s.mu must be held. -func (s *Server) forgetConn(c net.Conn) { - if _, ok := s.conns[c]; ok { - delete(s.conns, c) - s.wg.Done() - } -} diff --git a/vendor/github.com/vmware/govmomi/simulator/model.go b/vendor/github.com/vmware/govmomi/simulator/model.go index 7d137dd2be4..1d65c5944ce 100644 --- a/vendor/github.com/vmware/govmomi/simulator/model.go +++ b/vendor/github.com/vmware/govmomi/simulator/model.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017-2021 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,6 @@ import ( "context" "crypto/tls" "fmt" - "io/ioutil" "log" "math/rand" "os" @@ -75,32 +74,32 @@ type Model struct { // Datacenter specifies the number of Datacenter entities to create // Name prefix: DC, vcsim flag: -dc - Datacenter int + Datacenter int `json:"datacenter"` // Portgroup specifies the number of DistributedVirtualPortgroup entities to create per Datacenter // Name prefix: DVPG, vcsim flag: -pg - Portgroup int + Portgroup int `json:"portgroup"` // PortgroupNSX specifies the number NSX backed DistributedVirtualPortgroup entities to create per Datacenter // Name prefix: NSXPG, vcsim flag: -nsx-pg - PortgroupNSX int + PortgroupNSX int `json:"portgroupNSX"` // OpaqueNetwork specifies the number of OpaqueNetwork entities to create per Datacenter, // with Summary.OpaqueNetworkType set to nsx.LogicalSwitch and Summary.OpaqueNetworkId to a random uuid. // Name prefix: NSX, vcsim flag: -nsx - OpaqueNetwork int + OpaqueNetwork int `json:"opaqueNetwork"` // Host specifies the number of standalone HostSystems entities to create per Datacenter // Name prefix: H, vcsim flag: -standalone-host - Host int `json:",omitempty"` + Host int `json:"host,omitempty"` // Cluster specifies the number of ClusterComputeResource entities to create per Datacenter // Name prefix: C, vcsim flag: -cluster - Cluster int + Cluster int `json:"cluster"` // ClusterHost specifies the number of HostSystems entities to create within a Cluster // Name prefix: H, vcsim flag: -host - ClusterHost int `json:",omitempty"` + ClusterHost int `json:"clusterHost,omitempty"` // Pool specifies the number of ResourcePool entities to create per Cluster // Note that every cluster has a root ResourcePool named "Resources", as real vCenter does. @@ -110,13 +109,13 @@ type Model struct { // Note that this flag is not effective on standalone hosts. // For example: /DC0/host/DC0_C0/Resources/DC0_C0_RP1 // Name prefix: RP, vcsim flag: -pool - Pool int + Pool int `json:"pool"` // Datastore specifies the number of Datastore entities to create // Each Datastore will have temporary local file storage and will be mounted // on every HostSystem created by the ModelConfig // Name prefix: LocalDS, vcsim flag: -ds - Datastore int + Datastore int `json:"datastore"` // Machine specifies the number of VirtualMachine entities to create per // ResourcePool. If the pool flag is specified, the specified number of virtual @@ -125,21 +124,21 @@ type Model struct { // prefixed with RP0. On standalone hosts, machines are always deployed into the // root resource pool without any prefix. // Name prefix: VM, vcsim flag: -vm - Machine int + Machine int `json:"machine"` // Folder specifies the number of Datacenter to place within a Folder. // This includes a folder for the Datacenter itself and its host, vm, network and datastore folders. // All resources for the Datacenter are placed within these folders, rather than the top-level folders. // Name prefix: F, vcsim flag: -folder - Folder int + Folder int `json:"folder"` // App specifies the number of VirtualApp to create per Cluster // Name prefix: APP, vcsim flag: -app - App int + App int `json:"app"` // Pod specifies the number of StoragePod to create per Cluster // Name prefix: POD, vcsim flag: -pod - Pod int + Pod int `json:"pod"` // Delay configurations DelayConfig DelayConfig `json:"-"` @@ -368,7 +367,7 @@ func (m *Model) decode(path string, data interface{}) error { func (m *Model) loadMethod(obj mo.Reference, dir string) error { dir = filepath.Join(dir, obj.Reference().Encode()) - info, err := ioutil.ReadDir(dir) + info, err := os.ReadDir(dir) if err != nil { if os.IsNotExist(err) { return nil @@ -477,7 +476,10 @@ func (m *Model) Create() error { ctx := SpoofContext() m.Service = New(NewServiceInstance(ctx, m.ServiceContent, m.RootFolder)) ctx.Map = Map + return m.CreateInfrastructure(ctx) +} +func (m *Model) CreateInfrastructure(ctx *Context) error { client := m.Service.client root := object.NewRootFolder(client) @@ -492,7 +494,7 @@ func (m *Model) Create() error { // 1 NIC per VM, backed by a DVPG if Model.Portgroup > 0 vmnet := esx.EthernetCard.Backing - // addHost adds a cluster host or a stanalone host. + // addHost adds a cluster host or a standalone host. addHost := func(name string, f func(types.HostConnectSpec) (*object.Task, error)) (*object.HostSystem, error) { spec := types.HostConnectSpec{ HostName: name, @@ -820,7 +822,7 @@ func (m *Model) Create() error { } func (m *Model) createTempDir(dc string, name string) (string, error) { - dir, err := ioutil.TempDir("", fmt.Sprintf("govcsim-%s-%s-", dc, name)) + dir, err := os.MkdirTemp("", fmt.Sprintf("govcsim-%s-%s-", dc, name)) if err == nil { m.dirs = append(m.dirs, dir) } @@ -855,7 +857,7 @@ func (m *Model) Remove() { Map.m.Lock() for _, obj := range Map.objects { if vm, ok := obj.(*VirtualMachine); ok { - vm.run.remove(vm) + vm.svm.remove(SpoofContext()) } } Map.m.Unlock() @@ -876,9 +878,10 @@ func (m *Model) Run(f func(context.Context, *vim25.Client) error) error { if err != nil { return err } + // Only force TLS if the provided model didn't have any Service. + m.Service.TLS = new(tls.Config) } - m.Service.TLS = new(tls.Config) m.Service.RegisterEndpoints = true s := m.Service.NewServer() diff --git a/vendor/github.com/vmware/govmomi/simulator/option_manager.go b/vendor/github.com/vmware/govmomi/simulator/option_manager.go index efcdee2153e..1dd1688cd62 100644 --- a/vendor/github.com/vmware/govmomi/simulator/option_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/option_manager.go @@ -28,19 +28,45 @@ import ( "github.com/vmware/govmomi/vim25/types" ) +// OptionManager is used in at least two locations for ESX: +// 1. ServiceContent.setting - this is empty on ESX and //TODO on VC +// 2. ConfigManager.advancedOption - this is where the bulk of the ESX settings are found type OptionManager struct { mo.OptionManager + + // mirror is an array to keep in sync with OptionManager.Settings. Necessary because we use append. + // uni-directional - changes made to the mirrored array are not reflected back to Settings + mirror *[]types.BaseOptionValue +} + +func asOptionManager(ctx *Context, obj mo.Reference) (*OptionManager, bool) { + om, ok := ctx.Map.Get(obj.Reference()).(*OptionManager) + return om, ok } -func NewOptionManager(ref *types.ManagedObjectReference, setting []types.BaseOptionValue) object.Reference { +// NewOptionManager constructs the type. If mirror is non-nil it takes precedence over settings, and settings is ignored. +// Args: +// - ref - used to set OptionManager.Self if non-nil +// - setting - initial options, may be nil. +// - mirror - options array to keep updated with the OptionManager.Settings, may be nil. +func NewOptionManager(ref *types.ManagedObjectReference, setting []types.BaseOptionValue, mirror *[]types.BaseOptionValue) object.Reference { s := &OptionManager{} + + s.Setting = setting + if mirror != nil { + s.mirror = mirror + s.Setting = *mirror + } + if ref != nil { s.Self = *ref } - s.Setting = setting + return s } +// init constructs the OptionManager for ServiceContent.setting from the template directories. +// This does _not_ construct the OptionManager for ConfigManager.advancedOption. func (m *OptionManager) init(r *Registry) { if len(m.Setting) == 0 { if r.IsVPX() { @@ -103,6 +129,9 @@ func (m *OptionManager) UpdateOptions(req *types.UpdateOptions) soap.HasFault { } m.Setting = append(m.Setting, change) + if m.mirror != nil { + *m.mirror = m.Setting + } } body.Res = new(types.UpdateOptionsResponse) diff --git a/vendor/github.com/vmware/govmomi/simulator/ovf_manager.go b/vendor/github.com/vmware/govmomi/simulator/ovf_manager.go index 1540b4038e6..e9cbb8d2984 100644 --- a/vendor/github.com/vmware/govmomi/simulator/ovf_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/ovf_manager.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2019 VMware, Inc. All Rights Reserved. +Copyright (c) 2019-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -111,6 +111,7 @@ func (m *OvfManager) CreateImportSpec(ctx *Context, req *types.CreateImportSpec) ds := ctx.Map.Get(req.Datastore).(*Datastore) path := object.DatastorePath{Datastore: ds.Name} + vapp := &types.VAppConfigSpec{} spec := &types.VirtualMachineImportSpec{ ConfigSpec: types.VirtualMachineConfigSpec{ Name: req.Cisp.EntityName, @@ -122,10 +123,59 @@ func (m *OvfManager) CreateImportSpec(ctx *Context, req *types.CreateImportSpec) NumCPUs: 1, NumCoresPerSocket: 1, MemoryMB: 32, + VAppConfig: vapp, }, ResPoolEntity: &req.ResourcePool, } + index := 0 + for i, product := range env.VirtualSystem.Product { + vapp.Product = append(vapp.Product, types.VAppProductSpec{ + ArrayUpdateSpec: types.ArrayUpdateSpec{ + Operation: types.ArrayUpdateOperationAdd, + }, + Info: &types.VAppProductInfo{ + Key: int32(i), + ClassId: toString(product.Class), + InstanceId: toString(product.Instance), + Name: product.Product, + Vendor: product.Vendor, + Version: product.Version, + }, + }) + + for _, p := range product.Property { + key := product.Key(p) + val := "" + + for _, m := range req.Cisp.PropertyMapping { + if m.Key == key { + val = m.Value + } + } + + vapp.Property = append(vapp.Property, types.VAppPropertySpec{ + ArrayUpdateSpec: types.ArrayUpdateSpec{ + Operation: types.ArrayUpdateOperationAdd, + }, + Info: &types.VAppPropertyInfo{ + Key: int32(index), + ClassId: toString(product.Class), + InstanceId: toString(product.Instance), + Id: p.Key, + Category: product.Category, + Label: toString(p.Label), + Type: p.Type, + UserConfigurable: p.UserConfigurable, + DefaultValue: toString(p.Default), + Value: val, + Description: toString(p.Description), + }, + }) + index++ + } + } + if req.Cisp.DeploymentOption == "" && env.DeploymentOption != nil { for _, c := range env.DeploymentOption.Configuration { if isTrue(c.Default) { diff --git a/vendor/github.com/vmware/govmomi/simulator/performance_manager.go b/vendor/github.com/vmware/govmomi/simulator/performance_manager.go index 2bd8bf5f6f1..c64a336c21a 100644 --- a/vendor/github.com/vmware/govmomi/simulator/performance_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/performance_manager.go @@ -19,6 +19,7 @@ package simulator import ( "math/rand" "strconv" + "strings" "time" "github.com/vmware/govmomi/simulator/esx" @@ -56,12 +57,14 @@ type PerformanceManager struct { func (m *PerformanceManager) init(r *Registry) { if r.IsESX() { m.PerfCounter = esx.PerfCounter + m.HistoricalInterval = esx.HistoricalInterval m.hostMetrics = esx.HostMetrics m.vmMetrics = esx.VmMetrics m.rpMetrics = esx.ResourcePoolMetrics m.metricData = esx.MetricData } else { m.PerfCounter = vpx.PerfCounter + m.HistoricalInterval = vpx.HistoricalInterval m.hostMetrics = vpx.HostMetrics m.vmMetrics = vpx.VmMetrics m.rpMetrics = vpx.ResourcePoolMetrics @@ -174,9 +177,6 @@ func (p *PerformanceManager) QueryPerf(ctx *Context, req *types.QueryPerf) soap. body.Res.Returnval = make([]types.BasePerfEntityMetricBase, len(req.QuerySpec)) for i, qs := range req.QuerySpec { - metrics := new(types.PerfEntityMetric) - metrics.Entity = qs.Entity - // Get metric data for this entity type metricData, ok := p.metricData[qs.Entity.Type] if !ok { @@ -202,10 +202,13 @@ func (p *PerformanceManager) QueryPerf(ctx *Context, req *types.QueryPerf) soap. interval = 20 // TODO: Determine from entity type } n := 1 + int32(end.Sub(start).Seconds())/interval - if n > qs.MaxSample { + if qs.MaxSample > 0 && n > qs.MaxSample { n = qs.MaxSample } + metrics := new(types.PerfEntityMetric) + metrics.Entity = qs.Entity + // Loop through each interval "tick" metrics.SampleInfo = make([]types.PerfSampleInfo, n) metrics.Value = make([]types.BasePerfMetricSeries, len(qs.MetricId)) @@ -213,10 +216,11 @@ func (p *PerformanceManager) QueryPerf(ctx *Context, req *types.QueryPerf) soap. metrics.SampleInfo[tick] = types.PerfSampleInfo{Timestamp: end.Add(time.Duration(-interval*tick) * time.Second), Interval: interval} } + series := make([]*types.PerfMetricIntSeries, len(qs.MetricId)) for j, mid := range qs.MetricId { // Create list of metrics for this tick - series := &types.PerfMetricIntSeries{Value: make([]int64, n)} - series.Id = mid + series[j] = &types.PerfMetricIntSeries{Value: make([]int64, n)} + series[j].Id = mid points := metricData[mid.CounterId] offset := int64(start.Unix()) / int64(interval) @@ -237,11 +241,56 @@ func (p *PerformanceManager) QueryPerf(ctx *Context, req *types.QueryPerf) soap. } else { p = 0 } - series.Value[tick] = p + series[j].Value[tick] = p } - metrics.Value[j] = series + metrics.Value[j] = series[j] + } + + if qs.Format == string(types.PerfFormatCsv) { + metricsCsv := new(types.PerfEntityMetricCSV) + metricsCsv.Entity = qs.Entity + + //PerfSampleInfo encoded in the following CSV format: [interval1], [date1], [interval2], [date2], and so on. + metricsCsv.SampleInfoCSV = sampleInfoCSV(metrics) + metricsCsv.Value = make([]types.PerfMetricSeriesCSV, len(qs.MetricId)) + + for j, mid := range qs.MetricId { + seriesCsv := &types.PerfMetricSeriesCSV{Value: ""} + seriesCsv.Id = mid + seriesCsv.Value = valueCSV(series[j]) + metricsCsv.Value[j] = *seriesCsv + } + + body.Res.Returnval[i] = metricsCsv + } else { + body.Res.Returnval[i] = metrics } - body.Res.Returnval[i] = metrics } return body } + +// sampleInfoCSV converts the SampleInfo field to a CSV string +func sampleInfoCSV(m *types.PerfEntityMetric) string { + values := make([]string, len(m.SampleInfo)*2) + + i := 0 + for _, s := range m.SampleInfo { + values[i] = strconv.Itoa(int(s.Interval)) + i++ + values[i] = s.Timestamp.Format(time.RFC3339) + i++ + } + + return strings.Join(values, ",") +} + +// valueCSV converts the Value field to a CSV string +func valueCSV(s *types.PerfMetricIntSeries) string { + values := make([]string, len(s.Value)) + + for i := range s.Value { + values[i] = strconv.FormatInt(s.Value[i], 10) + } + + return strings.Join(values, ",") +} diff --git a/vendor/github.com/vmware/govmomi/simulator/portgroup.go b/vendor/github.com/vmware/govmomi/simulator/portgroup.go index a0973ae996d..d7b0b4d3547 100644 --- a/vendor/github.com/vmware/govmomi/simulator/portgroup.go +++ b/vendor/github.com/vmware/govmomi/simulator/portgroup.go @@ -27,6 +27,23 @@ type DistributedVirtualPortgroup struct { mo.DistributedVirtualPortgroup } +func (p *DistributedVirtualPortgroup) event(ctx *Context) types.DVPortgroupEvent { + dvs := ctx.Map.Get(*p.Config.DistributedVirtualSwitch).(*DistributedVirtualSwitch) + + return types.DVPortgroupEvent{ + Event: types.Event{ + Datacenter: datacenterEventArgument(p), + Net: &types.NetworkEventArgument{ + EntityEventArgument: types.EntityEventArgument{ + Name: p.Name, + }, + Network: p.Self, + }, + Dvs: dvs.eventArgument(), + }, + } +} + func (s *DistributedVirtualPortgroup) RenameTask(ctx *Context, req *types.Rename_Task) soap.HasFault { canDup := s.DistributedVirtualPortgroup.Config.BackingType == string(types.DistributedVirtualPortgroupBackingTypeNsx) @@ -66,6 +83,7 @@ func (s *DistributedVirtualPortgroup) DestroyTask(ctx *Context, req *types.Destr f := ctx.Map.getEntityParent(vswitch, "Folder").(*Folder) folderRemoveChild(ctx, &f.Folder, s.Reference()) + ctx.postEvent(&types.DVPortgroupDestroyedEvent{DVPortgroupEvent: s.event(ctx)}) return nil, nil }) diff --git a/vendor/github.com/vmware/govmomi/simulator/property_collector.go b/vendor/github.com/vmware/govmomi/simulator/property_collector.go index 44112b5a228..4f4b8124b70 100644 --- a/vendor/github.com/vmware/govmomi/simulator/property_collector.go +++ b/vendor/github.com/vmware/govmomi/simulator/property_collector.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -240,11 +240,24 @@ func isFalse(v *bool) bool { return v == nil || !*v } +func toString(v *string) string { + if v == nil { + return "" + } + return *v +} + func lcFirst(s string) string { + if len(s) < 1 { + return s + } return strings.ToLower(s[:1]) + s[1:] } func ucFirst(s string) string { + if len(s) < 1 { + return s + } return strings.ToUpper(s[:1]) + s[1:] } diff --git a/vendor/github.com/vmware/govmomi/simulator/registry.go b/vendor/github.com/vmware/govmomi/simulator/registry.go index c91af59e2a8..4b3e3306076 100644 --- a/vendor/github.com/vmware/govmomi/simulator/registry.go +++ b/vendor/github.com/vmware/govmomi/simulator/registry.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017-2021 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -577,8 +577,8 @@ func (r *Registry) MarshalJSON() ([]byte, error) { defer r.m.Unlock() vars := struct { - Objects int - Locks int + Objects int `json:"objects"` + Locks int `json:"locks"` }{ len(r.objects), len(r.locks), diff --git a/vendor/github.com/vmware/govmomi/simulator/resource_pool.go b/vendor/github.com/vmware/govmomi/simulator/resource_pool.go index a5f5a9aa25d..eeab93af74b 100644 --- a/vendor/github.com/vmware/govmomi/simulator/resource_pool.go +++ b/vendor/github.com/vmware/govmomi/simulator/resource_pool.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -217,59 +217,98 @@ func (p *ResourcePool) ImportVApp(ctx *Context, req *types.ImportVApp) soap.HasF folder = ctx.Map.Get(*req.Folder).(*Folder) } - res := folder.CreateVMTask(ctx, &types.CreateVM_Task{ - This: folder.Self, - Config: spec.ConfigSpec, - Pool: p.Self, - Host: req.Host, - }) + lease := newHttpNfcLease(ctx) + ref := lease.Reference() - ctask := ctx.Map.Get(res.(*methods.CreateVM_TaskBody).Res.Returnval).(*Task) - ctask.Wait() + CreateTask(p, "ImportVAppLRO", func(*Task) (types.AnyType, types.BaseMethodFault) { + if vapp, ok := spec.ConfigSpec.VAppConfig.(*types.VAppConfigSpec); ok { + for _, p := range vapp.Property { + if p.Info == nil || isTrue(p.Info.UserConfigurable) { + continue + } + + if p.Info.Value == "" || p.Info.Value == p.Info.DefaultValue { + continue + } + + fault := &types.NotUserConfigurableProperty{ + VAppPropertyFault: types.VAppPropertyFault{ + Id: p.Info.Id, + Category: p.Info.Category, + Label: p.Info.Label, + Type: p.Info.Type, + Value: p.Info.Value, + }, + } - if ctask.Info.Error != nil { - body.Fault_ = Fault("", ctask.Info.Error.Fault) - return body - } + lease.error(ctx, &types.LocalizedMethodFault{ + LocalizedMessage: fmt.Sprintf("Property %s.%s is not user configurable", p.Info.ClassId, p.Info.Id), + Fault: fault, + }) - lease := NewHttpNfcLease(ctx, ctask.Info.Result.(types.ManagedObjectReference)) - ref := lease.Reference() - lease.Info.Lease = ref - - vm := ctx.Map.Get(lease.Info.Entity).(*VirtualMachine) - device := object.VirtualDeviceList(vm.Config.Hardware.Device) - ndevice := make(map[string]int) - for _, d := range device { - info, ok := d.GetVirtualDevice().Backing.(types.BaseVirtualDeviceFileBackingInfo) - if !ok { - continue + return nil, fault + } } - var file object.DatastorePath - file.FromString(info.GetVirtualDeviceFileBackingInfo().FileName) - name := path.Base(file.Path) - ds := vm.findDatastore(file.Datastore) - lease.files[name] = path.Join(ds.Info.GetDatastoreInfo().Url, file.Path) - - _, disk := d.(*types.VirtualDisk) - kind := device.Type(d) - n := ndevice[kind] - ndevice[kind]++ - - lease.Info.DeviceUrl = append(lease.Info.DeviceUrl, types.HttpNfcLeaseDeviceUrl{ - Key: fmt.Sprintf("/%s/%s:%d", vm.Self.Value, kind, n), - ImportKey: fmt.Sprintf("/%s/%s:%d", vm.Name, kind, n), - Url: (&url.URL{ - Scheme: "https", - Host: "*", - Path: nfcPrefix + path.Join(ref.Value, name), - }).String(), - SslThumbprint: "", - Disk: types.NewBool(disk), - TargetId: name, - DatastoreKey: "", - FileSize: 0, + + res := folder.CreateVMTask(ctx, &types.CreateVM_Task{ + This: folder.Self, + Config: spec.ConfigSpec, + Pool: p.Self, + Host: req.Host, }) - } + + ctask := ctx.Map.Get(res.(*methods.CreateVM_TaskBody).Res.Returnval).(*Task) + ctask.Wait() + + if ctask.Info.Error != nil { + lease.error(ctx, ctask.Info.Error) + return nil, ctask.Info.Error.Fault + } + + mref := ctask.Info.Result.(types.ManagedObjectReference) + vm := ctx.Map.Get(mref).(*VirtualMachine) + device := object.VirtualDeviceList(vm.Config.Hardware.Device) + ndevice := make(map[string]int) + var urls []types.HttpNfcLeaseDeviceUrl + + for _, d := range device { + info, ok := d.GetVirtualDevice().Backing.(types.BaseVirtualDeviceFileBackingInfo) + if !ok { + continue + } + var file object.DatastorePath + file.FromString(info.GetVirtualDeviceFileBackingInfo().FileName) + name := path.Base(file.Path) + ds := vm.findDatastore(file.Datastore) + lease.files[name] = path.Join(ds.Info.GetDatastoreInfo().Url, file.Path) + + _, disk := d.(*types.VirtualDisk) + kind := device.Type(d) + n := ndevice[kind] + ndevice[kind]++ + + urls = append(urls, types.HttpNfcLeaseDeviceUrl{ + Key: fmt.Sprintf("/%s/%s:%d", vm.Self.Value, kind, n), + ImportKey: fmt.Sprintf("/%s/%s:%d", vm.Name, kind, n), + Url: (&url.URL{ + Scheme: "https", + Host: "*", + Path: nfcPrefix + path.Join(ref.Value, name), + }).String(), + SslThumbprint: "", + Disk: types.NewBool(disk), + TargetId: name, + DatastoreKey: "", + FileSize: 0, + }) + } + + lease.ready(ctx, mref, urls) + + // TODO: keep this task running until lease timeout or marked completed by the client + + return nil, nil + }).Run(ctx) body.Res = &types.ImportVAppResponse{ Returnval: ref, diff --git a/vendor/github.com/vmware/govmomi/simulator/search_index.go b/vendor/github.com/vmware/govmomi/simulator/search_index.go index 96e296274f8..79193862101 100644 --- a/vendor/github.com/vmware/govmomi/simulator/search_index.go +++ b/vendor/github.com/vmware/govmomi/simulator/search_index.go @@ -53,6 +53,14 @@ func (s *SearchIndex) FindByDatastorePath(r *types.FindByDatastorePath) soap.Has func (s *SearchIndex) FindByInventoryPath(req *types.FindByInventoryPath) soap.HasFault { body := &methods.FindByInventoryPathBody{Res: new(types.FindByInventoryPathResponse)} + root := Map.content().RootFolder + o := &root + + if req.InventoryPath == "/" { + body.Res.Returnval = o + return body + } + split := func(c rune) bool { return c == '/' } @@ -61,9 +69,6 @@ func (s *SearchIndex) FindByInventoryPath(req *types.FindByInventoryPath) soap.H return body } - root := Map.content().RootFolder - o := &root - for _, name := range path { f := s.FindChild(&types.FindChild{Entity: *o, Name: name}) diff --git a/vendor/github.com/vmware/govmomi/simulator/session_manager.go b/vendor/github.com/vmware/govmomi/simulator/session_manager.go index 169ea3c41c2..e9fbfcb6374 100644 --- a/vendor/github.com/vmware/govmomi/simulator/session_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/session_manager.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017-2018 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,6 +20,7 @@ import ( "context" "fmt" "net/http" + "net/url" "os" "reflect" "strings" @@ -41,6 +42,7 @@ type SessionManager struct { ServiceHostName string TLSCert func() string + ValidLogin func(*types.Login) bool sessions map[string]Session } @@ -106,22 +108,23 @@ func (m *SessionManager) putSession(s Session) { m.sessions[s.Key] = s } -func (s *SessionManager) validLogin(ctx *Context, req *types.Login) bool { - if ctx.Session != nil { - return false - } - user := ctx.svc.Listen.User - if user == nil || user == DefaultLogin { +func (s *SessionManager) Authenticate(u url.URL, req *types.Login) bool { + if u.User == nil || u.User == DefaultLogin { return req.UserName != "" && req.Password != "" } - pass, _ := user.Password() - return req.UserName == user.Username() && req.Password == pass + + if s.ValidLogin != nil { + return s.ValidLogin(req) + } + + pass, _ := u.User.Password() + return req.UserName == u.User.Username() && req.Password == pass } func (s *SessionManager) Login(ctx *Context, req *types.Login) soap.HasFault { body := new(methods.LoginBody) - if s.validLogin(ctx, req) { + if ctx.Session == nil && s.Authenticate(*ctx.svc.Listen, req) { body.Res = &types.LoginResponse{ Returnval: createSession(ctx, req.UserName, req.Locale), } diff --git a/vendor/github.com/vmware/govmomi/simulator/simulator.go b/vendor/github.com/vmware/govmomi/simulator/simulator.go index 673031fc950..0932a23a474 100644 --- a/vendor/github.com/vmware/govmomi/simulator/simulator.go +++ b/vendor/github.com/vmware/govmomi/simulator/simulator.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017-2018 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -26,7 +26,6 @@ import ( "encoding/pem" "fmt" "io" - "io/ioutil" "log" "net" "net/http" @@ -98,7 +97,7 @@ type Server struct { // New returns an initialized simulator Service instance func New(instance *ServiceInstance) *Service { s := &Service{ - readAll: ioutil.ReadAll, + readAll: io.ReadAll, sm: Map.SessionManager(), sdk: make(map[string]*Registry), } @@ -241,11 +240,14 @@ func (s *Service) RoundTrip(ctx context.Context, request, response soap.HasFault // Every request has a "This" field. this := req.Elem().FieldByName("This") + // Copy request body + body := reflect.New(req.Type().Elem()) + deepCopy(req.Interface(), body.Interface()) method := &Method{ Name: req.Elem().Type().Name(), This: this.Interface().(types.ManagedObjectReference), - Body: req.Interface(), + Body: body.Interface(), } res := s.call(&Context{ @@ -338,8 +340,8 @@ func (r *response) MarshalXML(e *xml.Encoder, start xml.StartElement) error { // About generates some info about the simulator. func (s *Service) About(w http.ResponseWriter, r *http.Request) { var about struct { - Methods []string - Types []string + Methods []string `json:"methods"` + Types []string `json:"types"` } seen := make(map[string]bool) @@ -421,7 +423,9 @@ func (s *Service) HandleFunc(pattern string, handler func(http.ResponseWriter, * // RegisterSDK adds an HTTP handler for the Registry's Path and Namespace. // If r.Path is already registered, r's objects are added to the existing Registry. -func (s *Service) RegisterSDK(r *Registry) { +// An optional set of aliases can be provided to register the same handler for +// multiple paths. +func (s *Service) RegisterSDK(r *Registry, alias ...string) { if existing, ok := s.sdk[r.Path]; ok { for id, obj := range r.objects { existing.objects[id] = obj @@ -435,6 +439,11 @@ func (s *Service) RegisterSDK(r *Registry) { s.sdk[r.Path] = r s.ServeMux.HandleFunc(r.Path, s.ServeSDK) + + for _, p := range alias { + s.sdk[p] = r + s.ServeMux.HandleFunc(p, s.ServeSDK) + } } // StatusSDK can be used to simulate an /sdk HTTP response code other than 200. @@ -654,12 +663,9 @@ func defaultIP(addr *net.TCPAddr) string { // NewServer returns an http Server instance for the given service func (s *Service) NewServer() *Server { - s.RegisterSDK(Map) + s.RegisterSDK(Map, Map.Path+"/vimService") mux := s.ServeMux - vim := Map.Path + "/vimService" - s.sdk[vim] = s.sdk[vim25.Path] - mux.HandleFunc(vim, s.ServeSDK) mux.HandleFunc(Map.Path+"/vimServiceVersions.xml", s.ServiceVersions) mux.HandleFunc(folderPrefix, s.ServeDatastore) mux.HandleFunc(guestPrefix, ServeGuest) @@ -768,7 +774,7 @@ func (s *Server) CertificateFile() (string, error) { return s.caFile, nil } - f, err := ioutil.TempFile("", "vcsim-") + f, err := os.CreateTemp("", "vcsim-") if err != nil { return "", err } diff --git a/vendor/github.com/vmware/govmomi/simulator/snapshot.go b/vendor/github.com/vmware/govmomi/simulator/snapshot.go index bb1b66f6ffe..84e404279b7 100644 --- a/vendor/github.com/vmware/govmomi/simulator/snapshot.go +++ b/vendor/github.com/vmware/govmomi/simulator/snapshot.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -30,6 +30,7 @@ import ( type VirtualMachineSnapshot struct { mo.VirtualMachineSnapshot + DataSets map[string]*DataSet } func (v *VirtualMachineSnapshot) createSnapshotFiles() types.BaseMethodFault { @@ -110,7 +111,7 @@ func (v *VirtualMachineSnapshot) removeSnapshotFiles(ctx *Context) types.BaseMet } func (v *VirtualMachineSnapshot) RemoveSnapshotTask(ctx *Context, req *types.RemoveSnapshot_Task) soap.HasFault { - task := CreateTask(v, "removeSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) { + task := CreateTask(v.Vm, "removeSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) { var changes []types.PropertyChange vm := ctx.Map.Get(v.Vm).(*VirtualMachine) @@ -158,6 +159,7 @@ func (v *VirtualMachineSnapshot) RevertToSnapshotTask(ctx *Context, req *types.R vm := ctx.Map.Get(v.Vm).(*VirtualMachine) ctx.WithLock(vm, func() { + vm.DataSets = copyDataSetsForVmClone(v.DataSets) ctx.Map.Update(vm, []types.PropertyChange{ {Name: "snapshot.currentSnapshot", Val: v.Self}, }) diff --git a/vendor/github.com/vmware/govmomi/simulator/task.go b/vendor/github.com/vmware/govmomi/simulator/task.go index bd43f7420b9..73c52b919cb 100644 --- a/vendor/github.com/vmware/govmomi/simulator/task.go +++ b/vendor/github.com/vmware/govmomi/simulator/task.go @@ -110,10 +110,21 @@ func (t *Task) Run(ctx *Context) types.ManagedObjectReference { // in most cases, the caller already holds this lock, and we would like // the lock to be held across the "hand off" to the async goroutine. - unlock := vimMap.AcquireLock(ctx, tr) - + // however, with a TaskDelay, PropertyCollector (for example) cannot read + // any object properties while the lock is held. + handoff := true + if v, ok := TaskDelay.MethodDelay["LockHandoff"]; ok { + handoff = v != 0 + } + var unlock func() + if handoff { + unlock = vimMap.AcquireLock(ctx, tr) + } go func() { TaskDelay.delay(t.Info.Name) + if !handoff { + unlock = vimMap.AcquireLock(ctx, tr) + } res, err := t.Execute(t) unlock() diff --git a/vendor/github.com/vmware/govmomi/simulator/view_manager.go b/vendor/github.com/vmware/govmomi/simulator/view_manager.go index 62d91bcc479..94e1d5265c2 100644 --- a/vendor/github.com/vmware/govmomi/simulator/view_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/view_manager.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -154,6 +154,8 @@ func walk(root mo.Reference, f func(child types.ManagedObjectReference)) { children = []types.ManagedObjectReference{e.VmFolder, e.HostFolder, e.DatastoreFolder, e.NetworkFolder} case *mo.Folder: children = e.ChildEntity + case *mo.StoragePod: + children = e.ChildEntity case *mo.ComputeResource: children = e.Host children = append(children, *e.ResourcePool) @@ -225,8 +227,8 @@ func (m *ViewManager) CreateListView(ctx *Context, req *types.CreateListView) so body := new(methods.CreateListViewBody) list := new(ListView) - if err := list.add(req.Obj); err != nil { - body.Fault_ = Fault("", err) + if refs := list.add(ctx, req.Obj); len(refs) != 0 { + body.Fault_ = Fault("", &types.ManagedObjectNotFound{Obj: refs[0]}) return body } @@ -243,19 +245,20 @@ type ListView struct { mo.ListView } -func (v *ListView) update() { - Map.Update(v, []types.PropertyChange{{Name: "view", Val: v.View}}) +func (v *ListView) update(ctx *Context) { + ctx.Map.Update(v, []types.PropertyChange{{Name: "view", Val: v.View}}) } -func (v *ListView) add(refs []types.ManagedObjectReference) *types.ManagedObjectNotFound { +func (v *ListView) add(ctx *Context, refs []types.ManagedObjectReference) []types.ManagedObjectReference { + var unresolved []types.ManagedObjectReference for _, ref := range refs { - obj := Map.Get(ref) + obj := ctx.Session.Get(ref) if obj == nil { - return &types.ManagedObjectNotFound{Obj: ref} + unresolved = append(unresolved, ref) } v.View = append(v.View, ref) } - return nil + return unresolved } func (v *ListView) DestroyView(ctx *Context, c *types.DestroyView) soap.HasFault { @@ -263,40 +266,37 @@ func (v *ListView) DestroyView(ctx *Context, c *types.DestroyView) soap.HasFault return destroyView(c.This) } -func (v *ListView) ModifyListView(req *types.ModifyListView) soap.HasFault { - body := new(methods.ModifyListViewBody) +func (v *ListView) ModifyListView(ctx *Context, req *types.ModifyListView) soap.HasFault { + body := &methods.ModifyListViewBody{ + Res: new(types.ModifyListViewResponse), + } + + body.Res.Returnval = v.add(ctx, req.Add) for _, ref := range req.Remove { RemoveReference(&v.View, ref) + if ctx.Map.Get(ref) == nil { + body.Res.Returnval = append(body.Res.Returnval, ref) + } } - if err := v.add(req.Add); err != nil { - body.Fault_ = Fault("", err) - return body - } - - body.Res = new(types.ModifyListViewResponse) - if len(req.Remove) != 0 || len(req.Add) != 0 { - v.update() + v.update(ctx) } return body } -func (v *ListView) ResetListView(req *types.ResetListView) soap.HasFault { - body := new(methods.ResetListViewBody) +func (v *ListView) ResetListView(ctx *Context, req *types.ResetListView) soap.HasFault { + body := &methods.ResetListViewBody{ + Res: new(types.ResetListViewResponse), + } v.View = nil - if err := v.add(req.Obj); err != nil { - body.Fault_ = Fault("", err) - return body - } - - body.Res = new(types.ResetListViewResponse) + body.Res.Returnval = v.add(ctx, req.Obj) - v.update() + v.update(ctx) return body } diff --git a/vendor/github.com/vmware/govmomi/simulator/virtual_machine.go b/vendor/github.com/vmware/govmomi/simulator/virtual_machine.go index 8deeceda7ac..98af0865ca0 100644 --- a/vendor/github.com/vmware/govmomi/simulator/virtual_machine.go +++ b/vendor/github.com/vmware/govmomi/simulator/virtual_machine.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017-2018 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -19,7 +19,6 @@ package simulator import ( "bytes" "fmt" - "io/ioutil" "log" "net" "os" @@ -43,10 +42,11 @@ import ( type VirtualMachine struct { mo.VirtualMachine + DataSets map[string]*DataSet log string sid int32 - run container + svm *simVM uid uuid.UUID imc *types.CustomizationSpec } @@ -141,6 +141,7 @@ func NewVirtualMachine(ctx *Context, parent types.ManagedObjectReference, spec * InstanceUuid: newUUID(strings.ToUpper(spec.Files.VmPathName)), Version: esx.HardwareVersion, Firmware: string(types.GuestOsDescriptorFirmwareTypeBios), + VAppConfig: spec.VAppConfig, Files: &types.VirtualMachineFileInfo{ SnapshotDirectory: dsPath, SuspendDirectory: dsPath, @@ -165,6 +166,7 @@ func NewVirtualMachine(ctx *Context, parent types.ManagedObjectReference, spec * vm.Summary.QuickStats.GuestHeartbeatStatus = types.ManagedEntityStatusGray vm.Summary.OverallStatus = types.ManagedEntityStatusGreen vm.ConfigStatus = types.ManagedEntityStatusGreen + vm.DataSets = make(map[string]*DataSet) // put vm in the folder only if no errors occurred f, _ := asFolderMO(folder) @@ -336,18 +338,20 @@ func (vm *VirtualMachine) apply(spec *types.VirtualMachineConfigSpec) { // updateVAppProperty updates the simulator VM with the specified VApp properties. func (vm *VirtualMachine) updateVAppProperty(spec *types.VmConfigSpec) types.BaseMethodFault { - ps := make([]types.VAppPropertyInfo, 0) - - if vm.Config.VAppConfig != nil && vm.Config.VAppConfig.GetVmConfigInfo() != nil { - ps = vm.Config.VAppConfig.GetVmConfigInfo().Property + if vm.Config.VAppConfig == nil { + vm.Config.VAppConfig = &types.VmConfigInfo{} } + info := vm.Config.VAppConfig.GetVmConfigInfo() + propertyInfo := info.Property + productInfo := info.Product + for _, prop := range spec.Property { var foundIndex int exists := false // Check if the specified property exists or not. This helps rejecting invalid // operations (e.g., Adding a VApp property that already exists) - for i, p := range ps { + for i, p := range propertyInfo { if p.Key == prop.Info.Key { exists = true foundIndex = i @@ -360,25 +364,54 @@ func (vm *VirtualMachine) updateVAppProperty(spec *types.VmConfigSpec) types.Bas if exists { return new(types.InvalidArgument) } - ps = append(ps, *prop.Info) + propertyInfo = append(propertyInfo, *prop.Info) case types.ArrayUpdateOperationEdit: if !exists { return new(types.InvalidArgument) } - ps[foundIndex] = *prop.Info + propertyInfo[foundIndex] = *prop.Info case types.ArrayUpdateOperationRemove: if !exists { return new(types.InvalidArgument) } - ps = append(ps[:foundIndex], ps[foundIndex+1:]...) + propertyInfo = append(propertyInfo[:foundIndex], propertyInfo[foundIndex+1:]...) } } - if vm.Config.VAppConfig == nil { - vm.Config.VAppConfig = &types.VmConfigInfo{} + for _, prod := range spec.Product { + var foundIndex int + exists := false + // Check if the specified product exists or not. This helps rejecting invalid + // operations (e.g., Adding a VApp product that already exists) + for i, p := range productInfo { + if p.Key == prod.Info.Key { + exists = true + foundIndex = i + break + } + } + + switch prod.Operation { + case types.ArrayUpdateOperationAdd: + if exists { + return new(types.InvalidArgument) + } + productInfo = append(productInfo, *prod.Info) + case types.ArrayUpdateOperationEdit: + if !exists { + return new(types.InvalidArgument) + } + productInfo[foundIndex] = *prod.Info + case types.ArrayUpdateOperationRemove: + if !exists { + return new(types.InvalidArgument) + } + productInfo = append(productInfo[:foundIndex], productInfo[foundIndex+1:]...) + } } - vm.Config.VAppConfig.GetVmConfigInfo().Property = ps + info.Product = productInfo + info.Property = propertyInfo return nil } @@ -394,13 +427,46 @@ func extraConfigKey(key string) string { return key } -func (vm *VirtualMachine) applyExtraConfig(spec *types.VirtualMachineConfigSpec) { +func (vm *VirtualMachine) applyExtraConfig(ctx *Context, spec *types.VirtualMachineConfigSpec) types.BaseMethodFault { + var removedContainerBacking bool var changes []types.PropertyChange for _, c := range spec.ExtraConfig { val := c.GetOptionValue() key := strings.TrimPrefix(extraConfigKey(val.Key), "SET.") if key == val.Key { - vm.Config.ExtraConfig = append(vm.Config.ExtraConfig, c) + keyIndex := -1 + for i := range vm.Config.ExtraConfig { + bov := vm.Config.ExtraConfig[i] + if bov == nil { + continue + } + ov := bov.GetOptionValue() + if ov == nil { + continue + } + if ov.Key == key { + keyIndex = i + break + } + } + if keyIndex < 0 { + vm.Config.ExtraConfig = append(vm.Config.ExtraConfig, c) + } else { + if s, ok := val.Value.(string); ok && s == "" { + if key == ContainerBackingOptionKey { + removedContainerBacking = true + } + // Remove existing element + l := len(vm.Config.ExtraConfig) + vm.Config.ExtraConfig[keyIndex] = vm.Config.ExtraConfig[l-1] + vm.Config.ExtraConfig[l-1] = nil + vm.Config.ExtraConfig = vm.Config.ExtraConfig[:l-1] + } else { + // Update existing element + vm.Config.ExtraConfig[keyIndex].GetOptionValue().Value = val.Value + } + } + continue } changes = append(changes, types.PropertyChange{Name: key, Val: val.Value}) @@ -421,9 +487,52 @@ func (vm *VirtualMachine) applyExtraConfig(spec *types.VirtualMachineConfigSpec) ) } } + + // create the container backing before we publish the updates so the simVM is available before handlers + // get triggered + var fault types.BaseMethodFault + if vm.svm == nil { + vm.svm = createSimulationVM(vm) + + // check to see if the VM is already powered on - if so we need to retroactively hit that path here + if vm.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOn { + err := vm.svm.start(ctx) + if err != nil { + // don't attempt to undo the changes already made - just return an error + // we'll retry the svm.start operation on pause/restart calls + fault = &types.VAppConfigFault{ + VimFault: types.VimFault{ + MethodFault: types.MethodFault{ + FaultCause: &types.LocalizedMethodFault{ + Fault: &types.SystemErrorFault{Reason: err.Error()}, + LocalizedMessage: err.Error()}}}} + } + } + } else if removedContainerBacking { + err := vm.svm.remove(ctx) + if err == nil { + // remove link from container to VM so callbacks no longer reflect state + vm.svm.vm = nil + // nil container backing reference to return this to a pure in-mem simulated VM + vm.svm = nil + + } else { + // don't attempt to undo the changes already made - just return an error + // we'll retry the svm.start operation on pause/restart calls + fault = &types.VAppConfigFault{ + VimFault: types.VimFault{ + MethodFault: types.MethodFault{ + FaultCause: &types.LocalizedMethodFault{ + Fault: &types.SystemErrorFault{Reason: err.Error()}, + LocalizedMessage: err.Error()}}}} + } + } + if len(changes) != 0 { Map.Update(vm, changes) } + + return fault } func validateGuestID(id string) types.BaseMethodFault { @@ -838,7 +947,7 @@ func (vm *VirtualMachine) RefreshStorageInfo(ctx *Context, req *types.RefreshSto continue } - files, err := ioutil.ReadDir(directory) + files, err := os.ReadDir(directory) if err != nil { body.Fault_ = Fault("", ctx.Map.FileManager().fault(directory, err, new(types.CannotAccessFile))) return body @@ -849,8 +958,8 @@ func (vm *VirtualMachine) RefreshStorageInfo(ctx *Context, req *types.RefreshSto Datastore: p.Datastore, Path: strings.TrimPrefix(file.Name(), datastore.Info.GetDatastoreInfo().Url), } - - vm.addFileLayoutEx(datastorePath, file.Size()) + info, _ := file.Info() + vm.addFileLayoutEx(datastorePath, info.Size()) } } @@ -1022,8 +1131,9 @@ var vmwOUI = net.HardwareAddr([]byte{0x0, 0xc, 0x29}) // From http://pubs.vmware.com/vsphere-60/index.jsp?topic=%2Fcom.vmware.vsphere.networking.doc%2FGUID-DC7478FF-DC44-4625-9AD7-38208C56A552.html // "The host generates generateMAC addresses that consists of the VMware OUI 00:0C:29 and the last three octets in hexadecimal -// format of the virtual machine UUID. The virtual machine UUID is based on a hash calculated by using the UUID of the -// ESXi physical machine and the path to the configuration file (.vmx) of the virtual machine." +// +// format of the virtual machine UUID. The virtual machine UUID is based on a hash calculated by using the UUID of the +// ESXi physical machine and the path to the configuration file (.vmx) of the virtual machine." func (vm *VirtualMachine) generateMAC(unit int32) string { id := []byte(vm.Config.Uuid) @@ -1465,6 +1575,7 @@ func (vm *VirtualMachine) genVmdkPath(p object.DatastorePath) (string, types.Bas func (vm *VirtualMachine) configureDevices(ctx *Context, spec *types.VirtualMachineConfigSpec) types.BaseMethodFault { devices := object.VirtualDeviceList(vm.Config.Hardware.Device) + var err types.BaseMethodFault for i, change := range spec.DeviceChange { dspec := change.GetVirtualDeviceConfigSpec() device := dspec.Device.GetVirtualDevice() @@ -1501,7 +1612,7 @@ func (vm *VirtualMachine) configureDevices(ctx *Context, spec *types.VirtualMach } key := device.Key - err := vm.configureDevice(ctx, devices, dspec, nil) + err = vm.configureDevice(ctx, devices, dspec, nil) if err != nil { return err } @@ -1528,7 +1639,7 @@ func (vm *VirtualMachine) configureDevices(ctx *Context, spec *types.VirtualMach device.DeviceInfo.GetDescription().Summary = "" // regenerate summary } - err := vm.configureDevice(ctx, devices, dspec, oldDevice) + err = vm.configureDevice(ctx, devices, dspec, oldDevice) if err != nil { return err } @@ -1543,9 +1654,16 @@ func (vm *VirtualMachine) configureDevices(ctx *Context, spec *types.VirtualMach {Name: "config.hardware.device", Val: []types.BaseVirtualDevice(devices)}, }) - vm.updateDiskLayouts() + err = vm.updateDiskLayouts() + if err != nil { + return err + } - vm.applyExtraConfig(spec) // Do this after device config, as some may apply to the devices themselves (e.g. ethernet -> guest.net) + // Do this after device config, as some may apply to the devices themselves (e.g. ethernet -> guest.net) + err = vm.applyExtraConfig(ctx, spec) + if err != nil { + return err + } return nil } @@ -1580,14 +1698,23 @@ func (c *powerVMTask) Run(task *Task) (types.AnyType, types.BaseMethodFault) { return nil, new(types.InvalidState) } - c.run.start(c.ctx, c.VirtualMachine) + err := c.svm.start(c.ctx) + if err != nil { + return nil, &types.MissingPowerOnConfiguration{ + VAppConfigFault: types.VAppConfigFault{ + VimFault: types.VimFault{ + MethodFault: types.MethodFault{ + FaultCause: &types.LocalizedMethodFault{ + Fault: &types.SystemErrorFault{Reason: err.Error()}, + LocalizedMessage: err.Error()}}}}} + } c.ctx.postEvent( &types.VmStartingEvent{VmEvent: event}, &types.VmPoweredOnEvent{VmEvent: event}, ) c.customize(c.ctx) case types.VirtualMachinePowerStatePoweredOff: - c.run.stop(c.ctx, c.VirtualMachine) + c.svm.stop(c.ctx) c.ctx.postEvent( &types.VmStoppingEvent{VmEvent: event}, &types.VmPoweredOffEvent{VmEvent: event}, @@ -1600,7 +1727,7 @@ func (c *powerVMTask) Run(task *Task) (types.AnyType, types.BaseMethodFault) { } } - c.run.pause(c.ctx, c.VirtualMachine) + c.svm.pause(c.ctx) c.ctx.postEvent( &types.VmSuspendingEvent{VmEvent: event}, &types.VmSuspendedEvent{VmEvent: event}, @@ -1707,7 +1834,7 @@ func (vm *VirtualMachine) RebootGuest(ctx *Context, req *types.RebootGuest) soap } if vm.Guest.ToolsRunningStatus == string(types.VirtualMachineToolsRunningStatusGuestToolsRunning) { - vm.run.restart(ctx, vm) + vm.svm.restart(ctx) body.Res = new(types.RebootGuestResponse) } else { body.Fault_ = Fault("", new(types.ToolsUnavailable)) @@ -1771,6 +1898,7 @@ func (vm *VirtualMachine) DestroyTask(ctx *Context, req *types.Destroy_Task) soa task := CreateTask(vm, "destroy", func(t *Task) (types.AnyType, types.BaseMethodFault) { if dc == nil { return nil, &types.ManagedObjectNotFound{Obj: vm.Self} // If our Parent was destroyed, so were we. + // TODO: should this also trigger container removal? } r := vm.UnregisterVM(ctx, &types.UnregisterVM{ @@ -1795,7 +1923,14 @@ func (vm *VirtualMachine) DestroyTask(ctx *Context, req *types.Destroy_Task) soa Datacenter: &dc.Self, }) - vm.run.remove(vm) + err := vm.svm.remove(ctx) + if err != nil { + return nil, &types.RuntimeFault{ + MethodFault: types.MethodFault{ + FaultCause: &types.LocalizedMethodFault{ + Fault: &types.SystemErrorFault{Reason: err.Error()}, + LocalizedMessage: err.Error()}}} + } return nil, nil }) @@ -1909,6 +2044,7 @@ func (vm *VirtualMachine) CloneVMTask(ctx *Context, req *types.CloneVM_Task) soa } config := types.VirtualMachineConfigSpec{ Name: req.Name, + Version: vm.Config.Version, GuestId: vm.Config.GuestId, Files: &types.VirtualMachineFileInfo{ VmPathName: vmx.String(), @@ -1973,6 +2109,7 @@ func (vm *VirtualMachine) CloneVMTask(ctx *Context, req *types.CloneVM_Task) soa if req.Spec.Config != nil && req.Spec.Config.DeviceChange != nil { clone.configureDevices(ctx, &types.VirtualMachineConfigSpec{DeviceChange: req.Spec.Config.DeviceChange}) } + clone.DataSets = copyDataSetsForVmClone(vm.DataSets) if req.Spec.Template { _ = clone.MarkAsTemplate(&types.MarkAsTemplate{This: clone.Self}) @@ -2178,6 +2315,7 @@ func (vm *VirtualMachine) CreateSnapshotTask(ctx *Context, req *types.CreateSnap snapshot := &VirtualMachineSnapshot{} snapshot.Vm = vm.Reference() snapshot.Config = *vm.Config + snapshot.DataSets = copyDataSetsForVmClone(vm.DataSets) ctx.Map.Put(snapshot) @@ -2235,8 +2373,10 @@ func (vm *VirtualMachine) RevertToCurrentSnapshotTask(ctx *Context, req *types.R return body } + snapshot := ctx.Map.Get(*vm.Snapshot.CurrentSnapshot).(*VirtualMachineSnapshot) task := CreateTask(vm, "revertSnapshot", func(t *Task) (types.AnyType, types.BaseMethodFault) { + vm.DataSets = copyDataSetsForVmClone(snapshot.DataSets) return nil, nil }) @@ -2277,8 +2417,8 @@ func (vm *VirtualMachine) RemoveAllSnapshotsTask(ctx *Context, req *types.Remove func (vm *VirtualMachine) ShutdownGuest(ctx *Context, c *types.ShutdownGuest) soap.HasFault { r := &methods.ShutdownGuestBody{} - // should be poweron - if vm.Runtime.PowerState == types.VirtualMachinePowerStatePoweredOff { + + if vm.Runtime.PowerState != types.VirtualMachinePowerStatePoweredOn { r.Fault_ = Fault("", &types.InvalidPowerState{ RequestedState: types.VirtualMachinePowerStatePoweredOn, ExistingState: vm.Runtime.PowerState, @@ -2286,27 +2426,61 @@ func (vm *VirtualMachine) ShutdownGuest(ctx *Context, c *types.ShutdownGuest) so return r } - // change state - vm.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff - vm.Summary.Runtime.PowerState = types.VirtualMachinePowerStatePoweredOff event := vm.event() - ctx.postEvent( - &types.VmGuestShutdownEvent{VmEvent: event}, - &types.VmPoweredOffEvent{VmEvent: event}, - ) - vm.run.stop(ctx, vm) + ctx.postEvent(&types.VmGuestShutdownEvent{VmEvent: event}) - ctx.Map.Update(vm, []types.PropertyChange{ - {Name: "runtime.powerState", Val: types.VirtualMachinePowerStatePoweredOff}, - {Name: "summary.runtime.powerState", Val: types.VirtualMachinePowerStatePoweredOff}, - }) + _ = CreateTask(vm, "shutdownGuest", func(*Task) (types.AnyType, types.BaseMethodFault) { + vm.svm.stop(ctx) + + ctx.Map.Update(vm, []types.PropertyChange{ + {Name: "runtime.powerState", Val: types.VirtualMachinePowerStatePoweredOff}, + {Name: "summary.runtime.powerState", Val: types.VirtualMachinePowerStatePoweredOff}, + }) + + ctx.postEvent(&types.VmPoweredOffEvent{VmEvent: event}) + + return nil, nil + }).Run(ctx) r.Res = new(types.ShutdownGuestResponse) return r } +func (vm *VirtualMachine) StandbyGuest(ctx *Context, c *types.StandbyGuest) soap.HasFault { + r := &methods.StandbyGuestBody{} + + if vm.Runtime.PowerState != types.VirtualMachinePowerStatePoweredOn { + r.Fault_ = Fault("", &types.InvalidPowerState{ + RequestedState: types.VirtualMachinePowerStatePoweredOn, + ExistingState: vm.Runtime.PowerState, + }) + + return r + } + + event := vm.event() + ctx.postEvent(&types.VmGuestStandbyEvent{VmEvent: event}) + + _ = CreateTask(vm, "standbyGuest", func(*Task) (types.AnyType, types.BaseMethodFault) { + vm.svm.pause(ctx) + + ctx.Map.Update(vm, []types.PropertyChange{ + {Name: "runtime.powerState", Val: types.VirtualMachinePowerStateSuspended}, + {Name: "summary.runtime.powerState", Val: types.VirtualMachinePowerStateSuspended}, + }) + + ctx.postEvent(&types.VmSuspendedEvent{VmEvent: event}) + + return nil, nil + }).Run(ctx) + + r.Res = new(types.StandbyGuestResponse) + + return r +} + func (vm *VirtualMachine) MarkAsTemplate(req *types.MarkAsTemplate) soap.HasFault { r := &methods.MarkAsTemplateBody{} diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/performance_manager.go b/vendor/github.com/vmware/govmomi/simulator/vpx/performance_manager.go index 11ca6839de3..9b50f1b81f1 100644 --- a/vendor/github.com/vmware/govmomi/simulator/vpx/performance_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/vpx/performance_manager.go @@ -18,6 +18,45 @@ package vpx import "github.com/vmware/govmomi/vim25/types" +// HistoricalInterval is the default template for the PerformanceManager historicalInterval property. +// Capture method: +// +// govc object.collect -s -dump PerformanceManager:Perfmgr historicalInterval +var HistoricalInterval = []types.PerfInterval{ + { + Enabled: true, + Key: 1, + Length: 86400, + Level: 1, + Name: "Past Day", + SamplingPeriod: 300, + }, + { + Enabled: true, + Key: 2, + Length: 604800, + Level: 1, + Name: "Past Week", + SamplingPeriod: 1800, + }, + { + Enabled: true, + Key: 1, + Length: 2592000, + Level: 1, + Name: "Past Month", + SamplingPeriod: 7200, + }, + { + Enabled: true, + Key: 1, + Length: 31536000, + Level: 1, + Name: "Past Year", + SamplingPeriod: 86400, + }, +} + // PerfCounter is the default template for the PerformanceManager perfCounter property. // Capture method: // govc object.collect -s -dump PerformanceManager:PerfMgr perfCounter diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/performance_manager_data.go b/vendor/github.com/vmware/govmomi/simulator/vpx/performance_manager_data.go index 3c42c5350e2..8fc34960ff9 100644 --- a/vendor/github.com/vmware/govmomi/simulator/vpx/performance_manager_data.go +++ b/vendor/github.com/vmware/govmomi/simulator/vpx/performance_manager_data.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -49,10 +49,10 @@ var VmMetricData = map[int32][]int64{ 185, 189, 134, 130, 160, 122, 84, 113, 153, 95, 110, 141, 91, 108, 130, 3372, 1942, 151, 102, 158, 162, 100, 143, 122, 109, 211, 229, 173, 187, 237, 200, 205, 241, 184, 204, 217, 182, 195, 219, 213, 211, 214, 189, 182, 245, 2671, 612, 1055, 595, 644, 747, 611, 336, 244, 118, 113, 128, 93, 94, 130, 359, 131, 151, 94, 137, 149, 106, 109, 127, 124}, - 70: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 70: []int64{91, 585, 246, 114, 553, 348, 824, 848, 827, 882, 632, 500, 647, 805, 425, 971, 789, 1001, 910, 1013, 338, 713, 496, 168, 201, 886, 124, 968, 768, 736, + 612, 859, 973, 64, 312, 449, 38, 839, 807, 571, 83, 862, 1015, 333, 818, 173, 396, 520, 171, 678, 160, 203, 991, 549, 776, 524, 390, 228, 576, 307, + 1005, 93, 893, 475, 451, 141, 98, 439, 95, 104, 739, 630, 275, 701, 722, 16, 207, 468, 310, 387, 217, 377, 684, 969, 396, 1010, 866, 914, 181, 621, 995, + 831, 278, 530, 465, 745, 704, 762, 545, 544}, 473: []int64{30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 27, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, @@ -113,10 +113,13 @@ var VmMetricData = map[int32][]int64{ 20, 20, 20, 25, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 21, 21, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 24, 20, 21, 20, 20, 20, 20, 20, 21, 20, 21, 20, 20, 20, 21, 20, 20, 20, 20, 20, 23, 20, 20, 20, 20, 20, 20, 21, 20, 20, 20, 20, 20, 21, 20, 20, 20}, - 410: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 410: []int64{976, 899, 657, 904, 171, 606, 607, 707, 823, 331, 255, 421, 230, 1001, + 937, 467, 738, 287, 904, 962, 518, 391, 593, 593, 59, 874, 364, 873, 728, 727, 533, + 328, 957, 637, 973, 1014, 259, 160, 698, 589, 933, 283, 385, 393, 129, 414, 16, 800, + 105, 150, 905, 278, 131, 115, 678, 738, 444, 411, 388, 402, 541, 428, 970, 260, 56, + 794, 975, 480, 644, 110, 702, 93, 240, 322, 651, 370, 261, 589, 72, 259, 405, 965, + 927, 519, 210, 291, 688, 758, 942, 301, 253, 605, 677, 995, 509, 478, 646, 3, 472, 1007, + }, 505: []int64{1100, 1100, 1100, 1100, 1100, 1000, 1000, 1000, 1000, 1000, 1100, 1100, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1200, 1300, 1300, 1300, 1100, 1200, 1100, 1100, 1100, 1100, 1100, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1300, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1600, 1300, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1200, 1400, 1600, 1800, 2000, 2300, 2500, 2600, 2600, 2600, 2600, 2600, 2600, 2600, 2600, @@ -181,10 +184,7 @@ var VmMetricData = map[int32][]int64{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - 94: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 94: []int64{341, 881, 851, 214, 263, 802, 777, 58, 661, 231, 255, 494, 192, 302, 90, 371, 709, 164, 58, 1, 511, 711, 1005, 556, 457, 869, 708, 994, 668, 826, 112, 633, 901, 345, 317, 199, 199, 168, 981, 665, 29, 436, 225, 426, 309, 333, 757, 696, 840, 210, 500, 343, 651, 717, 803, 869, 445, 907, 928, 268, 437, 583, 160, 478, 891, 471, 72, 448, 457, 499, 348, 527, 409, 731, 849, 572, 378, 33, 254, 414, 781, 322, 153, 755, 301, 583, 823, 55, 637, 233, 259, 6, 448, 217, 842, 921, 971, 419, 246, 289}, 400: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -305,10 +305,7 @@ var VmMetricData = map[int32][]int64{ 800, 900, 1000, 1000, 1300, 1400, 1300, 900, 800, 900, 1000, 1000, 1000, 800, 800, 2400, 3900, 4100, 2600, 1400, 1200, 1200, 900, 800, 800, 1000, 1100, 1000, 900, 800, 900, 900, 1000, 900, 1200, 1200, 1200, 900, 800, 900, 1100, 1100, 1100, 800, 900, 2000, 2900, 4100, 3800, 4200, 4500, 4700, 3900, 2400, 1400, 1000, 1100, 1100, 900, 800, 1000, 1100, 1200, 900, 1200, 1300, 1400, 1100, 1000, 1000}, - 74: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 74: []int64{961, 1016, 502, 571, 475, 122, 219, 937, 428, 657, 356, 987, 332, 469, 465, 216, 708, 984, 519, 696, 420, 994, 454, 7, 223, 559, 320, 521, 632, 18, 280, 144, 48, 994, 584, 555, 665, 944, 831, 135, 40, 851, 210, 440, 679, 569, 908, 745, 552, 125, 783, 877, 317, 895, 458, 999, 50, 288, 600, 729, 716, 441, 713, 800, 378, 440, 225, 226, 384, 588, 982, 393, 736, 817, 453, 644, 255, 92, 671, 81, 586, 1019, 286, 247, 781, 524, 765, 762, 217, 941, 595, 478, 597, 294, 648, 327, 1019, 706, 826, 813}, 85: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -357,10 +354,7 @@ var VmMetricData = map[int32][]int64{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - 406: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 406: []int64{942, 615, 308, 1003, 67, 638, 951, 442, 100, 350, 477, 964, 469, 905, 622, 523, 679, 130, 457, 208, 710, 905, 781, 740, 608, 254, 286, 483, 205, 929, 88, 936, 730, 832, 144, 658, 558, 306, 19, 920, 254, 804, 458, 370, 328, 655, 43, 165, 653, 310, 369, 705, 188, 238, 170, 948, 535, 209, 293, 971, 787, 245, 377, 767, 807, 324, 896, 109, 178, 928, 954, 312, 26, 831, 816, 646, 159, 232, 997, 820, 387, 128, 28, 582, 1010, 705, 662, 815, 830, 946, 750, 637, 600, 847, 732, 566, 562, 406, 311, 609}, 513: []int64{1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1800, 1800, 1900, 1900, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 1900, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 2000, 1900, 1900, 1900, 1900, 1900, 1800, 1700, 1800, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 1700, 2200, 2500, 3600, 3700, 3800, 3900, 3900, 4000, 4000, 4000, 4000, 4000, 4000, 4000, 4000, @@ -373,10 +367,12 @@ var VmMetricData = map[int32][]int64{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - 10: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 10: []int64{740, 967, 600, 858, 667, 588, 488, 323, 834, 600, 49, 486, 867, 163, 219, 532, + 224, 115, 377, 80, 671, 327, 77, 8, 995, 831, 594, 326, 595, 182, 152, 195, 897, 924, 995, + 393, 126, 296, 678, 494, 752, 198, 199, 184, 412, 600, 19, 454, 605, 481, 456, 54, 487, + 395, 24, 859, 670, 710, 339, 232, 300, 941, 187, 190, 779, 127, 252, 304, 580, 823, 30, + 43, 3, 30, 523, 670, 499, 474, 962, 588, 300, 978, 338, 772, 212, 435, 920, 958, 533, 650, + 39, 668, 185, 124, 851, 226, 356, 594, 247, 194}, 12: []int64{137, 101, 116, 123, 114, 107, 96, 96, 103, 124, 111, 109, 108, 106, 106, 124, 122, 117, 149, 137, 141, 109, 110, 154, 128, 88, 107, 119, 102, 108, 125, 91, 95, 116, 97, 108, 100, 103, 119, 122, 97, 99, 108, 94, 97, 106, 105, 106, 107, 98, 111, 105, 97, 98, 106, 111, 94, 90, 95, 100, 131, 100, 103, 125, 108, 112, 97, 91, 107, 106, 98, 102, 116, 96, 112, 257, 186, 182, 259, 271, 232, 196, 123, 107, 122, 112, 114, 118, 104, 116, @@ -684,11 +680,12 @@ var HostMetricData = map[int32][]int64{ 135, 102, 74, 158, 108, 74, 121, 144, 74, 132, 124, 82, 211, 154, 127, 142, 84, 76, 115, 96, 76, 128, 84, 72, 116, 157, 96, 126, 94, 107, 136, 132, 106, 158, 164, 96, 112, 137, 90, 142, }, - 410: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 410: []int64{976, 899, 657, 904, 171, 606, 607, 707, 823, 331, 255, 421, 230, 1001, + 937, 467, 738, 287, 904, 962, 518, 391, 593, 593, 59, 874, 364, 873, 728, 727, 533, + 328, 957, 637, 973, 1014, 259, 160, 698, 589, 933, 283, 385, 393, 129, 414, 16, 800, + 105, 150, 905, 278, 131, 115, 678, 738, 444, 411, 388, 402, 541, 428, 970, 260, 56, + 794, 975, 480, 644, 110, 702, 93, 240, 322, 651, 370, 261, 589, 72, 259, 405, 965, + 927, 519, 210, 291, 688, 758, 942, 301, 253, 605, 677, 995, 509, 478, 646, 3, 472, 1007, }, 470: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -708,11 +705,12 @@ var HostMetricData = map[int32][]int64{ 58386204, 58386216, 58386220, 58386220, 58388612, 58386220, 58386220, 58386220, 58386220, 58386208, 58386248, 58386248, 58386248, 58386236, 58386248, 58386248, 58386248, 58386248, 58386248, 58386248, 58386248, 58386248, 58386236, 58386248, 58388640, 58386248, 58386240, 58386248, 58386248, 58386248, 58386248, 58388640, 58386248, 58386248, 58386248, 58386236, 58386248, 58386248, 58386248, 58386236, }, - 90: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 90: []int64{6, 644, 90, 376, 809, 98, 902, 998, 526, 633, 973, 1019, 423, 410, 219, + 879, 566, 390, 109, 450, 489, 341, 61, 465, 29, 893, 134, 1022, 703, 73, 477, 976, + 172, 175, 65, 696, 410, 566, 430, 187, 300, 542, 305, 751, 606, 567, 905, 70, 369, + 524, 913, 829, 351, 456, 295, 29, 539, 694, 620, 1010, 441, 904, 706, 954, 777, 221, + 497, 586, 456, 694, 183, 631, 302, 391, 857, 864, 610, 880, 906, 299, 839, 399, 49, + 713, 220, 903, 788, 228, 256, 119, 562, 395, 991, 543, 205, 584, 130, 804, 70, 99, }, 406: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -1012,16 +1010,14 @@ var ResourcePoolMetricData = map[int32][]int64{ 1211531, 1206346, 1206131, 1206061, 1205836, 1205722, 1205495, 1205681, 1205711, 1204664, 1204509, 1205405, 1205132, 1204909, 1204796, 1204754, 1204743, 1204720, 1204484, 1204448, 1204636, 1204476, 1204354, 1204331, 1204079, 1203968, 1203899, 1203865, 1203811, 1203734, 1203865, 1203628, 1203251, 1203212, 1203098, 1203057, 1203938, 1203697, 1203608, 1203573, 1203545, 1203465, 1202291, 1201669, 1201782, 1201631, 1201743, 1201529, 1201474, 1201407, 1199122, 1198521, 1198570}, - 70: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, - 90: []int64{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + 70: []int64{91, 585, 246, 114, 553, 348, 824, 848, 827, 882, 632, 500, 647, 805, 425, 971, 789, 1001, 910, 1013, 338, 713, 496, 168, 201, 886, 124, 968, 768, 736, 612, 859, 973, 64, 312, 449, 38, 839, 807, 571, 83, 862, 1015, 333, 818, 173, 396, 520, 171, 678, 160, 203, 991, 549, 776, 524, 390, 228, 576, 307, 1005, 93, 893, 475, 451, 141, 98, 439, 95, 104, 739, 630, 275, 701, 722, 16, 207, 468, 310, 387, 217, 377, 684, 969, 396, 1010, 866, 914, 181, 621, 995, 831, 278, 530, 465, 745, 704, 762, 545, 544}, + 90: []int64{6, 644, 90, 376, 809, 98, 902, 998, 526, 633, 973, 1019, 423, 410, 219, + 879, 566, 390, 109, 450, 489, 341, 61, 465, 29, 893, 134, 1022, 703, 73, 477, 976, + 172, 175, 65, 696, 410, 566, 430, 187, 300, 542, 305, 751, 606, 567, 905, 70, 369, + 524, 913, 829, 351, 456, 295, 29, 539, 694, 620, 1010, 441, 904, 706, 954, 777, 221, + 497, 586, 456, 694, 183, 631, 302, 391, 857, 864, 610, 880, 906, 299, 839, 399, 49, + 713, 220, 903, 788, 228, 256, 119, 562, 395, 991, 543, 205, 584, 130, 804, 70, 99, + }, 7: []int64{1406, 1419, 1426, 1412, 1413, 1408, 1472, 1426, 1462, 1424, 1447, 1403, 1433, 1429, 1420, 1395, 1447, 1396, 1406, 1413, 1432, 1420, 1425, 1411, 1432, 1437, 1444, 1407, 1448, 1450, 1477, 1431, 1451, 1437, 1403, 1459, 1478, 1452, 1447, 1446, 1410, 1441, 1445, 1415, 1433, 1435, 1458, 1419, 1441, 1476, 1310, 1482, 1451, 1458, 1455, 1428, 1446, 1443, 1436, 1449, diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/service_content.go b/vendor/github.com/vmware/govmomi/simulator/vpx/service_content.go index 3018d01ed27..c1874c5df6d 100644 --- a/vendor/github.com/vmware/govmomi/simulator/vpx/service_content.go +++ b/vendor/github.com/vmware/govmomi/simulator/vpx/service_content.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -24,7 +24,7 @@ import ( // ServiceContent is the default template for the ServiceInstance content property. // Capture method: -// govc object.collect -s -dump - content +// govc object.collect -s -dump - content var ServiceContent = types.ServiceContent{ RootFolder: types.ManagedObjectReference{Type: "Folder", Value: "group-d1"}, PropertyCollector: types.ManagedObjectReference{Type: "PropertyCollector", Value: "propertyCollector"}, diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/setting.go b/vendor/github.com/vmware/govmomi/simulator/vpx/setting.go index 7bbf0c02d60..7625824da62 100644 --- a/vendor/github.com/vmware/govmomi/simulator/vpx/setting.go +++ b/vendor/github.com/vmware/govmomi/simulator/vpx/setting.go @@ -18,6 +18,8 @@ package vpx import "github.com/vmware/govmomi/vim25/types" +// TODO: figure out whether this is Setting or AdvancedOptions - see esx/setting.go for the difference + // Setting is captured from VC's ServiceContent.OptionManager.setting var Setting = []types.BaseOptionValue{ // This list is currently pruned to include sso options only with sso.enabled set to false diff --git a/vendor/github.com/vmware/govmomi/simulator/vpx/task_manager.go b/vendor/github.com/vmware/govmomi/simulator/vpx/task_manager.go index dee36ff71a1..a3fcc302d88 100644 --- a/vendor/github.com/vmware/govmomi/simulator/vpx/task_manager.go +++ b/vendor/github.com/vmware/govmomi/simulator/vpx/task_manager.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017-2018 VMware, Inc. All Rights Reserved. +Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -20,7 +20,7 @@ import "github.com/vmware/govmomi/vim25/types" // Description is the default template for the TaskManager description property. // Capture method: -// govc object.collect -s -dump TaskManager:TaskManager description +// govc object.collect -s -dump TaskManager:TaskManager description var Description = types.TaskDescription{ MethodInfo: []types.BaseElementDescription{ &types.ElementDescription{ diff --git a/vendor/github.com/vmware/govmomi/task/wait.go b/vendor/github.com/vmware/govmomi/task/wait.go index b78f5110d95..d52458e6678 100644 --- a/vendor/github.com/vmware/govmomi/task/wait.go +++ b/vendor/github.com/vmware/govmomi/task/wait.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -113,7 +113,6 @@ func (t *taskCallback) fn(pc []types.PropertyChange) bool { // The detail for the progress update is set to an empty string. If the task // finishes in the error state, the error instance is passed through as well. // Note that this error is the same error that is returned by this function. -// func Wait(ctx context.Context, ref types.ManagedObjectReference, pc *property.Collector, s progress.Sinker) (*types.TaskInfo, error) { cb := &taskCallback{} diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/archive.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/archive.go index 65f5743aba9..6360743beb3 100644 --- a/vendor/github.com/vmware/govmomi/toolbox/hgfs/archive.go +++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/archive.go @@ -22,7 +22,6 @@ import ( "bytes" "compress/gzip" "io" - "io/ioutil" "log" "math" "net/url" @@ -139,7 +138,7 @@ func (h *ArchiveHandler) newArchiveFromGuest(u *url.URL) (File, error) { } var z io.Writer = w - var c io.Closer = ioutil.NopCloser(nil) + var c io.Closer = io.NopCloser(nil) switch u.Query().Get("format") { case "tgz": @@ -194,7 +193,7 @@ func (h *ArchiveHandler) newArchiveToGuest(u *url.URL) (File, error) { c := func() error { // Drain the pipe of tar trailer data (two null blocks) if cerr == nil { - _, _ = io.Copy(ioutil.Discard, a.Reader) + _, _ = io.Copy(io.Discard, a.Reader) } return nil } diff --git a/vendor/github.com/vmware/govmomi/toolbox/hgfs/server.go b/vendor/github.com/vmware/govmomi/toolbox/hgfs/server.go index efc3faf212c..1c887e97480 100644 --- a/vendor/github.com/vmware/govmomi/toolbox/hgfs/server.go +++ b/vendor/github.com/vmware/govmomi/toolbox/hgfs/server.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2017 VMware, Inc. All Rights Reserved. +Copyright (c) 2017-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -198,9 +198,9 @@ func (s *Server) OpenFile(name string, mode int32) (File, error) { // Note that callers on the VMX side that reach this path are only concerned with: // - does the file exist? // - size: -// + used for UI progress with desktop Drag-N-Drop operations, which toolbox does not support. -// + sent to as Content-Length header in response to GET of FileTransferInformation.Url, -// if the first ReadV3 size is > HGFS_LARGE_PACKET_MAX +// + used for UI progress with desktop Drag-N-Drop operations, which toolbox does not support. +// + sent to as Content-Length header in response to GET of FileTransferInformation.Url, +// if the first ReadV3 size is > HGFS_LARGE_PACKET_MAX func (s *Server) Stat(name string) (os.FileInfo, error) { u := urlParse(name) diff --git a/vendor/github.com/vmware/govmomi/toolbox/process/process.go b/vendor/github.com/vmware/govmomi/toolbox/process/process.go index 312a0cf345a..8b9cc15d2d0 100644 --- a/vendor/github.com/vmware/govmomi/toolbox/process/process.go +++ b/vendor/github.com/vmware/govmomi/toolbox/process/process.go @@ -21,7 +21,6 @@ import ( "context" "fmt" "io" - "io/ioutil" "net" "net/url" "os" @@ -392,7 +391,7 @@ func (m *Manager) Stat(u *url.URL) (os.FileInfo, error) { pf := &File{ name: name, - Closer: ioutil.NopCloser(nil), // via hgfs, nop for stdout and stderr + Closer: io.NopCloser(nil), // via hgfs, nop for stdout and stderr } var r *bytes.Buffer diff --git a/vendor/github.com/vmware/govmomi/vapi/internal/internal.go b/vendor/github.com/vmware/govmomi/vapi/internal/internal.go index f6584c569bf..2872f380303 100644 --- a/vendor/github.com/vmware/govmomi/vapi/internal/internal.go +++ b/vendor/github.com/vmware/govmomi/vapi/internal/internal.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2018-2022 VMware, Inc. All Rights Reserved. +Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -43,7 +43,6 @@ const ( TrustedCertificatesPath = "/api/content/trusted-certificates" VCenterOVFLibraryItem = "/com/vmware/vcenter/ovf/library-item" VCenterVMTXLibraryItem = "/vcenter/vm-template/library-items" - VCenterVM = "/vcenter/vm" SessionCookieName = "vmware-api-session-id" UseHeaderAuthn = "vmware-use-header-authn" DebugEcho = "/vc-sim/debug/echo" @@ -59,7 +58,10 @@ type AssociatedObject struct { // Reference implements mo.Reference func (o AssociatedObject) Reference() types.ManagedObjectReference { - return types.ManagedObjectReference(o) + return types.ManagedObjectReference{ + Type: o.Type, + Value: o.Value, + } } // Association for tag-association requests. @@ -69,9 +71,11 @@ type Association struct { // NewAssociation returns an Association, converting ref to an AssociatedObject. func NewAssociation(ref mo.Reference) Association { - obj := AssociatedObject(ref.Reference()) return Association{ - ObjectID: &obj, + ObjectID: &AssociatedObject{ + Type: ref.Reference().Type, + Value: ref.Reference().Value, + }, } } diff --git a/vendor/github.com/vmware/govmomi/vapi/library/finder/README.md b/vendor/github.com/vmware/govmomi/vapi/library/finder/README.md new file mode 100644 index 00000000000..62331f26733 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vapi/library/finder/README.md @@ -0,0 +1,187 @@ +# The content library finder +The govmomi package now includes a finder for the content library, [`github.com/vmware/govmomi/vapi/library.Finder`](https://github.com/akutz/govmomi/blob/feature/content-library/vapi/library/finder/finder.go). This finder supports searching for objects in the content library using an inventory path design similar to the [standard govmomi finder](https://github.com/vmware/govmomi/blob/main/find/finder.go) and includes support for wildcard matching courtesy of golang's [`path.Match`](https://golang.org/pkg/path/#Match). For example: + +| Pattern | Result | +|---------|--------| +| `*` | Gets all of the content libraries | +| `*/` | Gets all of the content library items for all of the content libraries. | +| `/Public/` | Gets all of the content library items for the content library named `Public` | +| `/*/*/` | Gets all of the content library files for all of the content library items for all of the content libraries. | +| `Public/*/photon2*` | Gets all of the files that begin with `photon2` in all of the content library items for the content library named `Public` | + +The use of a wildcard character in the search string results in a full listing of content library objects for that part of the path's server-side analogue. If `Public/Photon2*` is searched, then all of the content library items for the `Public` library are listed in order to perform the wildcard matching. However, if `Public/PhotonOS-2-GA` then the server-side API call [`library:item:find`](https://vdc-repo.vmware.com/vmwb-repository/dcr-public/1cd28284-3b72-4885-9e31-d1c6d9e26686/71ef7304-a6c9-43b3-a3cd-868b2c236c81/doc/operations/com/vmware/content/library/item.find-operation.html) is used to find an item with the name `PhotonOS-2-GA`. + +## Performance +Search strings that do not use wildcard characters **should** be **more** efficient as these searches rely on server-side find calls and do not require dumping all of the objects. However, this is only true for systems with a large number of objects in the content libraries. This is due to the number of round-trips required to lookup an object with a direct path. For example: + +| Search path | Roundtrips | +|------|------------| +| `Public/Photon2` | 4 | +| `Public*/Photon2*` | 2 | + +The *absolute* search path takes twice as many roundtrips compared to the search path with wildcards: + +### Absolute path search logic +1. Find library ID for library with name using server-side find API +2. Get library with library ID +3. Find item ID for item with name using server-side find API +4. Get item with item ID + +### Wildcard search logic +1. Get all of the libraries and filter the pattern on the client-side +2. Get all of the items for the library and filter the pattern on the client-=side + +### Searches at scale +While a system that has few content library objects benefits from wildcard search logic, the fact is that the above approach regarding absolute paths proves out to be **much** more efficient for systems with large numbers of content library objects. + + +## `govc library.ls` + +### Listing all the objects in the content library + +```console +$ govc library.ls '*/*/' +/ISOs/CentOS-7-x86_64-Minimal-1804/CentOS-7-x86_64-Minimal-1804.iso +/ISOs/CoreOS Production/coreos_production_iso_image.iso +/ISOs/VMware-VCSA-all-6.7.0-8217866.iso/VMware-VCSA-all-6.7.0-8217866.iso +/ISOs/VMware-VIM-all-6.7.0-8217866.iso/VMware-VIM-all-6.7.0-8217866.iso +/ISOs/ubuntu-16.04.5-server-amd64/ubuntu-16.04.5-server-amd64.iso +/ISOs/photon-2.0-304b817/photon-2.0-304b817.iso +/OVAs/VMware-vCenter-Server-Appliance-6.7.0.10000-8217866_OVF10.ova/VMware-vCenter-Server-Appliance-6.7.0.10000-8217866_OVF10.ova +/OVAs/coreos_production_vmware_ova/coreos_production_vmware_ova.ovf +/OVAs/coreos_production_vmware_ova/coreos_production_vmware_ova-1.vmdk +/OVAs/centos_cloud_template/centos_cloud_template-2.iso +/OVAs/centos_cloud_template/centos_cloud_template.ovf +/OVAs/centos_cloud_template/centos_cloud_template-1.vmdk +/OVAs/centos_cloud_template/centos_cloud_template-3.nvram +/OVAs/photon-custom-hw13-2.0-304b817/photon-ova-disk1.vmdk +/OVAs/photon-custom-hw13-2.0-304b817/photon-ova.ovf +/OVAs/yakity-centos/yakity-centos-2.nvram +/OVAs/yakity-centos/yakity-centos-1.vmdk +/OVAs/yakity-centos/yakity-centos.ovf +/OVAs/yakity-photon/yakity-photon-1.vmdk +/OVAs/yakity-photon/yakity-photon.ovf +/OVAs/yakity-photon/yakity-photon-2.nvram +/OVAs/ubuntu-16.04-server-cloudimg-amd64/ubuntu-16.04-server-cloudimg-amd64.ovf +/OVAs/ubuntu-16.04-server-cloudimg-amd64/ubuntu-16.04-server-cloudimg-amd64-1.vmdk +/sk8-TestUploadOVA/photon2-cloud-init/photon2-cloud-init.ovf +/sk8-TestUploadOVA/photon2-cloud-init/photon2-cloud-init-1.vmdk +/Public/photon2-cloud-init/photon2-cloud-init.ovf +/Public/photon2-cloud-init/photon2-cloud-init-1.vmdk +``` + +## `govc library.info` + +### Getting the info for all the objects in the content library + +```console +$ govc library.info '*/*/' +Name: CentOS-7-x86_64-Minimal-1804.iso + Path: /ISOs/CentOS-7-x86_64-Minimal-1804/CentOS-7-x86_64-Minimal-1804.iso + Size: 824637106200 + Version: 1 +Name: coreos_production_iso_image.iso + Path: /ISOs/CoreOS Production/coreos_production_iso_image.iso + Size: 824637441624 + Version: 1 +Name: VMware-VCSA-all-6.7.0-8217866.iso + Path: /ISOs/VMware-VCSA-all-6.7.0-8217866.iso/VMware-VCSA-all-6.7.0-8217866.iso + Size: 824637106368 + Version: 1 +Name: VMware-VIM-all-6.7.0-8217866.iso + Path: /ISOs/VMware-VIM-all-6.7.0-8217866.iso/VMware-VIM-all-6.7.0-8217866.iso + Size: 824637106504 + Version: 1 +Name: ubuntu-16.04.5-server-amd64.iso + Path: /ISOs/ubuntu-16.04.5-server-amd64/ubuntu-16.04.5-server-amd64.iso + Size: 824637441944 + Version: 1 +Name: photon-2.0-304b817.iso + Path: /ISOs/photon-2.0-304b817/photon-2.0-304b817.iso + Size: 824637106672 + Version: 1 +Name: VMware-vCenter-Server-Appliance-6.7.0.10000-8217866_OVF10.ova + Path: /OVAs/VMware-vCenter-Server-Appliance-6.7.0.10000-8217866_OVF10.ova/VMware-vCenter-Server-Appliance-6.7.0.10000-8217866_OVF10.ova + Size: 824637106880 + Version: 1 +Name: coreos_production_vmware_ova.ovf + Path: /OVAs/coreos_production_vmware_ova/coreos_production_vmware_ova.ovf + Size: 824637107032 + Version: 1 +Name: coreos_production_vmware_ova-1.vmdk + Path: /OVAs/coreos_production_vmware_ova/coreos_production_vmware_ova-1.vmdk + Size: 824637107072 + Version: 1 +Name: centos_cloud_template-2.iso + Path: /OVAs/centos_cloud_template/centos_cloud_template-2.iso + Size: 824636997760 + Version: 1 +Name: centos_cloud_template.ovf + Path: /OVAs/centos_cloud_template/centos_cloud_template.ovf + Size: 824636997792 + Version: 1 +Name: centos_cloud_template-1.vmdk + Path: /OVAs/centos_cloud_template/centos_cloud_template-1.vmdk + Size: 824636997832 + Version: 1 +Name: centos_cloud_template-3.nvram + Path: /OVAs/centos_cloud_template/centos_cloud_template-3.nvram + Size: 824636997856 + Version: 1 +Name: photon-ova-disk1.vmdk + Path: /OVAs/photon-custom-hw13-2.0-304b817/photon-ova-disk1.vmdk + Size: 824637107280 + Version: 1 +Name: photon-ova.ovf + Path: /OVAs/photon-custom-hw13-2.0-304b817/photon-ova.ovf + Size: 824637107328 + Version: 1 +Name: yakity-centos-2.nvram + Path: /OVAs/yakity-centos/yakity-centos-2.nvram + Size: 824637253000 + Version: 2 +Name: yakity-centos-1.vmdk + Path: /OVAs/yakity-centos/yakity-centos-1.vmdk + Size: 824637253024 + Version: 2 +Name: yakity-centos.ovf + Path: /OVAs/yakity-centos/yakity-centos.ovf + Size: 824637253056 + Version: 2 +Name: yakity-photon-1.vmdk + Path: /OVAs/yakity-photon/yakity-photon-1.vmdk + Size: 824637107504 + Version: 5 +Name: yakity-photon.ovf + Path: /OVAs/yakity-photon/yakity-photon.ovf + Size: 824637107536 + Version: 5 +Name: yakity-photon-2.nvram + Path: /OVAs/yakity-photon/yakity-photon-2.nvram + Size: 824637107560 + Version: 5 +Name: ubuntu-16.04-server-cloudimg-amd64.ovf + Path: /OVAs/ubuntu-16.04-server-cloudimg-amd64/ubuntu-16.04-server-cloudimg-amd64.ovf + Size: 824637442112 + Version: 1 +Name: ubuntu-16.04-server-cloudimg-amd64-1.vmdk + Path: /OVAs/ubuntu-16.04-server-cloudimg-amd64/ubuntu-16.04-server-cloudimg-amd64-1.vmdk + Size: 824637442136 + Version: 1 +Name: photon2-cloud-init.ovf + Path: /sk8-TestUploadOVA/photon2-cloud-init/photon2-cloud-init.ovf + Size: 824636903184 + Version: 1 +Name: photon2-cloud-init-1.vmdk + Path: /sk8-TestUploadOVA/photon2-cloud-init/photon2-cloud-init-1.vmdk + Size: 824636903208 + Version: 1 +Name: photon2-cloud-init.ovf + Path: /Public/photon2-cloud-init/photon2-cloud-init.ovf + Size: 824637442304 + Version: 3 +Name: photon2-cloud-init-1.vmdk + Path: /Public/photon2-cloud-init/photon2-cloud-init-1.vmdk + Size: 824637442328 + Version: 3 +``` diff --git a/vendor/github.com/vmware/govmomi/vapi/library/finder/finder.go b/vendor/github.com/vmware/govmomi/vapi/library/finder/finder.go new file mode 100644 index 00000000000..5f030783163 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vapi/library/finder/finder.go @@ -0,0 +1,328 @@ +/* +Copyright (c) 2018 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package finder + +import ( + "context" + "encoding/json" + "fmt" + "path" + "strings" + + "github.com/vmware/govmomi/vapi/library" +) + +// Finder is a helper object for finding content library objects by their +// inventory paths: /LIBRARY/ITEM/FILE. +// +// Wildcard characters `*` and `?` are both supported. However, the use +// of a wildcard character in the search string results in a full listing of +// that part of the path's server-side items. +// +// Path parts that do not use wildcard characters rely on server-side Find +// functions to find the path token by its name. Ironically finding one +// item with a direct path takes longer than if a wildcard is used because +// of the multiple round-trips. Direct paths will be more performant on +// systems that have numerous items. +type Finder struct { + M *library.Manager +} + +// NewFinder returns a new Finder. +func NewFinder(m *library.Manager) *Finder { + return &Finder{m} +} + +// Find finds one or more items that match the provided inventory path(s). +func (f *Finder) Find( + ctx context.Context, ipath ...string) ([]FindResult, error) { + + if len(ipath) == 0 { + ipath = []string{""} + } + var result []FindResult + for _, p := range ipath { + results, err := f.find(ctx, p) + if err != nil { + return nil, err + } + result = append(result, results...) + } + return result, nil +} + +func (f *Finder) find(ctx context.Context, ipath string) ([]FindResult, error) { + + if ipath == "" { + ipath = "*" + } + + // Get the argument and remove any leading separator characters. + ipath = strings.TrimPrefix(ipath, "/") + + // Tokenize the path into its distinct parts. + parts := strings.Split(ipath, "/") + + // If there are more than three parts then the file name contains + // the "/" character. In that case collapse any additional parts + // back into the filename. + if len(parts) > 3 { + parts = []string{ + parts[0], + parts[1], + strings.Join(parts[2:], "/"), + } + } + + libs, err := f.findLibraries(ctx, parts[0]) + if err != nil { + return nil, err + } + + // If the path is a single token then the libraries are requested. + if len(parts) < 2 { + return libs, nil + } + + items, err := f.findLibraryItems(ctx, libs, parts[1]) + if err != nil { + return nil, err + } + + // If the path is two tokens then the library items are requested. + if len(parts) < 3 { + return items, nil + } + + // Get the library item files. + return f.findLibraryItemFiles(ctx, items, parts[2]) +} + +// FindResult is the type of object returned from a Find operation. +type FindResult interface { + + // GetParent returns the parent of the find result. If the find result + // is a Library then this function will return nil. + GetParent() FindResult + + // GetPath returns the inventory path of the find result. + GetPath() string + + // GetID returns the ID of the find result. + GetID() string + + // GetName returns the name of the find result. + GetName() string + + // GetResult gets the underlying library object. + GetResult() interface{} +} + +type findResult struct { + result interface{} + parent FindResult +} + +func (f findResult) GetResult() interface{} { + return f.result +} +func (f findResult) GetParent() FindResult { + return f.parent +} +func (f findResult) GetPath() string { + switch f.result.(type) { + case library.Library: + return fmt.Sprintf("/%s", f.GetName()) + case library.Item, library.File: + return fmt.Sprintf("%s/%s", f.parent.GetPath(), f.GetName()) + default: + return "" + } +} + +func (f findResult) GetID() string { + switch t := f.result.(type) { + case library.Library: + return t.ID + case library.Item: + return t.ID + default: + return "" + } +} + +func (f findResult) GetName() string { + switch t := f.result.(type) { + case library.Library: + return t.Name + case library.Item: + return t.Name + case library.File: + return t.Name + default: + return "" + } +} + +func (f findResult) MarshalJSON() ([]byte, error) { + return json.Marshal(f.GetResult()) +} + +func (f *Finder) findLibraries( + ctx context.Context, + token string) ([]FindResult, error) { + + if token == "" { + token = "*" + } + + var result []FindResult + + // If the token does not contain any wildcard characters then perform + // a lookup by name using a server side call. + if !strings.ContainsAny(token, "*?") { + libIDs, err := f.M.FindLibrary(ctx, library.Find{Name: token}) + if err != nil { + return nil, err + } + for _, id := range libIDs { + lib, err := f.M.GetLibraryByID(ctx, id) + if err != nil { + return nil, err + } + result = append(result, findResult{result: *lib}) + } + if len(result) == 0 { + lib, err := f.M.GetLibraryByID(ctx, token) + if err == nil { + result = append(result, findResult{result: *lib}) + } + } + return result, nil + } + + libs, err := f.M.GetLibraries(ctx) + if err != nil { + return nil, err + } + for _, lib := range libs { + match, err := path.Match(token, lib.Name) + if err != nil { + return nil, err + } + if match { + result = append(result, findResult{result: lib}) + } + } + return result, nil +} + +func (f *Finder) findLibraryItems( + ctx context.Context, + parents []FindResult, token string) ([]FindResult, error) { + + if token == "" { + token = "*" + } + + var result []FindResult + + for _, parent := range parents { + // If the token does not contain any wildcard characters then perform + // a lookup by name using a server side call. + if !strings.ContainsAny(token, "*?") { + childIDs, err := f.M.FindLibraryItems( + ctx, library.FindItem{ + Name: token, + LibraryID: parent.GetID(), + }) + if err != nil { + return nil, err + } + for _, id := range childIDs { + child, err := f.M.GetLibraryItem(ctx, id) + if err != nil { + return nil, err + } + result = append(result, findResult{ + result: *child, + parent: parent, + }) + } + continue + } + + children, err := f.M.GetLibraryItems(ctx, parent.GetID()) + if err != nil { + return nil, err + } + for _, child := range children { + match, err := path.Match(token, child.Name) + if err != nil { + return nil, err + } + if match { + result = append( + result, findResult{parent: parent, result: child}) + } + } + } + return result, nil +} + +func (f *Finder) findLibraryItemFiles( + ctx context.Context, + parents []FindResult, token string) ([]FindResult, error) { + + if token == "" { + token = "*" + } + + var result []FindResult + + for _, parent := range parents { + // If the token does not contain any wildcard characters then perform + // a lookup by name using a server side call. + if !strings.ContainsAny(token, "*?") { + child, err := f.M.GetLibraryItemFile(ctx, parent.GetID(), token) + if err != nil { + return nil, err + } + result = append(result, findResult{ + result: *child, + parent: parent, + }) + continue + } + + children, err := f.M.ListLibraryItemFiles(ctx, parent.GetID()) + if err != nil { + return nil, err + } + for _, child := range children { + match, err := path.Match(token, child.Name) + if err != nil { + return nil, err + } + if match { + result = append( + result, findResult{parent: parent, result: child}) + } + } + } + return result, nil +} diff --git a/vendor/github.com/vmware/govmomi/vapi/library/library.go b/vendor/github.com/vmware/govmomi/vapi/library/library.go index e5e5d0896f6..62ad873bc56 100644 --- a/vendor/github.com/vmware/govmomi/vapi/library/library.go +++ b/vendor/github.com/vmware/govmomi/vapi/library/library.go @@ -1,5 +1,5 @@ /* -Copyright (c) 2018 VMware, Inc. All Rights Reserved. +Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ type StorageBackings struct { // Library provides methods to create, read, update, delete, and enumerate libraries. type Library struct { CreationTime *time.Time `json:"creation_time,omitempty"` - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` ID string `json:"id,omitempty"` LastModifiedTime *time.Time `json:"last_modified_time,omitempty"` LastSyncTime *time.Time `json:"last_sync_time,omitempty"` @@ -120,7 +120,7 @@ func (l *Library) Patch(src *Library) { if src.Name != "" { l.Name = src.Name } - if src.Description != "" { + if src.Description != nil { l.Description = src.Description } if src.Version != "" { diff --git a/vendor/github.com/vmware/govmomi/vapi/library/library_item.go b/vendor/github.com/vmware/govmomi/vapi/library/library_item.go index adc2101ab1e..e143da5d968 100644 --- a/vendor/github.com/vmware/govmomi/vapi/library/library_item.go +++ b/vendor/github.com/vmware/govmomi/vapi/library/library_item.go @@ -36,7 +36,7 @@ type Item struct { Cached bool `json:"cached,omitempty"` ContentVersion string `json:"content_version,omitempty"` CreationTime *time.Time `json:"creation_time,omitempty"` - Description string `json:"description,omitempty"` + Description *string `json:"description,omitempty"` ID string `json:"id,omitempty"` LastModifiedTime *time.Time `json:"last_modified_time,omitempty"` LastSyncTime *time.Time `json:"last_sync_time,omitempty"` @@ -63,7 +63,7 @@ func (i *Item) Patch(src *Item) { if src.Name != "" { i.Name = src.Name } - if src.Description != "" { + if src.Description != nil { i.Description = src.Description } if src.Type != "" { @@ -82,12 +82,17 @@ func (c *Manager) CreateLibraryItem(ctx context.Context, item Item) (string, err LibraryID string `json:"library_id,omitempty"` Type string `json:"type"` } + + description := "" + if item.Description != nil { + description = *item.Description + } spec := struct { Item createItemSpec `json:"create_spec"` }{ Item: createItemSpec{ Name: item.Name, - Description: item.Description, + Description: description, LibraryID: item.LibraryID, Type: item.Type, }, diff --git a/vendor/github.com/vmware/govmomi/vapi/library/library_item_updatesession_file.go b/vendor/github.com/vmware/govmomi/vapi/library/library_item_updatesession_file.go index e34331cfa57..c571d3273c0 100644 --- a/vendor/github.com/vmware/govmomi/vapi/library/library_item_updatesession_file.go +++ b/vendor/github.com/vmware/govmomi/vapi/library/library_item_updatesession_file.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2018 VMware, Inc. All Rights Reserved. +Copyright (c) 2019-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -34,6 +34,13 @@ type TransferEndpoint struct { SSLCertificateThumbprint string `json:"ssl_certificate_thumbprint,omitempty"` } +type ProbeResult struct { + Status string `json:"status"` + SSLThumbprint string `json:"ssl_thumbprint,omitempty"` + SSLCertificate string `json:"ssl_certificate,omitempty"` + ErrorMessages []rest.LocalizableMessage `json:"error_messages,omitempty"` +} + // UpdateFile is the specification for the updatesession // operations file:add, file:get, and file:list. type UpdateFile struct { @@ -48,6 +55,19 @@ type UpdateFile struct { UploadEndpoint *TransferEndpoint `json:"upload_endpoint,omitempty"` } +// FileValidationError contains the validation error of a file in the update session +type FileValidationError struct { + Name string `json:"name"` + ErrorMessage rest.LocalizableMessage `json:"error_message"` +} + +// UpdateFileValidation contains the result of validating the files in the update session +type UpdateFileValidation struct { + HasErrors bool `json:"has_errors"` + MissingFiles []string `json:"missing_files,omitempty"` + InvalidFiles []FileValidationError `json:"invalid_files,omitempty"` +} + // AddLibraryItemFile adds a file func (c *Manager) AddLibraryItemFile(ctx context.Context, sessionID string, updateFile UpdateFile) (*UpdateFile, error) { url := c.Resource(internal.LibraryItemUpdateSessionFile).WithID(sessionID).WithAction("add") @@ -66,29 +86,31 @@ func (c *Manager) AddLibraryItemFile(ctx context.Context, sessionID string, upda } // AddLibraryItemFileFromURI adds a file from a remote URI. -func (c *Manager) AddLibraryItemFileFromURI( - ctx context.Context, - sessionID, fileName, uri string) (*UpdateFile, error) { +func (c *Manager) AddLibraryItemFileFromURI(ctx context.Context, sessionID, name, uri string) (*UpdateFile, error) { + source := &TransferEndpoint{ + URI: uri, + } - n, fingerprint, err := c.getContentLengthAndFingerprint(ctx, uri) - if err != nil { - return nil, err + file := UpdateFile{ + Name: name, + SourceType: "PULL", + SourceEndpoint: source, } - info, err := c.AddLibraryItemFile(ctx, sessionID, UpdateFile{ - Name: fileName, - SourceType: "PULL", - Size: n, - SourceEndpoint: &TransferEndpoint{ - URI: uri, - SSLCertificateThumbprint: fingerprint, - }, - }) - if err != nil { - return nil, err + if res, err := c.Head(uri); err == nil { + file.Size = res.ContentLength + if res.TLS != nil { + source.SSLCertificateThumbprint = soap.ThumbprintSHA1(res.TLS.PeerCertificates[0]) + } + } else { + res, err := c.ProbeTransferEndpoint(ctx, *source) + if err != nil { + return nil, err + } + source.SSLCertificateThumbprint = res.SSLThumbprint } - return info, c.CompleteLibraryItemUpdateSession(ctx, sessionID) + return c.AddLibraryItemFile(ctx, sessionID, file) } // GetLibraryItemUpdateSessionFile retrieves information about a specific file @@ -102,25 +124,36 @@ func (c *Manager) GetLibraryItemUpdateSessionFile(ctx context.Context, sessionID return &res, c.Do(ctx, url.Request(http.MethodPost, spec), &res) } -// getContentLengthAndFingerprint gets the number of bytes returned -// by the URI as well as the SHA1 fingerprint of the peer certificate -// if the URI's scheme is https. -func (c *Manager) getContentLengthAndFingerprint( - ctx context.Context, uri string) (int64, string, error) { - resp, err := c.Head(uri) - if err != nil { - return 0, "", err - } - if resp.TLS == nil || len(resp.TLS.PeerCertificates) == 0 { - return resp.ContentLength, "", nil - } - fingerprint := c.Thumbprint(resp.Request.URL.Host) - if fingerprint == "" { - if c.DefaultTransport().TLSClientConfig.InsecureSkipVerify { - fingerprint = soap.ThumbprintSHA1(resp.TLS.PeerCertificates[0]) - } - } - return resp.ContentLength, fingerprint, nil +// ListLibraryItemUpdateSessionFile lists all files in the library item associated with the update session +func (c *Manager) ListLibraryItemUpdateSessionFile(ctx context.Context, sessionID string) ([]UpdateFile, error) { + url := c.Resource(internal.LibraryItemUpdateSessionFile).WithParam("update_session_id", sessionID) + var res []UpdateFile + return res, c.Do(ctx, url.Request(http.MethodGet), &res) +} + +// ValidateLibraryItemUpdateSessionFile validates all files in the library item associated with the update session +func (c *Manager) ValidateLibraryItemUpdateSessionFile(ctx context.Context, sessionID string) (*UpdateFileValidation, error) { + url := c.Resource(internal.LibraryItemUpdateSessionFile).WithID(sessionID).WithAction("validate") + var res UpdateFileValidation + return &res, c.Do(ctx, url.Request(http.MethodPost), &res) +} + +// RemoveLibraryItemUpdateSessionFile requests a file to be removed. The file will only be effectively removed when the update session is completed. +func (c *Manager) RemoveLibraryItemUpdateSessionFile(ctx context.Context, sessionID string, fileName string) error { + url := c.Resource(internal.LibraryItemUpdateSessionFile).WithID(sessionID).WithAction("remove") + spec := struct { + Name string `json:"file_name"` + }{fileName} + return c.Do(ctx, url.Request(http.MethodPost, spec), nil) +} + +func (c *Manager) ProbeTransferEndpoint(ctx context.Context, endpoint TransferEndpoint) (*ProbeResult, error) { + url := c.Resource(internal.LibraryItemUpdateSessionFile).WithAction("probe") + spec := struct { + SourceEndpoint TransferEndpoint `json:"source_endpoint"` + }{endpoint} + var res ProbeResult + return &res, c.Do(ctx, url.Request(http.MethodPost, spec), &res) } // ReadManifest converts an ovf manifest to a map of file name -> Checksum. diff --git a/vendor/github.com/vmware/govmomi/vapi/rest/client.go b/vendor/github.com/vmware/govmomi/vapi/rest/client.go index b1cefd0e280..9cd59e5a3b1 100644 --- a/vendor/github.com/vmware/govmomi/vapi/rest/client.go +++ b/vendor/github.com/vmware/govmomi/vapi/rest/client.go @@ -22,7 +22,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "strings" @@ -32,6 +31,7 @@ import ( "github.com/vmware/govmomi/vapi/internal" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/soap" + "github.com/vmware/govmomi/vim25/types" ) // Client extends soap.Client to support JSON encoding, while inheriting security features, debug tracing and session persistence. @@ -155,6 +155,14 @@ func (e *statusError) Error() string { return fmt.Sprintf("%s %s: %s", e.res.Request.Method, e.res.Request.URL, e.res.Status) } +func IsStatusError(err error, code int) bool { + statusErr, ok := err.(*statusError) + if !ok || statusErr == nil || statusErr.res == nil { + return false + } + return statusErr.res.StatusCode == code +} + // RawResponse may be used with the Do method as the resBody argument in order // to capture the raw response data. type RawResponse struct { @@ -180,6 +188,11 @@ func (c *Client) Do(ctx context.Context, req *http.Request, resBody interface{}) } } + // OperationID (see soap.Client.soapRoundTrip) + if id, ok := ctx.Value(types.ID{}).(string); ok { + req.Header.Add("X-Request-ID", id) + } + if headers, ok := ctx.Value(headersContext{}).(http.Header); ok { for k, v := range headers { for _, v := range v { @@ -195,7 +208,7 @@ func (c *Client) Do(ctx context.Context, req *http.Request, resBody interface{}) case http.StatusNoContent: case http.StatusBadRequest: // TODO: structured error types - detail, err := ioutil.ReadAll(res.Body) + detail, err := io.ReadAll(res.Body) if err != nil { return err } diff --git a/vendor/github.com/vmware/govmomi/vapi/simulator/simulator.go b/vendor/github.com/vmware/govmomi/vapi/simulator/simulator.go index c43494f2b0a..af1ef9df5e0 100644 --- a/vendor/github.com/vmware/govmomi/vapi/simulator/simulator.go +++ b/vendor/github.com/vmware/govmomi/vapi/simulator/simulator.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2018-2022 VMware, Inc. All Rights Reserved. +Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -28,7 +28,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "log" "net/http" "net/url" @@ -56,6 +55,7 @@ import ( "github.com/vmware/govmomi/view" "github.com/vmware/govmomi/vim25" "github.com/vmware/govmomi/vim25/methods" + "github.com/vmware/govmomi/vim25/soap" "github.com/vmware/govmomi/vim25/types" vim "github.com/vmware/govmomi/vim25/types" "github.com/vmware/govmomi/vim25/xml" @@ -88,6 +88,7 @@ type download struct { type handler struct { sync.Mutex + sm *simulator.SessionManager ServeMux *http.ServeMux URL url.URL Category map[string]*tags.Category @@ -104,7 +105,7 @@ type handler struct { func init() { simulator.RegisterEndpoint(func(s *simulator.Service, r *simulator.Registry) { if r.IsVPX() { - patterns, h := New(s.Listen, r.OptionManager().Setting) + patterns, h := New(s.Listen, r) for _, p := range patterns { s.Handle(p, h) } @@ -113,8 +114,9 @@ func init() { } // New creates a vAPI simulator. -func New(u *url.URL, settings []vim.BaseOptionValue) ([]string, http.Handler) { +func New(u *url.URL, r *simulator.Registry) ([]string, http.Handler) { s := &handler{ + sm: r.SessionManager(), ServeMux: http.NewServeMux(), URL: *u, Category: make(map[string]*tags.Category), @@ -166,7 +168,6 @@ func New(u *url.URL, settings []vim.BaseOptionValue) ([]string, http.Handler) { {internal.VCenterOVFLibraryItem + "/", s.libraryItemOVFID}, {internal.VCenterVMTXLibraryItem, s.libraryItemCreateTemplate}, {internal.VCenterVMTXLibraryItem + "/", s.libraryItemTemplateID}, - {internal.VCenterVM + "/", s.vmID}, {internal.DebugEcho, s.debugEcho}, // /api/ patterns. {internal.SecurityPoliciesPath, s.librarySecurityPolicies}, @@ -237,10 +238,7 @@ func (s *handler) isAuthorized(r *http.Request) bool { func (s *handler) hasAuthorization(r *http.Request) (string, bool) { u, p, ok := r.BasicAuth() if ok { // user+pass auth - if u == "" || p == "" { - return u, false - } - return u, true + return u, s.sm.Authenticate(s.URL, &vim.Login{UserName: u, Password: p}) } auth := r.Header.Get("Authorization") return "TODO", strings.HasPrefix(auth, "SIGN ") // token auth @@ -267,14 +265,22 @@ func (s *handler) AttachedObjects(tag vim.VslmTagEntry) ([]vim.ManagedObjectRefe } var ids []vim.ManagedObjectReference for id := range s.Association[t.ID] { - ids = append(ids, vim.ManagedObjectReference(id)) + ids = append( + ids, + vim.ManagedObjectReference{ + Type: id.Type, + Value: id.Value, + }) } return ids, nil } // AttachedTags is meant for internal use via simulator.Registry.tagManager func (s *handler) AttachedTags(ref vim.ManagedObjectReference) ([]vim.VslmTagEntry, vim.BaseMethodFault) { - oid := internal.AssociatedObject(ref) + oid := internal.AssociatedObject{ + Type: ref.Type, + Value: ref.Value, + } var tags []vim.VslmTagEntry for id, objs := range s.Association { if objs[oid] { @@ -295,7 +301,10 @@ func (s *handler) AttachTag(ref vim.ManagedObjectReference, tag vim.VslmTagEntry if t == nil { return new(vim.NotFound) } - s.Association[t.ID][internal.AssociatedObject(ref)] = true + s.Association[t.ID][internal.AssociatedObject{ + Type: ref.Type, + Value: ref.Value, + }] = true return nil } @@ -305,13 +314,17 @@ func (s *handler) DetachTag(id vim.ManagedObjectReference, tag vim.VslmTagEntry) if t == nil { return new(vim.NotFound) } - delete(s.Association[t.ID], internal.AssociatedObject(id)) + delete(s.Association[t.ID], internal.AssociatedObject{ + Type: id.Type, + Value: id.Value, + }) return nil } // StatusOK responds with http.StatusOK and encodes val, if specified, to JSON // For use with "/api" endpoints. func StatusOK(w http.ResponseWriter, val ...interface{}) { + w.Header().Set("Content-Type", "application/json") w.WriteHeader(http.StatusOK) if len(val) == 0 { return @@ -360,6 +373,60 @@ func BadRequest(w http.ResponseWriter, kind string) { } } +// ApiErrorAlreadyExists responds with a REST error of type "ALREADY_EXISTS". +// For use with "/api" endpoints. +func ApiErrorAlreadyExists(w http.ResponseWriter) { + apiError(w, http.StatusBadRequest, "ALREADY_EXISTS") +} + +// ApiErrorGeneral responds with a REST error of type "ERROR". +// For use with "/api" endpoints. +func ApiErrorGeneral(w http.ResponseWriter) { + apiError(w, http.StatusInternalServerError, "ERROR") +} + +// ApiErrorInvalidArgument responds with a REST error of type "INVALID_ARGUMENT". +// For use with "/api" endpoints. +func ApiErrorInvalidArgument(w http.ResponseWriter) { + apiError(w, http.StatusBadRequest, "INVALID_ARGUMENT") +} + +// ApiErrorNotAllowedInCurrentState responds with a REST error of type "NOT_ALLOWED_IN_CURRENT_STATE". +// For use with "/api" endpoints. +func ApiErrorNotAllowedInCurrentState(w http.ResponseWriter) { + apiError(w, http.StatusBadRequest, "NOT_ALLOWED_IN_CURRENT_STATE") +} + +// ApiErrorNotFound responds with a REST error of type "NOT_FOUND". +// For use with "/api" endpoints. +func ApiErrorNotFound(w http.ResponseWriter) { + apiError(w, http.StatusNotFound, "NOT_FOUND") +} + +// ApiErrorResourceInUse responds with a REST error of type "RESOURCE_IN_USE". +// For use with "/api" endpoints. +func ApiErrorResourceInUse(w http.ResponseWriter) { + apiError(w, http.StatusBadRequest, "RESOURCE_IN_USE") +} + +// ApiErrorUnauthorized responds with a REST error of type "UNAUTHORIZED". +// For use with "/api" endpoints. +func ApiErrorUnauthorized(w http.ResponseWriter) { + apiError(w, http.StatusBadRequest, "UNAUTHORIZED") +} + +// ApiErrorUnsupported responds with a REST error of type "UNSUPPORTED". +// For use with "/api" endpoints. +func ApiErrorUnsupported(w http.ResponseWriter) { + apiError(w, http.StatusBadRequest, "UNSUPPORTED") +} + +func apiError(w http.ResponseWriter, statusCode int, errorType string) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(statusCode) + w.Write([]byte(fmt.Sprintf(`{"error_type":"%s", "messages":[]}`, errorType))) +} + func (*handler) error(w http.ResponseWriter, err error) { http.Error(w, err.Error(), http.StatusInternalServerError) log.Print(err) @@ -1276,8 +1343,88 @@ func (s *handler) libraryItemUpdateSessionID(w http.ResponseWriter, r *http.Requ } } +func (s *handler) libraryItemProbe(endpoint library.TransferEndpoint) *library.ProbeResult { + p := &library.ProbeResult{ + Status: "SUCCESS", + } + + result := func() *library.ProbeResult { + for i, m := range p.ErrorMessages { + p.ErrorMessages[i].DefaultMessage = fmt.Sprintf(m.DefaultMessage, m.Args[0]) + } + return p + } + + u, err := url.Parse(endpoint.URI) + if err != nil { + p.Status = "INVALID_URL" + p.ErrorMessages = []rest.LocalizableMessage{{ + Args: []string{endpoint.URI}, + ID: "com.vmware.vdcs.cls-main.invalid_url_format", + DefaultMessage: "Invalid URL format for %s", + }} + return result() + } + + if u.Scheme != "http" && u.Scheme != "https" { + p.Status = "INVALID_URL" + p.ErrorMessages = []rest.LocalizableMessage{{ + Args: []string{endpoint.URI}, + ID: "com.vmware.vdcs.cls-main.file_probe_unsupported_uri_scheme", + DefaultMessage: "The specified URI %s is not supported", + }} + return result() + } + + res, err := http.Head(endpoint.URI) + if err != nil { + id := "com.vmware.vdcs.cls-main.http_request_error" + p.Status = "INVALID_URL" + + if soap.IsCertificateUntrusted(err) { + var info object.HostCertificateInfo + _ = info.FromURL(u, nil) + + id = "com.vmware.vdcs.cls-main.http_request_error_peer_not_authenticated" + p.Status = "CERTIFICATE_ERROR" + p.SSLThumbprint = info.ThumbprintSHA1 + } + + p.ErrorMessages = []rest.LocalizableMessage{{ + Args: []string{err.Error()}, + ID: id, + DefaultMessage: "HTTP request error: %s", + }} + + return result() + } + _ = res.Body.Close() + + if res.TLS != nil { + p.SSLThumbprint = soap.ThumbprintSHA1(res.TLS.PeerCertificates[0]) + } + + return result() +} + func (s *handler) libraryItemUpdateSessionFile(w http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodGet { + switch r.Method { + case http.MethodPost: + switch s.action(r) { + case "probe": + var spec struct { + SourceEndpoint library.TransferEndpoint `json:"source_endpoint"` + } + if s.decode(r, w, &spec) { + res := s.libraryItemProbe(spec.SourceEndpoint) + OK(w, res) + } + default: + http.NotFound(w, r) + } + return + case http.MethodGet: + default: w.WriteHeader(http.StatusMethodNotAllowed) return } @@ -1377,10 +1524,20 @@ func (s *handler) libraryItemUpdateSessionFileID(w http.ResponseWriter, r *http. } OK(w, ids) case "remove": + if up.State != "ACTIVE" { + s.error(w, fmt.Errorf("removeFile not allowed in state %s", up.State)) + return + } delete(s.Update, id) OK(w) case "validate": - // TODO + if up.State != "ACTIVE" { + BadRequest(w, "com.vmware.vapi.std.errors.not_allowed_in_current_state") + return + } + var res library.UpdateFileValidation + // TODO check missing_files, validate .ovf + OK(w, res) } } @@ -1735,7 +1892,7 @@ func (s *handler) libraryDeploy(ctx context.Context, c *vim25.Client, lib *libra } name := item.ovf() - desc, err := ioutil.ReadFile(filepath.Join(libraryPath(lib, item.ID), name)) + desc, err := os.ReadFile(filepath.Join(libraryPath(lib, item.ID), name)) if err != nil { return nil, err } @@ -1810,6 +1967,23 @@ func (s *handler) libraryDeploy(ctx context.Context, c *vim25.Client, lib *libra return nil, errors.New(spec.Error[0].LocalizedMessage) } + if config != nil { + if vmImportSpec, ok := spec.ImportSpec.(*types.VirtualMachineImportSpec); ok { + var configSpecs []types.BaseVirtualDeviceConfigSpec + + // Remove devices that we don't want to carry over from the import spec. Otherwise, since we + // just reconfigure the VM with the provided ConfigSpec later these devices won't be removed. + for _, d := range vmImportSpec.ConfigSpec.DeviceChange { + switch d.GetVirtualDeviceConfigSpec().Device.(type) { + case types.BaseVirtualEthernetCard: + default: + configSpecs = append(configSpecs, d) + } + } + vmImportSpec.ConfigSpec.DeviceChange = configSpecs + } + } + req := types.ImportVApp{ This: pool, Spec: spec.ImportSpec, @@ -1865,7 +2039,7 @@ func (s *handler) libraryItemOVF(w http.ResponseWriter, r *http.Request) { ID: id, LibraryID: l.Library.ID, Name: req.Spec.Name, - Description: req.Spec.Description, + Description: &req.Spec.Description, Type: library.ItemTypeOVF, CreationTime: types.NewTime(time.Now()), LastModifiedTime: types.NewTime(time.Now()), @@ -1925,7 +2099,10 @@ func (s *handler) libraryItemOVFID(w http.ResponseWriter, r *http.Request) { if err != nil { return err } - id := vcenter.ResourceID(info.Entity) + id := vcenter.ResourceID{ + Type: info.Entity.Type, + Value: info.Entity.Value, + } d.Succeeded = true d.ResourceID = &id return nil @@ -2265,17 +2442,6 @@ func (s *handler) libraryTrustedCertificatesID(w http.ResponseWriter, r *http.Re } } -func (s *handler) vmID(w http.ResponseWriter, r *http.Request) { - id := path.Base(r.URL.Path) - - switch r.Method { - case http.MethodDelete: - s.deleteVM(&types.ManagedObjectReference{Type: "VirtualMachine", Value: id}) - default: - http.NotFound(w, r) - } -} - func (s *handler) debugEcho(w http.ResponseWriter, r *http.Request) { r.Write(w) } diff --git a/vendor/github.com/vmware/govmomi/vapi/tags/tag_association.go b/vendor/github.com/vmware/govmomi/vapi/tags/tag_association.go index 33b22093661..ca8818191b5 100644 --- a/vendor/github.com/vmware/govmomi/vapi/tags/tag_association.go +++ b/vendor/github.com/vmware/govmomi/vapi/tags/tag_association.go @@ -81,7 +81,11 @@ func (c *Manager) AttachTagToMultipleObjects(ctx context.Context, tagID string, var ids []internal.AssociatedObject for i := range refs { - ids = append(ids, internal.AssociatedObject(refs[i].Reference())) + ref := refs[i].Reference() + ids = append(ids, internal.AssociatedObject{ + Type: ref.Type, + Value: ref.Value, + }) } spec := struct { @@ -116,7 +120,10 @@ func (c *Manager) AttachMultipleTagsToObject(ctx context.Context, tagIDs []strin } } - obj := internal.AssociatedObject(ref.Reference()) + obj := internal.AssociatedObject{ + Type: ref.Reference().Type, + Value: ref.Reference().Value, + } spec := struct { ObjectID internal.AssociatedObject `json:"object_id"` TagIDs []string `json:"tag_ids"` @@ -166,7 +173,10 @@ func (c *Manager) DetachMultipleTagsFromObject(ctx context.Context, tagIDs []str } } - obj := internal.AssociatedObject(ref.Reference()) + obj := internal.AssociatedObject{ + Type: ref.Reference().Type, + Value: ref.Reference().Value, + } spec := struct { ObjectID internal.AssociatedObject `json:"object_id"` TagIDs []string `json:"tag_ids"` @@ -337,7 +347,11 @@ func (t *AttachedTags) UnmarshalJSON(b []byte) error { func (c *Manager) ListAttachedTagsOnObjects(ctx context.Context, objectID []mo.Reference) ([]AttachedTags, error) { var ids []internal.AssociatedObject for i := range objectID { - ids = append(ids, internal.AssociatedObject(objectID[i].Reference())) + ref := objectID[i].Reference() + ids = append(ids, internal.AssociatedObject{ + Type: ref.Type, + Value: ref.Value, + }) } spec := struct { diff --git a/vendor/github.com/vmware/govmomi/vapi/vcenter/vcenter_ovf.go b/vendor/github.com/vmware/govmomi/vapi/vcenter/vcenter_ovf.go index 80f0d38c313..71efc23abe8 100644 --- a/vendor/github.com/vmware/govmomi/vapi/vcenter/vcenter_ovf.go +++ b/vendor/github.com/vmware/govmomi/vapi/vcenter/vcenter_ovf.go @@ -297,8 +297,10 @@ func (c *Manager) DeployLibraryItem(ctx context.Context, libraryItemID string, d return nil, err } if res.Succeeded { - ref := types.ManagedObjectReference(*res.ResourceID) - return &ref, nil + return &types.ManagedObjectReference{ + Type: res.ResourceID.Type, + Value: res.ResourceID.Value, + }, nil } return nil, res.Error } diff --git a/vendor/github.com/vmware/govmomi/vapi/vm/dataset/dataset.go b/vendor/github.com/vmware/govmomi/vapi/vm/dataset/dataset.go new file mode 100644 index 00000000000..cb178d6fbf9 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vapi/vm/dataset/dataset.go @@ -0,0 +1,200 @@ +/* +Copyright (c) 2023-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package dataset + +import ( + "context" + "net/http" + "net/url" + "path" + "strconv" + + "github.com/vmware/govmomi/vapi/rest" + "github.com/vmware/govmomi/vapi/vm/internal" +) + +// Manager extends rest.Client, adding data set related methods. +// +// Data sets functionality was introduced in vSphere 8.0, +// and requires the VM to have virtual hardware version 20 or newer. +// +// See the VMware Guest SDK Programming Guide for details on using data sets +// from within the guest OS of a VM. +// +// See https://developer.vmware.com/apis/vsphere-automation/latest/vcenter/vm/data_sets/ +type Manager struct { + *rest.Client +} + +// NewManager creates a new Manager instance with the given client. +func NewManager(client *rest.Client) *Manager { + return &Manager{ + Client: client, + } +} + +// Access permission to the entries of a data set. +type Access string + +const ( + AccessNone = Access("NONE") + AccessReadOnly = Access("READ_ONLY") + AccessReadWrite = Access("READ_WRITE") +) + +// Describes a data set to be created. +type CreateSpec struct { + // Name should take the form "com.company.project" to avoid conflict with other uses. + // Must not be empty. + Name string `json:"name"` + + // Description of the data set. + Description string `json:"description"` + + // Host controls access to the data set entries by the ESXi host and the vCenter. + // For example, if the host access is set to NONE, the entries of this data set + // will not be accessible through the vCenter API. + // Must not be empty. + Host Access `json:"host"` + + // Guest controls access to the data set entries by the guest OS of the VM (i.e. in-guest APIs). + // For example, if the guest access is set to READ_ONLY, it will be forbidden + // to create, delete, and update entries in this data set via the VMware Guest SDK. + // Must not be empty. + Guest Access `json:"guest"` + + // OmitFromSnapshotAndClone controls whether the data set is included in snapshots and clones of the VM. + // When a VM is reverted to a snapshot, any data set with OmitFromSnapshotAndClone=true will be destroyed. + // Default is false. + OmitFromSnapshotAndClone *bool `json:"omit_from_snapshot_and_clone,omitempty"` +} + +// Describes modifications to a data set. +type UpdateSpec struct { + Description *string `json:"description,omitempty"` + Host *Access `json:"host,omitempty"` + Guest *Access `json:"guest,omitempty"` + OmitFromSnapshotAndClone *bool `json:"omit_from_snapshot_and_clone,omitempty"` +} + +// Data set information. +type Info struct { + Name string `json:"name"` + Description string `json:"description"` + Host Access `json:"host"` + Guest Access `json:"guest"` + Used int `json:"used"` + OmitFromSnapshotAndClone bool `json:"omit_from_snapshot_and_clone"` +} + +// Brief data set information. +type Summary struct { + DataSet string `json:"data_set"` + Name string `json:"name"` + Description string `json:"description"` +} + +const dataSetsPathField = "data-sets" + +func dataSetPath(vm string, dataSet string) string { + return path.Join(internal.VCenterVMPath, url.PathEscape(vm), dataSetsPathField, url.PathEscape(dataSet)) +} + +func dataSetsPath(vm string) string { + return path.Join(internal.VCenterVMPath, url.PathEscape(vm), dataSetsPathField) +} + +const entriesPathField = "entries" + +func entryPath(vm string, dataSet string, key string) string { + return path.Join(internal.VCenterVMPath, url.PathEscape(vm), dataSetsPathField, url.PathEscape(dataSet), entriesPathField, url.PathEscape(key)) +} + +func entriesPath(vm string, dataSet string) string { + return path.Join(internal.VCenterVMPath, url.PathEscape(vm), dataSetsPathField, url.PathEscape(dataSet), entriesPathField) +} + +// CreateDataSet creates a data set associated with the given virtual machine. +func (c *Manager) CreateDataSet(ctx context.Context, vm string, spec *CreateSpec) (string, error) { + url := c.Resource(dataSetsPath(vm)) + var res string + err := c.Do(ctx, url.Request(http.MethodPost, spec), &res) + return res, err +} + +// DeleteDataSet deletes an existing data set from the given virtual machine. +// The operation will fail if the data set is not empty. +// Set the force flag to delete a non-empty data set. +func (c *Manager) DeleteDataSet(ctx context.Context, vm string, dataSet string, force bool) error { + url := c.Resource(dataSetPath(vm, dataSet)) + if force { + url.WithParam("force", strconv.FormatBool(force)) + } + return c.Do(ctx, url.Request(http.MethodDelete), nil) +} + +// GetDataSet retrieves information about the given data set. +func (c *Manager) GetDataSet(ctx context.Context, vm string, dataSet string) (*Info, error) { + url := c.Resource(dataSetPath(vm, dataSet)) + var res Info + err := c.Do(ctx, url.Request(http.MethodGet), &res) + return &res, err +} + +// UpdateDataSet modifies the given data set. +func (c *Manager) UpdateDataSet(ctx context.Context, vm string, dataSet string, spec *UpdateSpec) error { + url := c.Resource(dataSetPath(vm, dataSet)) + return c.Do(ctx, url.Request(http.MethodPatch, spec), nil) +} + +// ListDataSets returns a list of brief descriptions of the data sets on with the given virtual machine. +func (c *Manager) ListDataSets(ctx context.Context, vm string) ([]Summary, error) { + url := c.Resource(dataSetsPath(vm)) + var res []Summary + err := c.Do(ctx, url.Request(http.MethodGet), &res) + return res, err +} + +// SetEntry creates or updates an entry in the given data set. +// If an entry with the given key already exists, it will be overwritten. +// The key can be at most 4096 bytes. The value can be at most 1MB. +func (c *Manager) SetEntry(ctx context.Context, vm string, dataSet string, key string, value string) error { + url := c.Resource(entryPath(vm, dataSet, key)) + return c.Do(ctx, url.Request(http.MethodPut, value), nil) +} + +// GetEntry returns the value of the data set entry with the given key. +func (c *Manager) GetEntry(ctx context.Context, vm string, dataSet string, key string) (string, error) { + url := c.Resource(entryPath(vm, dataSet, key)) + var res string + err := c.Do(ctx, url.Request(http.MethodGet), &res) + return res, err +} + +// DeleteEntry removes an existing entry from the given data set. +func (c *Manager) DeleteEntry(ctx context.Context, vm string, dataSet string, key string) error { + url := c.Resource(entryPath(vm, dataSet, key)) + return c.Do(ctx, url.Request(http.MethodDelete), nil) +} + +// ListEntries returns a list of all entry keys in the given data set. +func (c *Manager) ListEntries(ctx context.Context, vm string, dataSet string) ([]string, error) { + url := c.Resource(entriesPath(vm, dataSet)) + var res []string + err := c.Do(ctx, url.Request(http.MethodGet), &res) + return res, err +} diff --git a/vendor/github.com/vmware/govmomi/vapi/vm/internal/internal.go b/vendor/github.com/vmware/govmomi/vapi/vm/internal/internal.go new file mode 100644 index 00000000000..b016caa1a70 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vapi/vm/internal/internal.go @@ -0,0 +1,24 @@ +/* +Copyright (c) 2023-2023 VMware, Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package internal + +const ( + // VCenterVMPath is the REST endpoint for the virtual machine API + VCenterVMPath = "/api/vcenter/vm" + // LegacyVCenterVMPath is the legacy REST endpoint for the virtual machine API, relative to the "/rest" base path + LegacyVCenterVMPath = "/vcenter/vm" +) diff --git a/vendor/github.com/vmware/govmomi/view/list_view.go b/vendor/github.com/vmware/govmomi/view/list_view.go index e8cfb504341..4958941cc65 100644 --- a/vendor/github.com/vmware/govmomi/view/list_view.go +++ b/vendor/github.com/vmware/govmomi/view/list_view.go @@ -34,29 +34,41 @@ func NewListView(c *vim25.Client, ref types.ManagedObjectReference) *ListView { } } -func (v ListView) Add(ctx context.Context, refs []types.ManagedObjectReference) error { +func (v ListView) Add(ctx context.Context, refs []types.ManagedObjectReference) ([]types.ManagedObjectReference, error) { req := types.ModifyListView{ This: v.Reference(), Add: refs, } - _, err := methods.ModifyListView(ctx, v.Client(), &req) - return err + res, err := methods.ModifyListView(ctx, v.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil } -func (v ListView) Remove(ctx context.Context, refs []types.ManagedObjectReference) error { +func (v ListView) Remove(ctx context.Context, refs []types.ManagedObjectReference) ([]types.ManagedObjectReference, error) { req := types.ModifyListView{ This: v.Reference(), Remove: refs, } - _, err := methods.ModifyListView(ctx, v.Client(), &req) - return err + res, err := methods.ModifyListView(ctx, v.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil } -func (v ListView) Reset(ctx context.Context, refs []types.ManagedObjectReference) error { +func (v ListView) Reset(ctx context.Context, refs []types.ManagedObjectReference) ([]types.ManagedObjectReference, error) { req := types.ResetListView{ This: v.Reference(), Obj: refs, } - _, err := methods.ResetListView(ctx, v.Client(), &req) - return err + res, err := methods.ResetListView(ctx, v.Client(), &req) + if err != nil { + return nil, err + } + + return res.Returnval, nil } diff --git a/vendor/github.com/vmware/govmomi/view/task_view.go b/vendor/github.com/vmware/govmomi/view/task_view.go index 68f62f8d107..4e1beef38c5 100644 --- a/vendor/github.com/vmware/govmomi/view/task_view.go +++ b/vendor/github.com/vmware/govmomi/view/task_view.go @@ -73,7 +73,7 @@ func (v TaskView) Collect(ctx context.Context, f func([]types.TaskInfo)) error { tasks = change.Val.(types.ArrayOfManagedObjectReference).ManagedObjectReference if len(tasks) != 0 { reset = func() { - _ = v.Reset(ctx, tasks) + _, _ = v.Reset(ctx, tasks) // Remember any tasks we've reported as complete already, // to avoid reporting multiple times when Reset is triggered. @@ -113,7 +113,7 @@ func (v TaskView) Collect(ctx context.Context, f func([]types.TaskInfo)) error { if reset != nil { reset() } else if len(prune) != 0 { - _ = v.Remove(ctx, prune) + _, _ = v.Remove(ctx, prune) } if len(tasks) != 0 && len(infos) == 0 { diff --git a/vendor/github.com/vmware/govmomi/vim25/client.go b/vendor/github.com/vmware/govmomi/vim25/client.go index b14cea85202..6101330953e 100644 --- a/vendor/github.com/vmware/govmomi/vim25/client.go +++ b/vendor/github.com/vmware/govmomi/vim25/client.go @@ -1,11 +1,11 @@ /* -Copyright (c) 2015-2016 VMware, Inc. All Rights Reserved. +Copyright (c) 2015-2023 VMware, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at - http://www.apache.org/licenses/LICENSE-2.0 +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, @@ -32,7 +32,7 @@ import ( const ( Namespace = "vim25" - Version = "7.0" + Version = "8.0.2.0" Path = "/sdk" ) diff --git a/vendor/github.com/vmware/govmomi/vim25/json/LICENSE b/vendor/github.com/vmware/govmomi/vim25/json/LICENSE new file mode 100644 index 00000000000..6a66aea5eaf --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 The Go Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/vmware/govmomi/vim25/json/README.md b/vendor/github.com/vmware/govmomi/vim25/json/README.md new file mode 100644 index 00000000000..6cbe80349a5 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/README.md @@ -0,0 +1,9 @@ +# JSON with Discriminators + +The source code in this directory was copied from Go 1.17.13's `encoding/json` package in order to add support for JSON discriminators. Please use the following command to review the diff: + +```shell +C1="$(git log --pretty=format:'%h' --no-patch --grep='Vendor Go 1.17.13 encoding/json')" && \ +C2="$(git log --pretty=format:'%h' --no-patch --grep='JSON Encoding w Discriminator Support')" && \ +git diff "${C1}".."${C2}" +``` diff --git a/vendor/github.com/vmware/govmomi/vim25/json/decode.go b/vendor/github.com/vmware/govmomi/vim25/json/decode.go new file mode 100644 index 00000000000..6a92a2410bc --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/decode.go @@ -0,0 +1,1319 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Represents JSON data structure using native Go types: booleans, floats, +// strings, arrays, and maps. + +package json + +import ( + "encoding" + "encoding/base64" + "fmt" + "reflect" + "strconv" + "strings" + "unicode" + "unicode/utf16" + "unicode/utf8" +) + +// Unmarshal parses the JSON-encoded data and stores the result +// in the value pointed to by v. If v is nil or not a pointer, +// Unmarshal returns an InvalidUnmarshalError. +// +// Unmarshal uses the inverse of the encodings that +// Marshal uses, allocating maps, slices, and pointers as necessary, +// with the following additional rules: +// +// To unmarshal JSON into a pointer, Unmarshal first handles the case of +// the JSON being the JSON literal null. In that case, Unmarshal sets +// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into +// the value pointed at by the pointer. If the pointer is nil, Unmarshal +// allocates a new value for it to point to. +// +// To unmarshal JSON into a value implementing the Unmarshaler interface, +// Unmarshal calls that value's UnmarshalJSON method, including +// when the input is a JSON null. +// Otherwise, if the value implements encoding.TextUnmarshaler +// and the input is a JSON quoted string, Unmarshal calls that value's +// UnmarshalText method with the unquoted form of the string. +// +// To unmarshal JSON into a struct, Unmarshal matches incoming object +// keys to the keys used by Marshal (either the struct field name or its tag), +// preferring an exact match but also accepting a case-insensitive match. By +// default, object keys which don't have a corresponding struct field are +// ignored (see Decoder.DisallowUnknownFields for an alternative). +// +// To unmarshal JSON into an interface value, +// Unmarshal stores one of these in the interface value: +// +// bool, for JSON booleans +// float64, for JSON numbers +// string, for JSON strings +// []interface{}, for JSON arrays +// map[string]interface{}, for JSON objects +// nil for JSON null +// +// To unmarshal a JSON array into a slice, Unmarshal resets the slice length +// to zero and then appends each element to the slice. +// As a special case, to unmarshal an empty JSON array into a slice, +// Unmarshal replaces the slice with a new empty slice. +// +// To unmarshal a JSON array into a Go array, Unmarshal decodes +// JSON array elements into corresponding Go array elements. +// If the Go array is smaller than the JSON array, +// the additional JSON array elements are discarded. +// If the JSON array is smaller than the Go array, +// the additional Go array elements are set to zero values. +// +// To unmarshal a JSON object into a map, Unmarshal first establishes a map to +// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal +// reuses the existing map, keeping existing entries. Unmarshal then stores +// key-value pairs from the JSON object into the map. The map's key type must +// either be any string type, an integer, implement json.Unmarshaler, or +// implement encoding.TextUnmarshaler. +// +// If a JSON value is not appropriate for a given target type, +// or if a JSON number overflows the target type, Unmarshal +// skips that field and completes the unmarshaling as best it can. +// If no more serious errors are encountered, Unmarshal returns +// an UnmarshalTypeError describing the earliest such error. In any +// case, it's not guaranteed that all the remaining fields following +// the problematic one will be unmarshaled into the target object. +// +// The JSON null value unmarshals into an interface, map, pointer, or slice +// by setting that Go value to nil. Because null is often used in JSON to mean +// ``not present,'' unmarshaling a JSON null into any other Go type has no effect +// on the value and produces no error. +// +// When unmarshaling quoted strings, invalid UTF-8 or +// invalid UTF-16 surrogate pairs are not treated as an error. +// Instead, they are replaced by the Unicode replacement +// character U+FFFD. +// +func Unmarshal(data []byte, v interface{}) error { + // Check for well-formedness. + // Avoids filling out half a data structure + // before discovering a JSON syntax error. + var d decodeState + err := checkValid(data, &d.scan) + if err != nil { + return err + } + + d.init(data) + return d.unmarshal(v) +} + +// Unmarshaler is the interface implemented by types +// that can unmarshal a JSON description of themselves. +// The input can be assumed to be a valid encoding of +// a JSON value. UnmarshalJSON must copy the JSON data +// if it wishes to retain the data after returning. +// +// By convention, to approximate the behavior of Unmarshal itself, +// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op. +type Unmarshaler interface { + UnmarshalJSON([]byte) error +} + +// An UnmarshalTypeError describes a JSON value that was +// not appropriate for a value of a specific Go type. +type UnmarshalTypeError struct { + Value string // description of JSON value - "bool", "array", "number -5" + Type reflect.Type // type of Go value it could not be assigned to + Offset int64 // error occurred after reading Offset bytes + Struct string // name of the struct type containing the field + Field string // the full path from root node to the field +} + +func (e *UnmarshalTypeError) Error() string { + if e.Struct != "" || e.Field != "" { + return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String() + } + return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String() +} + +// An UnmarshalFieldError describes a JSON object key that +// led to an unexported (and therefore unwritable) struct field. +// +// Deprecated: No longer used; kept for compatibility. +type UnmarshalFieldError struct { + Key string + Type reflect.Type + Field reflect.StructField +} + +func (e *UnmarshalFieldError) Error() string { + return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String() +} + +// An InvalidUnmarshalError describes an invalid argument passed to Unmarshal. +// (The argument to Unmarshal must be a non-nil pointer.) +type InvalidUnmarshalError struct { + Type reflect.Type +} + +func (e *InvalidUnmarshalError) Error() string { + if e.Type == nil { + return "json: Unmarshal(nil)" + } + + if e.Type.Kind() != reflect.Ptr { + return "json: Unmarshal(non-pointer " + e.Type.String() + ")" + } + return "json: Unmarshal(nil " + e.Type.String() + ")" +} + +func (d *decodeState) unmarshal(v interface{}) error { + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr || rv.IsNil() { + return &InvalidUnmarshalError{reflect.TypeOf(v)} + } + + d.scan.reset() + d.scanWhile(scanSkipSpace) + // We decode rv not rv.Elem because the Unmarshaler interface + // test must be applied at the top level of the value. + err := d.value(rv) + if err != nil { + return d.addErrorContext(err) + } + return d.savedError +} + +// A Number represents a JSON number literal. +type Number string + +// String returns the literal text of the number. +func (n Number) String() string { return string(n) } + +// Float64 returns the number as a float64. +func (n Number) Float64() (float64, error) { + return strconv.ParseFloat(string(n), 64) +} + +// Int64 returns the number as an int64. +func (n Number) Int64() (int64, error) { + return strconv.ParseInt(string(n), 10, 64) +} + +// An errorContext provides context for type errors during decoding. +type errorContext struct { + Struct reflect.Type + FieldStack []string +} + +// decodeState represents the state while decoding a JSON value. +type decodeState struct { + data []byte + off int // next read offset in data + opcode int // last read result + scan scanner + errorContext *errorContext + savedError error + useNumber bool + disallowUnknownFields bool + + discriminatorTypeFieldName string + discriminatorValueFieldName string + discriminatorToTypeFn DiscriminatorToTypeFunc +} + +// readIndex returns the position of the last byte read. +func (d *decodeState) readIndex() int { + return d.off - 1 +} + +// phasePanicMsg is used as a panic message when we end up with something that +// shouldn't happen. It can indicate a bug in the JSON decoder, or that +// something is editing the data slice while the decoder executes. +const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?" + +func (d *decodeState) init(data []byte) *decodeState { + d.data = data + d.off = 0 + d.savedError = nil + if d.errorContext != nil { + d.errorContext.Struct = nil + // Reuse the allocated space for the FieldStack slice. + d.errorContext.FieldStack = d.errorContext.FieldStack[:0] + } + return d +} + +// saveError saves the first err it is called with, +// for reporting at the end of the unmarshal. +func (d *decodeState) saveError(err error) { + if d.savedError == nil { + d.savedError = d.addErrorContext(err) + } +} + +// addErrorContext returns a new error enhanced with information from d.errorContext +func (d *decodeState) addErrorContext(err error) error { + if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) { + switch err := err.(type) { + case *UnmarshalTypeError: + err.Struct = d.errorContext.Struct.Name() + err.Field = strings.Join(d.errorContext.FieldStack, ".") + } + } + return err +} + +// skip scans to the end of what was started. +func (d *decodeState) skip() { + s, data, i := &d.scan, d.data, d.off + depth := len(s.parseState) + for { + op := s.step(s, data[i]) + i++ + if len(s.parseState) < depth { + d.off = i + d.opcode = op + return + } + } +} + +// scanNext processes the byte at d.data[d.off]. +func (d *decodeState) scanNext() { + if d.off < len(d.data) { + d.opcode = d.scan.step(&d.scan, d.data[d.off]) + d.off++ + } else { + d.opcode = d.scan.eof() + d.off = len(d.data) + 1 // mark processed EOF with len+1 + } +} + +// scanWhile processes bytes in d.data[d.off:] until it +// receives a scan code not equal to op. +func (d *decodeState) scanWhile(op int) { + s, data, i := &d.scan, d.data, d.off + for i < len(data) { + newOp := s.step(s, data[i]) + i++ + if newOp != op { + d.opcode = newOp + d.off = i + return + } + } + + d.off = len(data) + 1 // mark processed EOF with len+1 + d.opcode = d.scan.eof() +} + +// rescanLiteral is similar to scanWhile(scanContinue), but it specialises the +// common case where we're decoding a literal. The decoder scans the input +// twice, once for syntax errors and to check the length of the value, and the +// second to perform the decoding. +// +// Only in the second step do we use decodeState to tokenize literals, so we +// know there aren't any syntax errors. We can take advantage of that knowledge, +// and scan a literal's bytes much more quickly. +func (d *decodeState) rescanLiteral() { + data, i := d.data, d.off +Switch: + switch data[i-1] { + case '"': // string + for ; i < len(data); i++ { + switch data[i] { + case '\\': + i++ // escaped char + case '"': + i++ // tokenize the closing quote too + break Switch + } + } + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': // number + for ; i < len(data); i++ { + switch data[i] { + case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + '.', 'e', 'E', '+', '-': + default: + break Switch + } + } + case 't': // true + i += len("rue") + case 'f': // false + i += len("alse") + case 'n': // null + i += len("ull") + } + if i < len(data) { + d.opcode = stateEndValue(&d.scan, data[i]) + } else { + d.opcode = scanEnd + } + d.off = i + 1 +} + +// value consumes a JSON value from d.data[d.off-1:], decoding into v, and +// reads the following byte ahead. If v is invalid, the value is discarded. +// The first byte of the value has been read already. +func (d *decodeState) value(v reflect.Value) error { + switch d.opcode { + default: + panic(phasePanicMsg) + + case scanBeginArray: + if v.IsValid() { + if err := d.array(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() + + case scanBeginObject: + if v.IsValid() { + if err := d.object(v); err != nil { + return err + } + } else { + d.skip() + } + d.scanNext() + + case scanBeginLiteral: + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.rescanLiteral() + + if v.IsValid() { + if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil { + return err + } + } + } + return nil +} + +type unquotedValue struct{} + +// valueQuoted is like value but decodes a +// quoted string literal or literal null into an interface value. +// If it finds anything other than a quoted string literal or null, +// valueQuoted returns unquotedValue{}. +func (d *decodeState) valueQuoted() interface{} { + switch d.opcode { + default: + panic(phasePanicMsg) + + case scanBeginArray, scanBeginObject: + d.skip() + d.scanNext() + + case scanBeginLiteral: + v := d.literalInterface() + switch v.(type) { + case nil, string: + return v + } + } + return unquotedValue{} +} + +// indirect walks down v allocating pointers as needed, +// until it gets to a non-pointer. +// If it encounters an Unmarshaler, indirect stops and returns that. +// If decodingNull is true, indirect stops at the first settable pointer so it +// can be set to nil. +func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) { + // Issue #24153 indicates that it is generally not a guaranteed property + // that you may round-trip a reflect.Value by calling Value.Addr().Elem() + // and expect the value to still be settable for values derived from + // unexported embedded struct fields. + // + // The logic below effectively does this when it first addresses the value + // (to satisfy possible pointer methods) and continues to dereference + // subsequent pointers as necessary. + // + // After the first round-trip, we set v back to the original value to + // preserve the original RW flags contained in reflect.Value. + v0 := v + haveAddr := false + + // If v is a named type and is addressable, + // start with its address, so that if the type has pointer methods, + // we find them. + if v.Kind() != reflect.Ptr && v.Type().Name() != "" && v.CanAddr() { + haveAddr = true + v = v.Addr() + } + for { + // Load value from interface, but only if the result will be + // usefully addressable. + if v.Kind() == reflect.Interface && !v.IsNil() { + e := v.Elem() + if e.Kind() == reflect.Ptr && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Ptr) { + haveAddr = false + v = e + continue + } + } + + if v.Kind() != reflect.Ptr { + break + } + + if decodingNull && v.CanSet() { + break + } + + // Prevent infinite loop if v is an interface pointing to its own address: + // var v interface{} + // v = &v + if v.Elem().Kind() == reflect.Interface && v.Elem().Elem() == v { + v = v.Elem() + break + } + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + if v.Type().NumMethod() > 0 && v.CanInterface() { + if u, ok := v.Interface().(Unmarshaler); ok { + return u, nil, reflect.Value{} + } + if !decodingNull { + if u, ok := v.Interface().(encoding.TextUnmarshaler); ok { + return nil, u, reflect.Value{} + } + } + } + + if haveAddr { + v = v0 // restore original value after round-trip Value.Addr().Elem() + haveAddr = false + } else { + v = v.Elem() + } + } + return nil, nil, v +} + +// array consumes an array from d.data[d.off-1:], decoding into v. +// The first byte of the array ('[') has been read already. +func (d *decodeState) array(v reflect.Value) error { + // Check for unmarshaler. + u, ut, pv := indirect(v, false) + if u != nil { + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) + } + if ut != nil { + d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + } + v = pv + + // Check type of target. + switch v.Kind() { + case reflect.Interface: + if v.NumMethod() == 0 { + // Decoding into nil interface? Switch to non-reflect code. + ai := d.arrayInterface() + v.Set(reflect.ValueOf(ai)) + return nil + } + // Otherwise it's invalid. + fallthrough + default: + d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + case reflect.Array, reflect.Slice: + break + } + + i := 0 + for { + // Look ahead for ] - can only happen on first iteration. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { + break + } + + // Get element of array, growing if necessary. + if v.Kind() == reflect.Slice { + // Grow slice if necessary + if i >= v.Cap() { + newcap := v.Cap() + v.Cap()/2 + if newcap < 4 { + newcap = 4 + } + newv := reflect.MakeSlice(v.Type(), v.Len(), newcap) + reflect.Copy(newv, v) + v.Set(newv) + } + if i >= v.Len() { + v.SetLen(i + 1) + } + } + + if i < v.Len() { + // Decode into element. + if err := d.value(v.Index(i)); err != nil { + return err + } + } else { + // Ran out of fixed array: skip. + if err := d.value(reflect.Value{}); err != nil { + return err + } + } + i++ + + // Next token must be , or ]. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { + break + } + if d.opcode != scanArrayValue { + panic(phasePanicMsg) + } + } + + if i < v.Len() { + if v.Kind() == reflect.Array { + // Array. Zero the rest. + z := reflect.Zero(v.Type().Elem()) + for ; i < v.Len(); i++ { + v.Index(i).Set(z) + } + } else { + v.SetLen(i) + } + } + if i == 0 && v.Kind() == reflect.Slice { + v.Set(reflect.MakeSlice(v.Type(), 0, 0)) + } + return nil +} + +var nullLiteral = []byte("null") +var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() + +// object consumes an object from d.data[d.off-1:], decoding into v. +// The first byte ('{') of the object has been read already. +func (d *decodeState) object(v reflect.Value) error { + // Check for unmarshaler. + u, ut, pv := indirect(v, false) + if u != nil { + start := d.readIndex() + d.skip() + return u.UnmarshalJSON(d.data[start:d.off]) + } + if ut != nil { + d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)}) + d.skip() + return nil + } + v = pv + t := v.Type() + + // Decoding into nil interface? Switch to non-reflect code. + if v.Kind() == reflect.Interface && v.NumMethod() == 0 && !d.isDiscriminatorSet() { + oi := d.objectInterface() + v.Set(reflect.ValueOf(oi)) + return nil + } + + var fields structFields + + // Check type of target: + // struct or + // map[T1]T2 where T1 is string, an integer type, + // or an encoding.TextUnmarshaler + switch v.Kind() { + case reflect.Map: + // Map key must either have string kind, have an integer kind, + // or be an encoding.TextUnmarshaler. + switch t.Key().Kind() { + case reflect.String, + reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + default: + if !reflect.PtrTo(t.Key()).Implements(textUnmarshalerType) { + d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) + d.skip() + return nil + } + } + if v.IsNil() { + v.Set(reflect.MakeMap(t)) + } + case reflect.Struct: + fields = cachedTypeFields(t) + // ok + default: + if d.isDiscriminatorSet() { + return d.discriminatorInterfaceDecode(t, v) + } + d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)}) + d.skip() + return nil + } + + var mapElem reflect.Value + var origErrorContext errorContext + if d.errorContext != nil { + origErrorContext = *d.errorContext + } + + for { + // Read opening " of string key or closing }. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read key. + start := d.readIndex() + d.rescanLiteral() + item := d.data[start:d.readIndex()] + key, ok := unquoteBytes(item) + if !ok { + panic(phasePanicMsg) + } + + // Figure out field corresponding to key. + var subv reflect.Value + destring := false // whether the value is wrapped in a string to be decoded first + + if v.Kind() == reflect.Map { + elemType := t.Elem() + if !mapElem.IsValid() { + mapElem = reflect.New(elemType).Elem() + } else { + mapElem.Set(reflect.Zero(elemType)) + } + subv = mapElem + } else { + var f *field + if i, ok := fields.nameIndex[string(key)]; ok { + // Found an exact name match. + f = &fields.list[i] + } else { + // Fall back to the expensive case-insensitive + // linear search. + for i := range fields.list { + ff := &fields.list[i] + if ff.equalFold(ff.nameBytes, key) { + f = ff + break + } + } + } + if f != nil { + subv = v + destring = f.quoted + for _, i := range f.index { + if subv.Kind() == reflect.Ptr { + if subv.IsNil() { + // If a struct embeds a pointer to an unexported type, + // it is not possible to set a newly allocated value + // since the field is unexported. + // + // See https://golang.org/issue/21357 + if !subv.CanSet() { + d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem())) + // Invalidate subv to ensure d.value(subv) skips over + // the JSON value without assigning it to subv. + subv = reflect.Value{} + destring = false + break + } + subv.Set(reflect.New(subv.Type().Elem())) + } + subv = subv.Elem() + } + subv = subv.Field(i) + } + if d.errorContext == nil { + d.errorContext = new(errorContext) + } + d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name) + d.errorContext.Struct = t + } else if d.disallowUnknownFields { + d.saveError(fmt.Errorf("json: unknown field %q", key)) + } + } + + // Read : before value. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanObjectKey { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + + if destring { + switch qv := d.valueQuoted().(type) { + case nil: + if err := d.literalStore(nullLiteral, subv, false); err != nil { + return err + } + case string: + if err := d.literalStore([]byte(qv), subv, true); err != nil { + return err + } + default: + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type())) + } + } else { + if err := d.value(subv); err != nil { + return err + } + } + + // Write value back to map; + // if using struct, subv points into struct already. + if v.Kind() == reflect.Map { + kt := t.Key() + var kv reflect.Value + switch { + case reflect.PtrTo(kt).Implements(textUnmarshalerType): + kv = reflect.New(kt) + if err := d.literalStore(item, kv, true); err != nil { + return err + } + kv = kv.Elem() + case kt.Kind() == reflect.String: + kv = reflect.ValueOf(key).Convert(kt) + default: + switch kt.Kind() { + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + s := string(key) + n, err := strconv.ParseInt(s, 10, 64) + if err != nil || reflect.Zero(kt).OverflowInt(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) + break + } + kv = reflect.ValueOf(n).Convert(kt) + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + s := string(key) + n, err := strconv.ParseUint(s, 10, 64) + if err != nil || reflect.Zero(kt).OverflowUint(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)}) + break + } + kv = reflect.ValueOf(n).Convert(kt) + default: + panic("json: Unexpected key type") // should never occur + } + } + if kv.IsValid() { + if !d.isDiscriminatorSet() || kv.String() != d.discriminatorTypeFieldName { + v.SetMapIndex(kv, subv) + } + } + } + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.errorContext != nil { + // Reset errorContext to its original state. + // Keep the same underlying array for FieldStack, to reuse the + // space and avoid unnecessary allocs. + d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)] + d.errorContext.Struct = origErrorContext.Struct + } + if d.opcode == scanEndObject { + break + } + if d.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + return nil +} + +// convertNumber converts the number literal s to a float64 or a Number +// depending on the setting of d.useNumber. +func (d *decodeState) convertNumber(s string) (interface{}, error) { + if d.useNumber { + return Number(s), nil + } + f, err := strconv.ParseFloat(s, 64) + if err != nil { + return nil, &UnmarshalTypeError{Value: "number " + s, Type: reflect.TypeOf(0.0), Offset: int64(d.off)} + } + return f, nil +} + +var numberType = reflect.TypeOf(Number("")) + +// literalStore decodes a literal stored in item into v. +// +// fromQuoted indicates whether this literal came from unwrapping a +// string from the ",string" struct tag option. this is used only to +// produce more helpful error messages. +func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error { + // Check for unmarshaler. + if len(item) == 0 { + //Empty string given + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return nil + } + isNull := item[0] == 'n' // null + u, ut, pv := indirect(v, isNull) + if u != nil { + return u.UnmarshalJSON(item) + } + if ut != nil { + if item[0] != '"' { + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + return nil + } + val := "number" + switch item[0] { + case 'n': + val = "null" + case 't', 'f': + val = "bool" + } + d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())}) + return nil + } + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + return ut.UnmarshalText(s) + } + + v = pv + + switch c := item[0]; c { + case 'n': // null + // The main parser checks that only true and false can reach here, + // but if this was a quoted string input, it could be anything. + if fromQuoted && string(item) != "null" { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + break + } + switch v.Kind() { + case reflect.Interface, reflect.Ptr, reflect.Map, reflect.Slice: + v.Set(reflect.Zero(v.Type())) + // otherwise, ignore null for primitives/string + } + case 't', 'f': // true, false + value := item[0] == 't' + // The main parser checks that only true and false can reach here, + // but if this was a quoted string input, it could be anything. + if fromQuoted && string(item) != "true" && string(item) != "false" { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + break + } + switch v.Kind() { + default: + if fromQuoted { + d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())) + } else { + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) + } + case reflect.Bool: + v.SetBool(value) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(value)) + } else { + d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())}) + } + } + + case '"': // string + s, ok := unquoteBytes(item) + if !ok { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + switch v.Kind() { + default: + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + case reflect.Slice: + if v.Type().Elem().Kind() != reflect.Uint8 { + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + b := make([]byte, base64.StdEncoding.DecodedLen(len(s))) + n, err := base64.StdEncoding.Decode(b, s) + if err != nil { + d.saveError(err) + break + } + v.SetBytes(b[:n]) + case reflect.String: + if v.Type() == numberType && !isValidNumber(string(s)) { + return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item) + } + v.SetString(string(s)) + case reflect.Interface: + if v.NumMethod() == 0 { + v.Set(reflect.ValueOf(string(s))) + } else { + d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())}) + } + } + + default: // number + if c != '-' && (c < '0' || c > '9') { + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + panic(phasePanicMsg) + } + s := string(item) + switch v.Kind() { + default: + if v.Kind() == reflect.String && v.Type() == numberType { + // s must be a valid number, because it's + // already been tokenized. + v.SetString(s) + break + } + if fromQuoted { + return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()) + } + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) + case reflect.Interface: + n, err := d.convertNumber(s) + if err != nil { + d.saveError(err) + break + } + if v.NumMethod() != 0 { + d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.Set(reflect.ValueOf(n)) + + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + n, err := strconv.ParseInt(s, 10, 64) + if err != nil || v.OverflowInt(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetInt(n) + + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + n, err := strconv.ParseUint(s, 10, 64) + if err != nil || v.OverflowUint(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetUint(n) + + case reflect.Float32, reflect.Float64: + n, err := strconv.ParseFloat(s, v.Type().Bits()) + if err != nil || v.OverflowFloat(n) { + d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: v.Type(), Offset: int64(d.readIndex())}) + break + } + v.SetFloat(n) + } + } + return nil +} + +// The xxxInterface routines build up a value to be stored +// in an empty interface. They are not strictly necessary, +// but they avoid the weight of reflection in this common case. + +// valueInterface is like value but returns interface{} +func (d *decodeState) valueInterface() (val interface{}) { + switch d.opcode { + default: + panic(phasePanicMsg) + case scanBeginArray: + val = d.arrayInterface() + d.scanNext() + case scanBeginObject: + val = d.objectInterface() + d.scanNext() + case scanBeginLiteral: + val = d.literalInterface() + } + return +} + +// arrayInterface is like array but returns []interface{}. +func (d *decodeState) arrayInterface() []interface{} { + var v = make([]interface{}, 0) + for { + // Look ahead for ] - can only happen on first iteration. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndArray { + break + } + + v = append(v, d.valueInterface()) + + // Next token must be , or ]. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndArray { + break + } + if d.opcode != scanArrayValue { + panic(phasePanicMsg) + } + } + return v +} + +// objectInterface is like object but returns map[string]interface{}. +func (d *decodeState) objectInterface() map[string]interface{} { + m := make(map[string]interface{}) + for { + // Read opening " of string key or closing }. + d.scanWhile(scanSkipSpace) + if d.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if d.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read string key. + start := d.readIndex() + d.rescanLiteral() + item := d.data[start:d.readIndex()] + key, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + + // Read : before value. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode != scanObjectKey { + panic(phasePanicMsg) + } + d.scanWhile(scanSkipSpace) + + // Read value. + m[key] = d.valueInterface() + + // Next token must be , or }. + if d.opcode == scanSkipSpace { + d.scanWhile(scanSkipSpace) + } + if d.opcode == scanEndObject { + break + } + if d.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + return m +} + +// literalInterface consumes and returns a literal from d.data[d.off-1:] and +// it reads the following byte ahead. The first byte of the literal has been +// read already (that's how the caller knows it's a literal). +func (d *decodeState) literalInterface() interface{} { + // All bytes inside literal return scanContinue op code. + start := d.readIndex() + d.rescanLiteral() + + item := d.data[start:d.readIndex()] + + switch c := item[0]; c { + case 'n': // null + return nil + + case 't', 'f': // true, false + return c == 't' + + case '"': // string + s, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + return s + + default: // number + if c != '-' && (c < '0' || c > '9') { + panic(phasePanicMsg) + } + n, err := d.convertNumber(string(item)) + if err != nil { + d.saveError(err) + } + return n + } +} + +// getu4 decodes \uXXXX from the beginning of s, returning the hex value, +// or it returns -1. +func getu4(s []byte) rune { + if len(s) < 6 || s[0] != '\\' || s[1] != 'u' { + return -1 + } + var r rune + for _, c := range s[2:6] { + switch { + case '0' <= c && c <= '9': + c = c - '0' + case 'a' <= c && c <= 'f': + c = c - 'a' + 10 + case 'A' <= c && c <= 'F': + c = c - 'A' + 10 + default: + return -1 + } + r = r*16 + rune(c) + } + return r +} + +// unquote converts a quoted JSON string literal s into an actual string t. +// The rules are different than for Go, so cannot use strconv.Unquote. +func unquote(s []byte) (t string, ok bool) { + s, ok = unquoteBytes(s) + t = string(s) + return +} + +func unquoteBytes(s []byte) (t []byte, ok bool) { + if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' { + return + } + s = s[1 : len(s)-1] + + // Check for unusual characters. If there are none, + // then no unquoting is needed, so return a slice of the + // original bytes. + r := 0 + for r < len(s) { + c := s[r] + if c == '\\' || c == '"' || c < ' ' { + break + } + if c < utf8.RuneSelf { + r++ + continue + } + rr, size := utf8.DecodeRune(s[r:]) + if rr == utf8.RuneError && size == 1 { + break + } + r += size + } + if r == len(s) { + return s, true + } + + b := make([]byte, len(s)+2*utf8.UTFMax) + w := copy(b, s[0:r]) + for r < len(s) { + // Out of room? Can only happen if s is full of + // malformed UTF-8 and we're replacing each + // byte with RuneError. + if w >= len(b)-2*utf8.UTFMax { + nb := make([]byte, (len(b)+utf8.UTFMax)*2) + copy(nb, b[0:w]) + b = nb + } + switch c := s[r]; { + case c == '\\': + r++ + if r >= len(s) { + return + } + switch s[r] { + default: + return + case '"', '\\', '/', '\'': + b[w] = s[r] + r++ + w++ + case 'b': + b[w] = '\b' + r++ + w++ + case 'f': + b[w] = '\f' + r++ + w++ + case 'n': + b[w] = '\n' + r++ + w++ + case 'r': + b[w] = '\r' + r++ + w++ + case 't': + b[w] = '\t' + r++ + w++ + case 'u': + r-- + rr := getu4(s[r:]) + if rr < 0 { + return + } + r += 6 + if utf16.IsSurrogate(rr) { + rr1 := getu4(s[r:]) + if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar { + // A valid pair; consume. + r += 6 + w += utf8.EncodeRune(b[w:], dec) + break + } + // Invalid surrogate; fall back to replacement rune. + rr = unicode.ReplacementChar + } + w += utf8.EncodeRune(b[w:], rr) + } + + // Quote, control characters are invalid. + case c == '"', c < ' ': + return + + // ASCII + case c < utf8.RuneSelf: + b[w] = c + r++ + w++ + + // Coerce to well-formed UTF-8. + default: + rr, size := utf8.DecodeRune(s[r:]) + r += size + w += utf8.EncodeRune(b[w:], rr) + } + } + return b[0:w], true +} diff --git a/vendor/github.com/vmware/govmomi/vim25/json/discriminator.go b/vendor/github.com/vmware/govmomi/vim25/json/discriminator.go new file mode 100644 index 00000000000..ce315dd527a --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/discriminator.go @@ -0,0 +1,568 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package json + +import ( + "fmt" + "reflect" + "regexp" + "strconv" + "sync" +) + +// DiscriminatorToTypeFunc is used to get a reflect.Type from its +// discriminator. +type DiscriminatorToTypeFunc func(discriminator string) (reflect.Type, bool) + +// TypeToDiscriminatorFunc is used to get a discriminator string from a +// reflect.Type. Empty return value suppresses discriminator rendering. +type TypeToDiscriminatorFunc func(reflect.Type) (discriminator string) + +// DefaultDiscriminatorFunc is shorthand for the ShortName func and is used when +// no other discriminator func is set explicitly +var DefaultDiscriminatorFunc = ShortName + +// ShortName returns the type name in golang without the package name +func ShortName(t reflect.Type) (discriminator string) { + tn := t.Name() + if tn == "" { + return t.String() + } + return tn +} + +// FullName return the name of the type prefixed with the package name as +// appropriate +func FullName(t reflect.Type) (discriminator string) { + tn := t.Name() + if tn == "" { + return t.String() + } + if pp := t.PkgPath(); pp != "" { + return fmt.Sprintf("%s.%s", pp, tn) + } + return tn +} + +// DiscriminatorEncodeMode is a mask that describes the different encode +// options. +type DiscriminatorEncodeMode uint8 + +const ( + // DiscriminatorEncodeTypeNameRootValue causes the type name to be encoded + // for the root value. + DiscriminatorEncodeTypeNameRootValue DiscriminatorEncodeMode = 1 << iota + + // DiscriminatorEncodeTypeNameAllObjects causes the type name to be encoded + // for all struct and map values. Please note this specifically does not + // apply to the root value. + DiscriminatorEncodeTypeNameAllObjects + + // DiscriminatorEncodeTypeNameIfRequired is the default behavior when + // the discriminator is set, and the type name is only encoded if required. + DiscriminatorEncodeTypeNameIfRequired DiscriminatorEncodeMode = 0 +) + +func (m DiscriminatorEncodeMode) root() bool { + return m&DiscriminatorEncodeTypeNameRootValue > 0 +} + +func (m DiscriminatorEncodeMode) all() bool { + return m&DiscriminatorEncodeTypeNameAllObjects > 0 +} + +func (d *decodeState) isDiscriminatorSet() bool { + return d.discriminatorTypeFieldName != "" && + d.discriminatorValueFieldName != "" +} + +// discriminatorOpType describes the current operation related to +// discriminators when reading a JSON object's fields. +type discriminatorOpType uint8 + +const ( + // discriminatorOpTypeNameField indicates the discriminator type name + // field was discovered. + discriminatorOpTypeNameField = iota + 1 + + // discriminatorOpValueField indicates the discriminator value field + // was discovered. + discriminatorOpValueField +) + +func (d *decodeState) discriminatorGetValue() (reflect.Value, error) { + // Record the current offset so we know where the data starts. + offset := d.readIndex() + + // Create a temporary decodeState used to inspect the current object + // and determine its discriminator type and decode its value. + dd := &decodeState{ + disallowUnknownFields: d.disallowUnknownFields, + useNumber: d.useNumber, + discriminatorToTypeFn: d.discriminatorToTypeFn, + discriminatorTypeFieldName: d.discriminatorTypeFieldName, + discriminatorValueFieldName: d.discriminatorValueFieldName, + } + dd.init(append([]byte{}, d.data[offset:]...)) + defer freeScanner(&dd.scan) + dd.scan.reset() + + var ( + t reflect.Type // the instance of the type + valueOff = -1 // the offset of a possible discriminator value + ) + + dd.scanWhile(scanSkipSpace) + if dd.opcode != scanBeginObject { + panic(phasePanicMsg) + } + + for { + dd.scanWhile(scanSkipSpace) + if dd.opcode == scanEndObject { + // closing } - can only happen on first iteration. + break + } + if dd.opcode != scanBeginLiteral { + panic(phasePanicMsg) + } + + // Read key. + start := dd.readIndex() + dd.rescanLiteral() + item := dd.data[start:dd.readIndex()] + key, ok := unquote(item) + if !ok { + panic(phasePanicMsg) + } + + // Check to see if the key is related to the discriminator. + var discriminatorOp discriminatorOpType + switch key { + case d.discriminatorTypeFieldName: + discriminatorOp = discriminatorOpTypeNameField + case d.discriminatorValueFieldName: + discriminatorOp = discriminatorOpValueField + } + + // Read : before value. + if dd.opcode == scanSkipSpace { + dd.scanWhile(scanSkipSpace) + } + + if dd.opcode != scanObjectKey { + panic(phasePanicMsg) + } + dd.scanWhile(scanSkipSpace) + + // Read value. + valOff := dd.readIndex() + val := dd.valueInterface() + + switch discriminatorOp { + case discriminatorOpTypeNameField: + tn, ok := val.(string) + if !ok { + return reflect.Value{}, fmt.Errorf( + "json: discriminator type at offset %d is not string", + offset+valOff) + } + if tn == "" { + return reflect.Value{}, fmt.Errorf( + "json: discriminator type at offset %d is empty", + offset+valOff) + } + + // Parse the type name into a type instance. + ti, err := discriminatorParseTypeName(tn, d.discriminatorToTypeFn) + if err != nil { + return reflect.Value{}, err + } + + // Assign the type instance to the outer variable, t. + t = ti + + // Primitive types and types with Unmarshaler are wrapped in a + // structure with type and value fields. Structures and Maps not + // implementing Unmarshaler use discriminator embedded within their + // content. + if useNestedDiscriminator(t) { + // If the type is a map or a struct not implementing Unmarshaler + // then it is not necessary to continue walking over the current + // JSON object since it will be completely re-scanned to decode + // its value into the discovered type. + dd.opcode = scanEndObject + } else { + // Otherwise if the value offset has been discovered then it is + // safe to stop walking over the current JSON object as well. + if valueOff > -1 { + dd.opcode = scanEndObject + } + } + case discriminatorOpValueField: + valueOff = valOff + + // If the type has been discovered then it is safe to stop walking + // over the current JSON object. + if t != nil { + dd.opcode = scanEndObject + } + } + + // Next token must be , or }. + if dd.opcode == scanSkipSpace { + dd.scanWhile(scanSkipSpace) + } + if dd.opcode == scanEndObject { + break + } + if dd.opcode != scanObjectValue { + panic(phasePanicMsg) + } + } + + // If there is not a type discriminator then return early. + if t == nil { + return reflect.Value{}, fmt.Errorf("json: missing discriminator") + } + + // Instantiate a new instance of the discriminated type. + var v reflect.Value + switch t.Kind() { + case reflect.Slice: + // MakeSlice returns a value that is not addressable. + // Instead, use MakeSlice to get the type, then use + // reflect.New to create an addressable value. + v = reflect.New(reflect.MakeSlice(t, 0, 0).Type()).Elem() + case reflect.Map: + // MakeMap returns a value that is not addressable. + // Instead, use MakeMap to get the type, then use + // reflect.New to create an addressable value. + v = reflect.New(reflect.MakeMap(t).Type()).Elem() + case reflect.Complex64, reflect.Complex128: + return reflect.Value{}, fmt.Errorf("json: unsupported discriminator type: %s", t.Kind()) + default: + v = reflect.New(t) + } + + // Reset the decode state to prepare for decoding the data. + dd.scan.reset() + + if useNestedDiscriminator(t) { + // Set the offset to zero since the entire object will be decoded + // into v. + dd.off = 0 + } else { + // Set the offset to what it was before the discriminator value was + // read so only the value field is decoded into v. + dd.off = valueOff + } + // This will initialize the correct scan step and op code. + dd.scanWhile(scanSkipSpace) + + // Decode the data into the value. + if err := dd.value(v); err != nil { + return reflect.Value{}, err + } + + // Check the saved error as well since the decoder.value function does not + // always return an error. If the reflected value is still zero, then it is + // likely the decoder was unable to decode the value. + if err := dd.savedError; err != nil { + switch v.Kind() { + case reflect.Ptr, reflect.Interface: + v = v.Elem() + } + if v.IsZero() { + return reflect.Value{}, err + } + } + + return v, nil +} + +func (d *decodeState) discriminatorInterfaceDecode(t reflect.Type, v reflect.Value) error { + + defer func() { + // Advance the decode state, throwing away the value. + _ = d.objectInterface() + }() + + dv, err := d.discriminatorGetValue() + if err != nil { + return err + } + + switch dv.Kind() { + case reflect.Map, reflect.Slice: + if dv.Type().AssignableTo(t) { + v.Set(dv) + return nil + } + if pdv := dv.Addr(); pdv.Type().AssignableTo(t) { + v.Set(pdv) + return nil + } + case reflect.Ptr: + if dve := dv.Elem(); dve.Type().AssignableTo(t) { + v.Set(dve) + return nil + } + if dv.Type().AssignableTo(t) { + v.Set(dv) + return nil + } + } + + return fmt.Errorf("json: unsupported discriminator kind: %s", dv.Kind()) +} + +func (o encOpts) isDiscriminatorSet() bool { + return o.discriminatorTypeFieldName != "" && + o.discriminatorValueFieldName != "" +} + +func discriminatorInterfaceEncode(e *encodeState, v reflect.Value, opts encOpts) { + v = v.Elem() + + if v.Type().Implements(marshalerType) { + discriminatorValue := opts.discriminatorValueFn(v.Type()) + if discriminatorValue == "" { + marshalerEncoder(e, v, opts) + } + e.WriteString(`{"`) + e.WriteString(opts.discriminatorTypeFieldName) + e.WriteString(`":"`) + e.WriteString(discriminatorValue) + e.WriteString(`","`) + e.WriteString(opts.discriminatorValueFieldName) + e.WriteString(`":`) + marshalerEncoder(e, v, opts) + e.WriteByte('}') + return + } + + switch v.Kind() { + case reflect.Chan, reflect.Func, reflect.Invalid: + e.error(&UnsupportedValueError{v, fmt.Sprintf("invalid kind: %s", v.Kind())}) + case reflect.Map: + e.discriminatorEncodeTypeName = true + newMapEncoder(v.Type())(e, v, opts) + case reflect.Struct: + e.discriminatorEncodeTypeName = true + newStructEncoder(v.Type())(e, v, opts) + case reflect.Ptr: + discriminatorInterfaceEncode(e, v, opts) + default: + discriminatorValue := opts.discriminatorValueFn(v.Type()) + if discriminatorValue == "" { + e.reflectValue(v, opts) + return + } + e.WriteString(`{"`) + e.WriteString(opts.discriminatorTypeFieldName) + e.WriteString(`":"`) + e.WriteString(discriminatorValue) + e.WriteString(`","`) + e.WriteString(opts.discriminatorValueFieldName) + e.WriteString(`":`) + e.reflectValue(v, opts) + e.WriteByte('}') + } +} + +func discriminatorMapEncode(e *encodeState, v reflect.Value, opts encOpts) { + if !e.discriminatorEncodeTypeName && !opts.discriminatorEncodeMode.all() { + return + } + discriminatorValue := opts.discriminatorValueFn(v.Type()) + if discriminatorValue == "" { + return + } + e.WriteByte('"') + e.WriteString(opts.discriminatorTypeFieldName) + e.WriteString(`":"`) + e.WriteString(discriminatorValue) + e.WriteByte('"') + if v.Len() > 0 { + e.WriteByte(',') + } + e.discriminatorEncodeTypeName = false +} + +func discriminatorStructEncode(e *encodeState, v reflect.Value, opts encOpts) byte { + if !e.discriminatorEncodeTypeName && !opts.discriminatorEncodeMode.all() { + return '{' + } + discriminatorValue := opts.discriminatorValueFn(v.Type()) + if discriminatorValue == "" { + return '{' + } + e.WriteString(`{"`) + e.WriteString(opts.discriminatorTypeFieldName) + e.WriteString(`":"`) + e.WriteString(discriminatorValue) + e.WriteByte('"') + e.discriminatorEncodeTypeName = false + return ',' +} + +var unmarshalerType = reflect.TypeOf((*Unmarshaler)(nil)).Elem() + +// Discriminator is nested in map and struct unless they implement Unmarshaler. +func useNestedDiscriminator(t reflect.Type) bool { + if t.Implements(unmarshalerType) || reflect.PtrTo(t).Implements(unmarshalerType) { + return false + } + kind := t.Kind() + if kind == reflect.Struct || kind == reflect.Map { + return true + } + return false +} + +var discriminatorTypeRegistry = map[string]reflect.Type{ + "uint": reflect.TypeOf(uint(0)), + "uint8": reflect.TypeOf(uint8(0)), + "uint16": reflect.TypeOf(uint16(0)), + "uint32": reflect.TypeOf(uint32(0)), + "uint64": reflect.TypeOf(uint64(0)), + "uintptr": reflect.TypeOf(uintptr(0)), + "int": reflect.TypeOf(int(0)), + "int8": reflect.TypeOf(int8(0)), + "int16": reflect.TypeOf(int16(0)), + "int32": reflect.TypeOf(int32(0)), + "int64": reflect.TypeOf(int64(0)), + "float32": reflect.TypeOf(float32(0)), + "float64": reflect.TypeOf(float64(0)), + "bool": reflect.TypeOf(true), + "string": reflect.TypeOf(""), + "any": reflect.TypeOf((*interface{})(nil)).Elem(), + "interface{}": reflect.TypeOf((*interface{})(nil)).Elem(), + "interface {}": reflect.TypeOf((*interface{})(nil)).Elem(), + + // Not supported, but here to prevent the decoder from panicing + // if encountered. + "complex64": reflect.TypeOf(complex64(0)), + "complex128": reflect.TypeOf(complex128(0)), +} + +// discriminatorPointerTypeCache caches the pointer type for another type. +// For example, a key that was the int type would have a value that is the +// *int type. +var discriminatorPointerTypeCache sync.Map // map[reflect.Type]reflect.Type + +// cachedPointerType returns the pointer type for another and avoids repeated +// work by using a cache. +func cachedPointerType(t reflect.Type) reflect.Type { + if value, ok := discriminatorPointerTypeCache.Load(t); ok { + return value.(reflect.Type) + } + pt := reflect.New(t).Type() + value, _ := discriminatorPointerTypeCache.LoadOrStore(t, pt) + return value.(reflect.Type) +} + +var ( + mapPatt = regexp.MustCompile(`^\*?map\[([^\]]+)\](.+)$`) + arrayPatt = regexp.MustCompile(`^\*?\[(\d+)\](.+)$`) + slicePatt = regexp.MustCompile(`^\*?\[\](.+)$`) +) + +// discriminatorParseTypeName returns a reflect.Type for the given type name. +func discriminatorParseTypeName( + typeName string, + typeFn DiscriminatorToTypeFunc) (reflect.Type, error) { + + // Check to see if the type is an array, map, or slice. + var ( + aln = -1 // array length + etn string // map or slice element type name + ktn string // map key type name + ) + if m := arrayPatt.FindStringSubmatch(typeName); len(m) > 0 { + i, err := strconv.Atoi(m[1]) + if err != nil { + return nil, err + } + aln = i + etn = m[2] + } else if m := slicePatt.FindStringSubmatch(typeName); len(m) > 0 { + etn = m[1] + } else if m := mapPatt.FindStringSubmatch(typeName); len(m) > 0 { + ktn = m[1] + etn = m[2] + } + + // indirectTypeName checks to see if the type name begins with a + // "*" characters. If it does, then the type name sans the "*" + // character is returned along with a true value indicating the + // type is a pointer. Otherwise the original type name is returned + // along with a false value. + indirectTypeName := func(tn string) (string, bool) { + if len(tn) > 1 && tn[0] == '*' { + return tn[1:], true + } + return tn, false + } + + lookupType := func(tn string) (reflect.Type, bool) { + // Get the actual type name and a flag indicating whether the + // type is a pointer. + n, p := indirectTypeName(tn) + + var t reflect.Type + ok := false + // look up the type in the external registry to allow name override. + if typeFn != nil { + t, ok = typeFn(n) + } + if !ok { + // Use the built-in registry if the external registry fails + if t, ok = discriminatorTypeRegistry[n]; !ok { + return nil, false + } + } + // If the type was a pointer then get the type's pointer type. + if p { + t = cachedPointerType(t) + } + return t, true + } + + var t reflect.Type + + if ktn == "" && etn != "" { + et, ok := lookupType(etn) + if !ok { + return nil, fmt.Errorf("json: invalid array/slice element type: %s", etn) + } + if aln > -1 { + // Array + t = reflect.ArrayOf(aln, et) + } else { + // Slice + t = reflect.SliceOf(et) + } + } else if ktn != "" && etn != "" { + // Map + kt, ok := lookupType(ktn) + if !ok { + return nil, fmt.Errorf("json: invalid map key type: %s", ktn) + } + et, ok := lookupType(etn) + if !ok { + return nil, fmt.Errorf("json: invalid map element type: %s", etn) + } + t = reflect.MapOf(kt, et) + } else { + var ok bool + if t, ok = lookupType(typeName); !ok { + return nil, fmt.Errorf("json: invalid discriminator type: %s", typeName) + } + } + + return t, nil +} diff --git a/vendor/github.com/vmware/govmomi/vim25/json/encode.go b/vendor/github.com/vmware/govmomi/vim25/json/encode.go new file mode 100644 index 00000000000..0c8aa202fe2 --- /dev/null +++ b/vendor/github.com/vmware/govmomi/vim25/json/encode.go @@ -0,0 +1,1453 @@ +// Copyright 2010 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Package json implements encoding and decoding of JSON as defined in +// RFC 7159. The mapping between JSON and Go values is described +// in the documentation for the Marshal and Unmarshal functions. +// +// See "JSON and Go" for an introduction to this package: +// https://golang.org/doc/articles/json_and_go.html +package json + +import ( + "bytes" + "encoding" + "encoding/base64" + "fmt" + "math" + "reflect" + "sort" + "strconv" + "strings" + "sync" + "unicode" + "unicode/utf8" +) + +// Marshal returns the JSON encoding of v. +// +// Marshal traverses the value v recursively. +// If an encountered value implements the Marshaler interface +// and is not a nil pointer, Marshal calls its MarshalJSON method +// to produce JSON. If no MarshalJSON method is present but the +// value implements encoding.TextMarshaler instead, Marshal calls +// its MarshalText method and encodes the result as a JSON string. +// The nil pointer exception is not strictly necessary +// but mimics a similar, necessary exception in the behavior of +// UnmarshalJSON. +// +// Otherwise, Marshal uses the following type-dependent default encodings: +// +// Boolean values encode as JSON booleans. +// +// Floating point, integer, and Number values encode as JSON numbers. +// +// String values encode as JSON strings coerced to valid UTF-8, +// replacing invalid bytes with the Unicode replacement rune. +// So that the JSON will be safe to embed inside HTML