blob: 17bd6773bee8f7a6fe0bbd7ea11a08e75ee4787e [file] [log] [blame]
# Copyright 2021 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
from . import add_windows_package
from . import add_windows_driver
from PB.recipes.infra.windows_image_builder import windows_image_builder as wib
NAME_SEP = '-'
class Customization(object):
""" Base customization class. Provides support for pinning and executing
recipes.
"""
def __init__(self, image, cust, arch, scripts, configs, module, source,
try_job):
""" __init__ copies common module objects to class references. These are
commonly used for all customizations
Args:
* image: wib.Image proto object
* cust: wib.Customization proto object
* arch: string representing architecture to build the image for
* scripts: path to the scripts resource dir
* configs: dir to store configs in
* module: module object with all dependencies
* source: module object for Source from sources.py
"""
# generate a copy of image
self._image = wib.Image()
self._image.CopyFrom(image)
self._image.ClearField('customizations')
# generate a copy of customization
self._customization = wib.Customization()
self._customization.CopyFrom(cust)
# Add customization to the image
self._image.customizations.append(self._customization)
self._arch = arch
self._scripts = scripts
self.m = module
self._source = source
self._key = ''
self._configs = configs
self._name = ''
self._try_job = try_job
def name(self):
""" name returns the name of the customization object. This needs to be
set by the inheriting class"""
return self._name
def customization(self):
"""customization returns wib.Customization object representing self"""
return self._customization
def image(self):
""" image returns wib.Image object representing self"""
return self._image
@property
def id(self):
""" id returns the identifier for this customization"""
return NAME_SEP.join(
['image({})'.format(self.image().name), 'cust({})'.format(self._name)])
@property
def type(self):
""" type returns the customization type for self (customization) """
return self.customization().WhichOneof('customization')
@property
def arch(self):
""" arch returns the targeted arch for the self (customization) """
return self.image().arch
@property
def tryrun(self):
""" tryrun returns true if we are running in try mode """
return self._try_job
@property
def needs_build(self):
""" needs_build returns True if this customization needs to be built.
False otherwise """
# Override the check if we need to force the build.
if self.mode == wib.CustomizationMode.CUST_FORCE_BUILD:
return True
for output in self.outputs:
# If all the outputs exist. We need not build the image
if output and not self._source.exists(output):
return True
return False
@property
def mode(self):
""" mode returns the mode that this customization is set to. """
return self._customization.mode
def executable(self, inputs=()):
""" executable returns true if the customization is executable false
otherwise.
executable ensures that at least one of the outputs that is expected from
this customization doesn't exist (No need to execute the customization if
all the outputs already exist) and all the inputs required to execute the
customization are available.
Args:
* inputs: list of urls for inputs that will be available at time of
execution
"""
if self.needs_build:
# check if we can build the image
for ip in self.inputs:
if self._source.get_url(
ip) not in inputs and not self._source.exists(ip):
# still waiting on some input. Cannot build now
return False
# we have all the inputs for the image. We can build
return True
# image doesn't need building
return False
def pinnable(self, ctx):
""" pinnable determines if the customization is pinnable
Args:
* ctx: dict containing the context for pinning
Returns True if the customization is pinnable. False otherwise
"""
for ip in self.inputs:
if ip.WhichOneof('src') == 'local_src' and ip.local_src not in ctx:
return False
return True
def unpinnable(self, ctx):
""" unpinnable determines if the customization is pinnable. And returns
srcs that it cannot pin
Args:
* ctx: dict containing the context for pinning
Returns list of srcs that cannot be pinned. Empty list otherwise
"""
unpins = []
for ip in self.inputs:
if ip.WhichOneof('src') == 'local_src' and ip.local_src not in ctx:
unpins.append(ip)
return unpins
def set_key(self, key):
""" set_key is used to set the identification keys for the customization
Args:
* key: string representing the unique key for this customization
"""
self._key = key
def get_key(self):
""" get_key returns the hash associated with the customization
"""
return self._key
def execute_script(self, name, command, *args, **kwargs):
""" Executes the windows powershell script
Args:
* name: string representing step name
* command: string|path representing command to be run
* args: args to be passed on to the command
* kwargs: logs and ret_codes, logs ([]str) are list os paths to watch
and record logs from. ret_codes ([]int) is a list of ints,
these will be treated as success return codes upon execution
"""
logs = kwargs['logs']
ret_codes = kwargs['ret_codes']
return self.m.powershell(
name, command, logs=logs, ret_codes=ret_codes, args=list(args))