blob: 72e66d5e6516fd0a7d8112c136a6c74275eaa2d1 [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.
from libcloud.common.google import GoogleOAuth2Credential
from libcloud.container.providers import Provider
from libcloud.container.drivers.kubernetes import KubernetesContainerDriver
from libcloud.common.google import GoogleResponse
from libcloud.common.google import GoogleBaseConnection
API_VERSION = "v1"
class GKEResponse(GoogleResponse):
pass
class GKEConnection(GoogleBaseConnection):
"""
Connection class for the GKE driver.
GKEConnection extends :class:`google.GoogleBaseConnection` for 3 reasons:
1. modify request_path for GKE URI.
2. Implement gce_params functionality described below.
3. Add request_aggregated_items method for making aggregated API calls.
"""
host = "container.googleapis.com"
responseCls = GKEResponse
def __init__(
self,
user_id,
key,
secure,
auth_type=None,
credential_file=None,
project=None,
**kwargs,
):
super(GKEConnection, self).__init__(
user_id,
key,
secure=secure,
auth_type=auth_type,
credential_file=credential_file,
**kwargs,
)
self.request_path = "/%s/projects/%s" % (API_VERSION, project)
self.gke_params = {}
def pre_connect_hook(self, params, headers):
"""
Update URL parameters with values from self.gke_params.
@inherits: :class:`GoogleBaseConnection.pre_connect_hook`
"""
params, headers = super(GKEConnection, self).pre_connect_hook(params, headers)
if self.gke_params:
params.update(self.gke_params)
return params, headers
def request(self, *args, **kwargs):
"""
Perform request then do GKE-specific processing of URL params.
@inherits: :class:`GoogleBaseConnection.request`
"""
response = super(GKEConnection, self).request(*args, **kwargs)
# If gce_params has been set, then update the pageToken with the
# nextPageToken so it can be used in the next request.
if self.gke_params:
if "nextPageToken" in response.object:
self.gke_params["pageToken"] = response.object["nextPageToken"]
elif "pageToken" in self.gke_params:
del self.gke_params["pageToken"]
self.gke_params = None
return response
class GKEContainerDriver(KubernetesContainerDriver):
"""
GKE Container Driver class.
This is the primary driver for interacting with Google Container
Engine. It contains all of the standard libcloud methods,
plus additional ex_* methods for more features.
Note that many methods allow either objects or strings (or lists of
objects/strings). In most cases, passing strings instead of objects
will result in additional GKE API calls.
"""
connectionCls = GKEConnection
api_name = "google"
name = "Google Container Engine"
type = Provider.GKE
website = "https://container.googleapis.com"
supports_clusters = True
AUTH_URL = "https://container.googleapis.com/auth/"
def __init__(
self,
user_id,
key=None,
datacenter=None,
project=None,
auth_type=None,
scopes=None,
credential_file=None,
host=None,
port=443,
**kwargs,
):
"""
:param user_id: The email address (for service accounts) or Client ID
(for installed apps) to be used for authentication.
:type user_id: ``str``
:param key: The RSA Key (for service accounts) or file path containing
key or Client Secret (for installed apps) to be used for
authentication.
:type key: ``str``
:keyword datacenter: The name of the datacenter (zone) used for
operations.
:type datacenter: ``str``
:keyword project: Your GKE project name. (required)
:type project: ``str``
:keyword auth_type: Accepted values are "SA" or "IA" or "GKE"
("Service Account" or "Installed Application" or
"GKE" if libcloud is being used on a GKE instance
with service account enabled).
If not supplied, auth_type will be guessed based
on value of user_id or if the code is being
executed in a GKE instance.
:type auth_type: ``str``
:keyword scopes: List of authorization URLs. Default is empty and
grants read/write to Compute, Storage, DNS.
:type scopes: ``list``
:keyword credential_file: Path to file for caching authentication
information used by GKEConnection.
:type credential_file: ``str``
"""
if not project:
raise ValueError(
"Project name must be specified using " '"project" keyword.'
)
if host is None:
host = GKEContainerDriver.website
self.auth_type = auth_type
self.project = project
self.scopes = scopes
self.zone = None
if datacenter is not None:
self.zone = datacenter
self.credential_file = (
credential_file
or GoogleOAuth2Credential.default_credential_file + "." + self.project
)
super(GKEContainerDriver, self).__init__(
user_id, key, secure=True, host=None, port=None, **kwargs
)
self.base_path = "/%s/projects/%s" % (API_VERSION, self.project)
self.website = GKEContainerDriver.website
def _ex_connection_class_kwargs(self):
return {
"auth_type": self.auth_type,
"project": self.project,
"scopes": self.scopes,
"credential_file": self.credential_file,
}
def list_clusters(self, ex_zone=None):
"""
Return a list of cluster information in the current zone or all zones.
:keyword ex_zone: Optional zone name or None
:type ex_zone: ``str`` or :class:`GCEZone` or
:class:`NodeLocation` or ``None``
"""
request = "/zones/%s/clusters" % (ex_zone)
if ex_zone is None:
request = "/zones/clusters"
response = self.connection.request(request, method="GET").object
return response
def get_server_config(self, ex_zone=None):
"""
Return configuration info about the Container Engine service.
:keyword ex_zone: Optional zone name or None
:type ex_zone: ``str`` or :class:`GCEZone` or
:class:`NodeLocation` or ``None``
"""
if ex_zone is None:
ex_zone = self.zone
request = "/zones/%s/serverconfig" % (ex_zone)
response = self.connection.request(request, method="GET").object
return response