Exemple #1
0
 def __post_init__(self):
     ASSERT.in_(self.kind, ('range', 'values'))
     if self.kind == 'range':
         ASSERT.equal(len(self.args), 2)
         ASSERT.all(self.args, lambda arg: isinstance(arg, int))
         ASSERT.less_or_equal(self.args[0], self.args[1])
     else:
         ASSERT.equal(self.kind, 'values')
         ASSERT.all(self.args, lambda arg: isinstance(arg, str))
Exemple #2
0
def build(parameters):
    ASSERT.is_(parameters['inside-builder-pod'], True)
    ASSERT.all(parameters['roots'], _is_root_dir)
    with scripts.using_sudo():
        # We should run `apt-get update` even when we are not upgrading
        # the full system because some packages may be removed from the
        # distro repo while our local package index still has it.
        scripts.apt_get_update()
    scripts.mkdir(parameters['drydock'])
Exemple #3
0
 def __post_init__(self):
     validate_pod_label(self.label)
     ctr_models.validate_pod_version(self.version)
     # Only allow specifying image for pods by name for now.
     ASSERT.all(self.images, lambda image: image.name and image.version)
     # The current implementation does not resolve any unit name
     # conflicts (note that because we include pod id in the unit
     # name, they could only conflict within the same group).
     ASSERT.unique(self.systemd_unit_configs,
                   lambda config: config.unit_name)
Exemple #4
0
def raising(*exc_types):
    """Annotate a class or a method about what exceptions it raises."""

    ASSERT.all(exc_types, lambda type_: issubclass(type_, Exception))

    def decorate(cls_or_func):
        md = get_interface_metadata(cls_or_func)
        if md:
            md = Metadata(raising=md.raising + exc_types)
        else:
            md = Metadata(raising=exc_types)
        set_interface_metadata(cls_or_func, md)
        return cls_or_func

    return decorate
Exemple #5
0
def columnar_arguments(columns, default_columns):
    return functionals.compose(
        argparses.argument(
            '--format',
            action=argparses.StoreEnumAction,
            default=Formats.TEXT,
            help='set output format (default: %(default_string)s)',
        ),
        argparses.argument(
            '--header',
            action=argparses.StoreBoolAction,
            default=True,
            help='enable/disable header output (default: %(default_string)s)',
        ),
        argparses.begin_argument(
            '--columns',
            type=lambda columns_str: ASSERT.all(
                list(filter(None, columns_str.split(','))),
                columns.__contains__,
            ),
            default=','.join(default_columns),
            help=('set output columns that are comma separated '
                  'from available columns: %(columns)s '
                  '(default: %(default)s)'),
        ),
        argparses.apply(lambda action: setattr(action, 'columns', ', '.join(
            sorted(columns)))),
        argparses.end,
    )
Exemple #6
0
        def validate_assigned_values(self, assigned_values):
            """Validate assigned values.

            * No duplicated assignments.
            * Assigned values are a subset of defined values.
            """
            ASSERT.all(assigned_values, lambda value: isinstance(value, str))
            if self.kind == 'range':
                ASSERT.unique(assigned_values)
                ASSERT.all(
                    assigned_values,
                    lambda value: self.args[0] <= int(value) < self.args[1],
                )
            else:
                ASSERT.equal(self.kind, 'values')
                ASSERT.issubset(
                    g1_collections.Multiset(assigned_values),
                    g1_collections.Multiset(self.args),
                )
            return assigned_values
Exemple #7
0
 def __post_init__(self):
     validate_pod_label(self.label)
     ASSERT.equal(
         _get_label_name(_POD_LABEL_PATTERN, self.label),
         self.pod_config_template.name,
     )
     # Only allow specifying image for pods by name for now.
     ASSERT.all(self.images, lambda image: image.name and image.version)
     # Due to bundle directory layout, image names and volume names
     # are expected to be unique.  (This layout restriction should be
     # not too restrictive in practice.)
     ASSERT.unique(self.images, lambda image: image.name)
     ASSERT.unique(self.volumes, lambda volume: volume.name)
     # We use the same format on local alias as on token name.
     ASSERT.all(self.token_names.keys(), validate_token_name)
     ASSERT.all(self.token_names.values(), validate_token_name)
