def __init__(self, base, tar_gz, port, *envs): """Creates a new layer on top of a base with optional tar.gz, port or envs. Args: base: a base DockerImage for a new layer. tar_gz: an optional gzipped tarball passed as a string with filesystem changeset. port: an optional port to be exposed, passed as a string. For example: '8080/tcp'. *envs: environment variables passed as strings in the format: 'ENV_ONE=val', 'ENV_TWO=val2'. """ self._base = base unsigned_manifest, unused_signatures = util.DetachSignatures( self._base.manifest()) manifest = json.loads(unsigned_manifest) v1_compat = json.loads(manifest['history'][0]['v1Compatibility']) if tar_gz: if isinstance(tar_gz, six.text_type): self._blob = tar_gz.encode() else: self._blob = tar_gz self._blob_sum = 'sha256:' + hashlib.sha256(self._blob).hexdigest() v1_compat['throwaway'] = False else: self._blob_sum = _EMPTY_LAYER_TAR_ID self._blob = '' v1_compat['throwaway'] = True manifest['fsLayers'].insert(0, {'blobSum': self._blob_sum}) v1_compat['parent'] = v1_compat['id'] v1_compat['id'] = binascii.hexlify(os.urandom(32)).decode('ascii') config = v1_compat.get('config', {}) or {} envs = list(envs) if envs: env_keys = [env.split('=')[0] for env in envs] old_envs = config.get('Env', []) or [] old_envs = [env for env in old_envs if env.split('=')[0] not in env_keys] config['Env'] = old_envs + envs if port is not None: old_ports = config.get('ExposedPorts', {}) or {} old_ports[port] = {} config['ExposedPorts'] = old_ports v1_compat['config'] = config manifest['history'].insert( 0, {'v1Compatibility': json.dumps(v1_compat, sort_keys=True)}) self._manifest = util.Sign(json.dumps(manifest, sort_keys=True))
def SignedManifestToSHA256(manifest): """Return 'sha256:' + hex(sha256(manifest - signatures)).""" unsigned_manifest, unused_signatures = util.DetachSignatures(manifest) return SHA256(unsigned_manifest.encode('utf8'))