def CreateDeployment(service_name, image_name, memory_limit=None, cpu_limit=None, cpu_request=None): """Create a deployment specification for a service. Args: service_name: Name of the service. image_name: Image tag. memory_limit: Container memory limit. cpu_limit: Container cpu limit. cpu_request: Container cpu request. Returns: Dictionary object representing the deployment yaml. """ deployment = yaml.load(_POD_TEMPLATE.format(service=service_name)) container = yaml.load( _CONTAINER_TEMPLATE.format(service=service_name, image=image_name)) if memory_limit is not None: limits = yaml_helper.GetOrCreate(container, ('resources', 'limits')) limits['memory'] = memory_limit if cpu_limit is not None: limits = yaml_helper.GetOrCreate(container, ('resources', 'limits')) limits['cpu'] = six.text_type(cpu_limit) if cpu_request is not None: requests = yaml_helper.GetOrCreate(container, ('resources', 'requests')) requests['cpu'] = six.text_type(cpu_request) containers = yaml_helper.GetOrCreate( deployment, ('spec', 'template', 'spec', 'containers'), constructor=list) containers.append(container) return deployment
def ModifyContainer(self, container): """Add volume mount and set application credential environment variable.""" secret_info = self.GetInfo() mounts = yaml_helper.GetOrCreate(container, ('volumeMounts',), list) _AddSecretVolumeMount(mounts, secret_info.secret_name) envs = yaml_helper.GetOrCreate(container, ('env',), list) _AddSecretEnvVar(envs, secret_info.path)
def SkaffoldConfig(self, kubernetes_file_path): """Create a skaffold yaml file. Args: kubernetes_file_path: Path to the kubernetes config file. Returns: Text of the skaffold yaml file. """ skaffold_yaml = yaml.load(_SKAFFOLD_TEMPLATE) manifests = yaml_helper.GetOrCreate(skaffold_yaml, ('deploy', 'kubectl', 'manifests'), constructor=list) manifests.append(kubernetes_file_path) artifact = {'image': self._settings.image} # Need to escape file paths for the yaml encoder. The yaml encoder will # interpret \ as the beginning of an escape character. Windows paths may # have backslashes. artifact['context'] = six.ensure_text( self._settings.context.encode('unicode_escape')) if isinstance(self._settings.builder, local.BuildpackBuilder): artifact['buildpacks'] = { 'builder': self._settings.builder.builder, } if self._settings.builder.devmode: artifact['buildpacks']['env'] = ['GOOGLE_DEVMODE=1'] artifact['sync'] = {'auto': {}} if self._settings.builder.trust: artifact['buildpacks']['trustBuilder'] = True else: artifact['docker'] = { 'dockerfile': six.ensure_text( os.path.relpath( self._settings.builder.dockerfile, self._settings.context).encode('unicode_escape')) } artifacts = yaml_helper.GetOrCreate(skaffold_yaml, ('build', 'artifacts'), constructor=list) artifacts.append(artifact) if self._settings.local_port: port_forward_config = { 'resourceType': 'service', 'resourceName': self._settings.service_name, 'port': 8080, 'localPort': self._settings.local_port } if self._settings.namespace: port_forward_config['namespace'] = self._settings.namespace skaffold_yaml['portForward'] = [port_forward_config] return yaml.dump(skaffold_yaml)
def ModifyDeployment(self, deployment): """Add sidecar container and empty volume for unix socket.""" volumes = yaml_helper.GetOrCreate( deployment, ('spec', 'template', 'spec', 'volumes'), constructor=list) volumes.append({'name': 'cloudsql', 'emptyDir': {}}) containers = yaml_helper.GetOrCreate( deployment, ('spec', 'template', 'spec', 'containers'), constructor=list) containers.append( _CreateCloudSqlProxyContainer(self._instance_names, self._secret_info.path))
def AddEnvironmentVariables(deployment, container_name, env_vars): """Add environment variable settings to a container. Args: deployment: (dict) Yaml deployment configuration. container_name: (str) Container name. env_vars: (dict) Key value environment variable pairs. """ containers = yaml_helper.GetOrCreate( deployment, ('spec', 'template', 'spec', 'containers'), constructor=list) container = _FindFirst(containers, lambda c: c['name'] == container_name) env_list = yaml_helper.GetOrCreate(container, ('env',), constructor=list) for key, value in sorted(env_vars.items()): env_list.append({'name': key, 'value': value})
def ModifyDeployment(self, deployment): """Add a secret volume to a deployment.""" secret_info = self.GetInfo() volumes = yaml_helper.GetOrCreate(deployment, ('spec', 'template', 'spec', 'volumes'), list) _AddSecretVolume(volumes, secret_info.secret_name)
def _SetImagePush(skaffold_file, shared_docker): """Set build.local.push value in skaffold file. Args: skaffold_file: Skaffold file handle. shared_docker: Boolean that is true if docker instance is shared between the kubernetes cluster and local docker builder. Yields: Path of skaffold file with build.local.push value set to the proper value. """ # TODO(b/149935260): This function can be removed when # https://github.com/GoogleContainerTools/skaffold/issues/3668 is resolved. if not shared_docker: # If docker is not shared, use the default value (false). There is no need # to rewrite the skaffold file. yield skaffold_file else: skaffold_yaml = yaml.load_path(skaffold_file.name) local_block = yaml_helper.GetOrCreate(skaffold_yaml, ('build', 'local')) local_block['push'] = False with cross_platform_temp_file.NamedTempFile( yaml.dump(skaffold_yaml)) as patched_skaffold_file: yield patched_skaffold_file
def AddServiceAccountSecret(configs): """Add a service account secret and mounts to kubernetes configs. Args: configs: List of kubernetes yaml configurations as dictionaries. """ deployments = (config for config in configs if config['kind'] == 'Deployment') for deployment in deployments: volumes = yaml_helper.GetOrCreate(deployment, ('spec', 'template', 'spec', 'volumes'), list) _AddSecretVolume(volumes, _CREDENTIAL_SECRET_NAME) for container in yaml_helper.GetOrCreate( deployment, ('spec', 'template', 'spec', 'containers'), list): mounts = yaml_helper.GetOrCreate(container, ('volumeMounts',), list) _AddVolumeMount(mounts, _CREDENTIAL_SECRET_NAME) envs = yaml_helper.GetOrCreate(container, ('env',), list) _AddSecretEnvVar(envs, _CREDENTIAL_SECRET_NAME)
def SkaffoldConfig(self, kubernetes_file_path): """Create a skaffold yaml file. Args: kubernetes_file_path: Path to the kubernetes config file. Returns: Text of the skaffold yaml file. """ skaffold_yaml_text = _SKAFFOLD_TEMPLATE.format( image_name=self._settings.image_name, context_path=self._settings.build_context_directory or os.path.dirname(self._settings.dockerfile) or '.') skaffold_yaml = yaml.load(skaffold_yaml_text) manifests = yaml_helper.GetOrCreate(skaffold_yaml, ('deploy', 'kubectl', 'manifests'), constructor=list) manifests.append(kubernetes_file_path) artifact = {'image': self._settings.image_name} if self._settings.builder: artifact['buildpack'] = {'builder': self._settings.builder} else: artifact['context'] = (self._settings.build_context_directory or os.path.dirname( self._settings.dockerfile) or '.') artifacts = yaml_helper.GetOrCreate(skaffold_yaml, ('build', 'artifacts'), constructor=list) artifacts.append(artifact) if self._settings.local_port: skaffold_yaml['portForward'] = [{ 'resourceType': 'service', 'resourceName': self._settings.service_name, 'port': 8080, 'localPort': self._settings.local_port }] return yaml.dump(skaffold_yaml)
def ModifyContainer(self, container): """Add volume mount to continer. This method will not modify the CloudSql proxy container. Args: container: (dict) Container yaml as a dict. """ if container['name'] == _CLOUD_PROXY_CONTAINER_NAME: return volume_mounts = yaml_helper.GetOrCreate( container, ('volumeMounts',), constructor=list) volume_mounts.append({ 'name': 'cloudsql', 'mountPath': '/cloudsql', 'readOnly': True })
def testCreateList(self): obj = {'A': {'B': {}}} self.assertEqual( yaml_helper.GetOrCreate(obj, ('A', 'B', 'C', 'D'), constructor=list), []) self.assertEqual(obj, {'A': {'B': {'C': {'D': []}}}})
def testCreateDict(self): obj = {'A': {'B': {}}} self.assertEqual(yaml_helper.GetOrCreate(obj, ('A', 'B', 'C', 'D')), {}) self.assertEqual(obj, {'A': {'B': {'C': {'D': {}}}}})
def testGetExistingDict(self): obj = {'A': {'B': {'C': {'D': [1, 2, 3]}}}} self.assertIs(yaml_helper.GetOrCreate(obj, ('A', 'B', 'C')), obj['A']['B']['C'])