Exemplo n.º 1
0
    def create(self):
        component = Component(
            name=self.slug,
            repo=None,
            version='master',
            repo_url=f"[email protected]:{self.github_owner}/component-{self.slug}.git",
        )
        if component.target_directory.exists():
            raise click.ClickException(
                f"Unable to add component {self.name}: {component.target_directory} already exists.")
        click.secho(f"Adding component {self.name}...", bold=True)
        component_template = __install_dir__ / 'component-template'
        cookiecutter(str(component_template.resolve()), no_input=True,
                     output_dir='dependencies',
                     extra_context=self.cookiecutter_args())

        repo = git.create_repository(component.target_directory)
        component = component._replace(repo=repo)
        git.add_remote(repo, 'origin', component.repo_url)
        index = repo.index
        index.add('*')
        index.add('.github')
        index.add('.*.yml')
        git.commit(repo, 'Initial commit', self.config)

        click.echo(' > Installing component')
        create_component_symlinks(self.config, component)

        targetfile = P('inventory', 'targets', 'cluster.yml')
        target = yaml_load(targetfile)
        target['classes'].append(f"components.{self.slug}")
        target['classes'].insert(0, f"defaults.{self.slug}")
        yaml_dump(target, targetfile)

        click.secho(f"Component {self.name} successfully added 🎉", bold=True)
Exemplo n.º 2
0
    def create(self):
        component = Component(
            name=self.slug,
            repo=None,
            version="master",
            repo_url=
            f"[email protected]:{self.github_owner}/component-{self.slug}.git",
        )
        if component.target_directory.exists():
            raise click.ClickException(
                f"Unable to add component {self.name}: {component.target_directory} already exists."
            )
        click.secho(f"Adding component {self.name}...", bold=True)
        component_template = __install_dir__ / "component-template"
        cookiecutter(
            str(component_template.resolve()),
            no_input=True,
            output_dir="dependencies",
            extra_context=self.cookiecutter_args(),
        )

        repo = git.create_repository(component.target_directory)
        component = component._replace(repo=repo)
        git.add_remote(repo, "origin", component.repo_url)
        index = repo.index
        index.add("*")
        index.add(".github")
        index.add(".gitignore")
        index.add(".*.yml")
        index.add(".editorconfig")
        git.commit(repo, "Initial commit", self.config)

        click.echo(" > Installing component")
        try:
            create_component_symlinks(self.config, component)

            targetfile = P("inventory", "targets", "cluster.yml")
            insert_into_inventory_targets_cluster(targetfile, self.slug)
            insert_into_jsonnetfile(P("jsonnetfile.json"),
                                    component.target_directory)
            # call fetch_jsonnet_libraries after updating jsonnetfile to
            # symlink new component into vendor/
            fetch_jsonnet_libraries()
        except FileNotFoundError:
            # TODO: This should maybe cleanup the "dependencies" subdirectory
            # (since we just created it).
            click.echo("Cannot find catalog files. Did you forget to run "
                       "'catalog compile' in the current directory?")
        else:
            click.secho(f"Component {self.name} successfully added 🎉",
                        bold=True)
Exemplo n.º 3
0
    def delete(self):
        component = Component(
            name=self.slug,
            repo=None,
            repo_url="",
        )

        if component.target_directory.exists():

            if not self.config.force:
                click.confirm(
                    "Are you sure you want to delete component "
                    f"{self.slug}? This action cannot be undone",
                    abort=True,
                )
            delete_component_symlinks(self.config, component)
            rmtree(component.target_directory)

            targetfile = P("inventory", "targets", "cluster.yml")
            remove_from_inventory_targets_cluster(targetfile, self.slug)
            remove_from_jsonnetfile(P("jsonnetfile.json"),
                                    component.target_directory)
            # Fetch jsonnet libs after removing component from jsonnetfile to
            # remove symlink to removed component in vendor/
            fetch_jsonnet_libraries()

            click.secho(f"Component {self.slug} successfully deleted 🎉",
                        bold=True)
        else:
            raise click.BadParameter("Cannot find component with slug "
                                     f"'{self.slug}'.")