Exemple #8
0
 def post_init(self):
     ASSERT.predicate(self.path, Path.is_dir)
     ASSERT.predicate(self.deploy_instruction_path, Path.is_file)
     ASSERT.all((path for _, path in self.iter_images()), Path.is_file)
     ASSERT.all((path for _, path in self.iter_volumes()), Path.is_file)
Exemple #9
0
def define_pod(
    *,
    name: str,
    apps: typing.List[App] = (),
    images: typing.List[str] = (),
    mounts: typing.List[Mount] = (),
    volumes: typing.List[Volume] = (),
    systemd_unit_groups: typing.List[SystemdUnitGroup] = (),
    token_names: typing.Mapping[str, str] = None,
):
    """Define a pod.

    This defines:
    * Parameter: name/version.
    * Rule: name/build.  NOTE: This rule is generally run in the host
      system, not inside a builder pod.
    """
    ASSERT(len(images) <= 1, 'expect at most one image per pod for now: {}')
    # Let's require absolute release labels (because it is quite hard to
    # derive label path for images and volumes from pod label).
    ASSERT.all(images, lambda label: label.startswith('//'))
    ASSERT.all(volumes, lambda volume: volume.label.startswith('//'))
    ASSERT.unique(map(_get_label_name, images))
    ASSERT.unique(_get_label_name(volume.label) for volume in volumes)

    name_prefix = shipyard2.rules.canonicalize_name_prefix(name)
    parameter_version = name_prefix + 'version'
    rule_build = name_prefix + 'build'

    (foreman.define_parameter(parameter_version)\
     .with_doc('pod version'))

    images = list(map(foreman.Label.parse, images))

    @foreman.rule(rule_build)
    @foreman.rule.depend('//pods/bases:build')
    @foreman.rule.depend('//releases:build')
    def build(parameters):
        version = ASSERT.not_none(parameters[parameter_version])
        pod_dir_path = releases.get_output_dir_path(parameters, name, version)
        if (
            pod_dir_path / \
            shipyard2.POD_DIR_RELEASE_METADATA_FILENAME
        ).exists():
            LOG.info('skip: build pod: %s %s', name, version)
            return
        LOG.info('build pod: %s %s', name, version)
        try:
            scripts.mkdir(pod_dir_path)
            releases.generate_release_metadata(
                parameters,
                pod_dir_path / shipyard2.POD_DIR_RELEASE_METADATA_FILENAME,
            )
            _generate_deploy_instruction(
                parameters=parameters,
                pod_dir_path=pod_dir_path,
                name=name,
                version=version,
                apps=apps,
                images=images,
                mounts=mounts,
                volumes=volumes,
                systemd_unit_groups=systemd_unit_groups,
                token_names=token_names,
            )
            _link_images(parameters, pod_dir_path, images)
            _link_volumes(parameters, pod_dir_path, volumes)
        except Exception:
            # Roll back on error.
            scripts.rm(pod_dir_path, recursive=True)
            raise

    for label in images:
        build.depend(str(_images.derive_rule(label)))

    return PodRules(build=build)
Exemple #10
0
def cleanup(parameters):
    ASSERT.is_(parameters['inside-builder-pod'], True)
    ASSERT.all(parameters['roots'], _is_root_dir)
    with scripts.using_sudo():
        scripts.apt_get_clean()
Exemple #11
0
 def test_assert_collection_mapper(self):
     self.assertEqual(ASSERT.all([2, 4, 6], is_even), [2, 4, 6])
     pattern = r'expect all .*is_even.*, not \[2, 4, 6, 7\]'
     with self.assertRaisesRegex(AssertionError, pattern):
         ASSERT.all([2, 4, 6, 7], is_even)
Exemple #12
0
 def check_invariants(self):
     ASSERT.all(self.definitions, models.validate_token_name)
     for token_name, assignments in self.assignments.items():
         models.validate_token_name(token_name)
         ASSERT.getitem(self.definitions, token_name)\
         .validate_assigned_values([a.value for a in assignments])