ftl/node/builder.py (75 lines of code) (raw):

# Copyright 2017 Google 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. """This package defines the interface for orchestrating image builds.""" import os import logging from ftl.common import builder from ftl.common import constants from ftl.common import ftl_util from ftl.common import ftl_error from ftl.common import layer_builder as base_builder from ftl.node import layer_builder as node_builder class Node(builder.RuntimeBase): def __init__(self, ctx, args): super(Node, self).__init__(ctx, constants.NODE_CACHE_NAMESPACE, args, [ constants.PACKAGE_LOCK, constants.YARN_LOCK, constants.PACKAGE_JSON, constants.NPMRC ]) self._gen_package_lock_if_required(self._ctx) self._should_use_yarn = self._should_use_yarn(self._ctx) def _gen_package_lock_if_required(self, ctx): if not ftl_util.has_pkg_descriptor(self._descriptor_files, self._ctx): return if ctx.Contains(constants.PACKAGE_JSON) and \ not ctx.Contains(constants.YARN_LOCK) and \ not ctx.Contains(constants.PACKAGE_LOCK): logging.info('Found neither yarn.lock or package-lock.json,' 'generating package-lock.json from package.json') gen_package_lock_cmd = ['npm', 'install', '--package-lock-only'] ftl_util.run_command( 'gen_package_lock', gen_package_lock_cmd, cmd_cwd=self._args.directory, err_type=ftl_error.FTLErrors.USER()) def _should_use_yarn(self, ctx): if ctx.Contains(constants.YARN_LOCK): if ctx.Contains(constants.PACKAGE_LOCK): logging.warning( 'Detected both package-lock.json and yarn.lock;\ proceeding with an npm install') return False return True return False def Build(self): lyr_imgs = [] lyr_imgs.append(self._base_image) # delete any existing files in node_modules folder if self._args.directory: modules_dir = os.path.join(self._args.directory, "node_modules") rm_cmd = ['rm', '-rf', modules_dir] ftl_util.run_command('rm_node_modules', rm_cmd) os.makedirs(os.path.join(modules_dir)) if ftl_util.has_pkg_descriptor(self._descriptor_files, self._ctx): layer_builder = node_builder.LayerBuilder( ctx=self._ctx, descriptor_files=self._descriptor_files, directory=self._args.directory, destination_path=self._args.destination_path, should_use_yarn=self._should_use_yarn, cache_key_version=self._args.cache_key_version, cache=self._cache) layer_builder.BuildLayer() lyr_imgs.append(layer_builder.GetImage()) app = base_builder.AppLayerBuilder( directory=self._args.directory, destination_path=self._args.destination_path, entrypoint=self._args.entrypoint, exposed_ports=self._args.exposed_ports) app.BuildLayer() lyr_imgs.append(app.GetImage()) if self._args.additional_directory: additional_directory = base_builder.AppLayerBuilder( directory=self._args.additional_directory, destination_path=self._args.additional_directory, entrypoint=self._args.entrypoint, exposed_ports=self._args.exposed_ports) additional_directory.BuildLayer() lyr_imgs.append(additional_directory.GetImage()) ftl_image = ftl_util.AppendLayersIntoImage(lyr_imgs) self.StoreImage(ftl_image)