Exemplo n.º 4
0
def test_create_component_symlinks_fails(data: Config, tmp_path: Path):
    os.chdir(tmp_path)
    component = Component(
        name='my-component',
        repo=None,
        version='master',
        repo_url=None,
    )
    with pytest.raises(click.ClickException) as excinfo:
        dependency_mgmt.create_component_symlinks(data, component)
    assert component.name in str(excinfo)
Exemplo n.º 5
0
def test_create_legacy_component_symlinks(capsys, data: Config, tmp_path):
    os.chdir(tmp_path)
    component = Component(
        name='my-component',
        repo=None,
        version='master',
        repo_url=None,
    )
    target_dir = Path('inventory/classes/components')
    target_dir.mkdir(parents=True, exist_ok=True)
    dependency_mgmt.create_component_symlinks(data, component)
    capture = capsys.readouterr()
    assert (target_dir / f"{component.name}.yml").is_symlink()
    assert 'Old-style component detected.' in capture.out
Exemplo n.º 6
0
def _setup(tmp_path, filter):
    os.chdir(tmp_path)

    test_run_component_new_command(tmp_path=tmp_path)

    target = "target"
    targetdir = tmp_path / "compiled" / target / "test"
    os.makedirs(targetdir, exist_ok=True)
    testf = targetdir / "object.yaml"
    with open(testf, "w") as objf:
        obj = {
            "metadata": {
                "name": "test",
                "namespace": "untouched",
            },
            "kind": "Secret",
            "apiVersion": "v1",
            "stringData": {
                "content": "verysecret",
            },
        }
        yaml.dump(obj, objf)
    with open(
            tmp_path / "dependencies" / "test-component" / "postprocess" /
            "filters.yml",
            "w",
    ) as filterf:
        yaml.dump(filter, filterf)

    config = Config()
    component = Component(
        "test-component",
        Repo(tmp_path / "dependencies" / "test-component"),
        "https://fake.repo.url",
        "master",
    )
    inventory = {
        "classes": {
            "defaults.test-component",
            "global.common",
            "components.test-component",
        },
        "parameters": {
            "test_component": {
                "namespace": "syn-test-component",
            },
        },
    }
    return testf, config, inventory, target, {"test-component": component}
Exemplo n.º 7
0
def _setup(tmp_path, filter):
    os.chdir(tmp_path)

    test_run_component_new_command(tmp_path=tmp_path)

    target = 'target'
    targetdir = tmp_path / 'compiled' / target / 'test'
    os.makedirs(targetdir, exist_ok=True)
    testf = targetdir / 'object.yaml'
    with open(testf, 'w') as objf:
        obj = {
            'metadata': {
                'name': 'test',
                'namespace': 'untouched',
            },
            'kind': 'Secret',
            'apiVersion': 'v1',
            'stringData': {
                'content': 'verysecret',
            },
        }
        yaml.dump(obj, objf)
    with open(
            tmp_path / 'dependencies' / 'test-component' / 'postprocess' /
            'filters.yml', 'w') as filterf:
        yaml.dump(filter, filterf)

    config = Config()
    component = Component('test-component',
                          Repo(tmp_path / 'dependencies' / 'test-component'),
                          'https://fake.repo.url', 'master')
    inventory = {
        'classes': {
            'defaults.test-component',
            'global.common',
            'components.test-component',
        },
        'parameters': {
            'test_component': {
                'namespace': 'syn-test-component',
            },
        },
    }
    return testf, config, inventory, target, {'test-component': component}
Exemplo n.º 8
0
def test_create_component_symlinks(capsys, data: Config, tmp_path):
    os.chdir(tmp_path)
    component = Component(
        name='my-component',
        repo=None,
        version='master',
        repo_url=None,
    )
    class_dir = Path('dependencies') / component.name / 'class'
    class_dir.mkdir(parents=True, exist_ok=True)
    (class_dir / f"{component.name}.yml").touch()
    (class_dir / 'defaults.yml').touch()
    target_dir = Path('inventory/classes/components')
    target_dir.mkdir(parents=True, exist_ok=True)
    target_defaults = Path('inventory/classes/defaults')
    target_defaults.mkdir(parents=True, exist_ok=True)
    dependency_mgmt.create_component_symlinks(data, component)
    capture = capsys.readouterr()
    assert (target_dir / f"{component.name}.yml").is_symlink()
    assert (target_defaults / f"{component.name}.yml").is_symlink()
    assert capture.out == ''
Exemplo n.º 9
0
def test_fetch_components(patch_discover, patch_urls, patch_clone, data: Config, tmp_path):
    os.chdir(tmp_path)
    components = ['component-one', 'component-two']
    # Prepare minimum component directories
    for component in components:
        class_dir = Path('dependencies') / component / 'class'
        class_dir.mkdir(parents=True, exist_ok=True)
        (class_dir / 'defaults.yml').touch(exist_ok=True)
    patch_discover.return_value = components
    patch_urls.return_value = [
        Component(
            name=c,
            repo=None,
            repo_url='mock-url',
            version='master',
        ) for c in components]
    dependency_mgmt.fetch_components(data)
    print(data._components)
    for component in components:
        assert component in data._components
        assert (Path('inventory/classes/components') / f"{component}.yml").is_symlink()
        assert (Path('inventory/classes/defaults') / f"{component}.yml").is_symlink()
        assert data.get_component_repo(component) is not None
Exemplo n.º 10
0
def compile_component(config: Config, component_path, value_files,
                      search_paths, output_path):
    # Resolve all input to absolute paths to fix symlinks
    component_path = P(component_path).resolve()
    value_files = [P(f).resolve() for f in value_files]
    search_paths = [P(d).resolve() for d in search_paths]
    output_path = P(output_path).resolve()
    # Ignore 'component-' prefix in dir name
    component_name = component_path.stem.replace('component-', '')

    click.secho(f"Compile component {component_name}...", bold=True)

    temp_dir = P(tempfile.mkdtemp(prefix='component-')).resolve()
    original_working_dir = os.getcwd()
    os.chdir(temp_dir)
    try:
        if config.debug:
            click.echo(f"   > Created temp workspace: {temp_dir}")

        _prepare_fake_inventory(temp_dir, component_name, component_path,
                                value_files)

        # Create class for fake parameters
        with open(temp_dir / 'inventory/classes/fake.yml', 'w') as file:
            file.write("""
parameters:
  cloud:
    provider: cloudscale
    region: rma1
  cluster:
    catalog_url: ssh://[email protected]/org/repo.git
    dist: test-distribution
    name: c-green-test-1234
  customer:
    name: t-silent-test-1234
  argocd:
    namespace: test

  kapitan:
    vars:
      target: test
      namespace: test
""")

        # Create test target
        with open(temp_dir / 'inventory/targets/test.yml', 'w') as file:
            value_classes = "\n".join([f"- {c.stem}" for c in value_files])
            file.write(f"""
classes:
- fake
- defaults.{component_name}
- components.{component_name}
{value_classes}
""")

        # Fake Argo CD lib
        (temp_dir / 'dependencies/lib').mkdir(exist_ok=True)
        with open(temp_dir / 'dependencies/lib/argocd.libjsonnet',
                  'w') as file:
            file.write("""
local ArgoApp(component, namespace, project='', secrets=true) = {};
local ArgoProject(name) = {};

{
  App: ArgoApp,
  Project: ArgoProject,
}
""")

        # Fetch Jsonnet libs
        fetch_jsonnet_libs(config, libs)

        # Compile component
        kapitan_compile(config,
                        target='test',
                        output_dir=output_path,
                        search_paths=search_paths,
                        fake_refs=True,
                        reveal=True)
        click.echo(f" > Component compiled to {output_path / 'compiled/test'}")

        # prepare inventory and fake component object for postprocess
        inventory = inventory_reclass(temp_dir / 'inventory')['nodes']['test']
        component = Component(component_name, Repo(component_path),
                              'https://fake.repo.url/', 'master')
        # We change the working directory to the output_path directory here,
        # as postprocess expects to find `compiled/<target>` in the working
        # directory.
        os.chdir(output_path)
        postprocess_components(config, inventory, 'test',
                               {component_name: component})
    finally:
        os.chdir(original_working_dir)
        if config.trace:
            click.echo(f" > Temp dir left in place {temp_dir}")
        else:
            if config.debug:
                click.echo(f" > Remove temp dir {temp_dir}")
            shutil.rmtree(temp_dir)