Compare commits

..

6 Commits

Author SHA1 Message Date
aacd2b1f07 ci: fix trivyignore path match
All checks were successful
ZeroDownTime/CloudBender/pipeline/head This commit looks good
2024-12-03 14:40:58 +00:00
31a9b6a7d5 ci: add trivyignore.yaml
Some checks failed
ZeroDownTime/CloudBender/pipeline/head There was a failure building this commit
2024-12-03 13:22:59 +00:00
638876381c feat: add list_stacks command to list existing pulumi stacks
Some checks failed
ZeroDownTime/CloudBender/pipeline/head There was a failure building this commit
ZeroDownTime/CloudBender/pipeline/tag There was a failure building this commit
2024-12-03 12:49:16 +00:00
266604b964 docs: improve error message
Some checks failed
ZeroDownTime/CloudBender/pipeline/head There was a failure building this commit
2024-12-02 12:49:59 +00:00
24c0346864 feat: add import task to pulumi stacks
Some checks failed
ZeroDownTime/CloudBender/pipeline/head There was a failure building this commit
2024-12-02 12:48:30 +00:00
9a25dc34bb fix: adjust to pulumi API changes
Some checks failed
ZeroDownTime/CloudBender/pipeline/head There was a failure building this commit
ZeroDownTime/CloudBender/pipeline/tag There was a failure building this commit
2024-11-27 17:50:09 +00:00
7 changed files with 116 additions and 23 deletions

8
.trivyignore.yaml Normal file
View File

@ -0,0 +1,8 @@
secrets:
- id: private-key
paths:
- "**/pulumi_aws/glue/connection.py"
- id: gcp-service-account
paths:
- "**/pulumi_aws/glue/connection.py"

View File

@ -55,12 +55,13 @@ def cli(ctx, profile, region, debug, directory):
sys.exit(1)
# Only load stackgroups to get profile and region
if ctx.invoked_subcommand == "wrap":
if ctx.invoked_subcommand in ["wrap", "list_stacks"]:
cb.read_config(loadStacks=False)
else:
cb.read_config()
cb.dump_config()
if debug:
cb.dump_config()
ctx.obj = cb
@ -212,6 +213,21 @@ def execute(cb, stack_name, function, args):
)
@click.command('import')
@click.argument("stack_name")
@click.argument("pulumi_state_file")
@click.pass_obj
def _import(cb, stack_name, pulumi_state_file):
"""Imports a Pulumi state file as stack"""
stacks = _find_stacks(cb, [stack_name])
for s in stacks:
if s.mode == "pulumi":
s._import(pulumi_state_file)
else:
logger.info("Cannot import as {} uses Cloudformation.".format(s.stackname))
@click.command()
@click.argument("stack_name")
@click.option(
@ -334,7 +350,16 @@ def wrap(cb, stack_group, cmd):
"""Execute custom external program"""
sg = cb.sg.get_stackgroup(stack_group)
cb.wrap(sg, " ".join(cmd))
sg.wrap(" ".join(cmd))
@click.command()
@click.argument("stack_group", nargs=1, required=True)
@click.pass_obj
def list_stacks(cb, stack_group):
"""List all Pulumi stacks"""
sg = cb.sg.get_stackgroup(stack_group)
sg.list_stacks()
@click.command()
@ -482,7 +507,9 @@ cli.add_command(refresh)
cli.add_command(preview)
cli.add_command(set_config)
cli.add_command(get_config)
cli.add_command(_import)
cli.add_command(export)
cli.add_command(list_stacks)
cli.add_command(assimilate)
cli.add_command(execute)
cli.add_command(wrap)

View File

@ -1,9 +1,7 @@
import pathlib
import logging
import pexpect
from .stackgroup import StackGroup
from .connection import BotoConnection
from .jinja import read_config_file
from .exceptions import InvalidProjectDir
@ -133,17 +131,3 @@ class CloudBender(object):
matching_stacks.append(s)
return matching_stacks
def wrap(self, stack_group, cmd):
"""
Set AWS environment based on profile before executing a custom command, eg. steampipe
"""
profile = stack_group.config.get("profile", "default")
region = stack_group.config.get("region", "global")
connection_manager = BotoConnection(profile, region)
connection_manager.exportProfileEnv()
child = pexpect.spawn(cmd)
child.interact()

View File

@ -189,7 +189,7 @@ def pulumi_ws(func):
)
project_settings = pulumi.automation.ProjectSettings(
name=project_name, runtime="python", backend={"url": pulumi_backend}
name=project_name, runtime="python", backend=pulumi.automation.ProjectBackend(url=pulumi_backend)
)
self.pulumi_ws_opts = pulumi.automation.LocalWorkspaceOptions(
@ -199,6 +199,8 @@ def pulumi_ws(func):
secrets_provider=secrets_provider,
)
# self.pulumi_workspace = pulumi.automation.LocalWorkspace(self.pulumi_ws_opts)
response = func(self, *args, **kwargs)
# Cleanup temp workspace

View File

@ -987,7 +987,7 @@ class Stack(object):
def assimilate(self):
"""Import resources into Pulumi stack"""
pulumi_stack = self._get_pulumi_stack(create=True)
pulumi_stack = self._get_pulumi_stack()
# now lets import each defined resource
for r in self._pulumi_code.RESOURCES:
@ -1024,6 +1024,19 @@ class Stack(object):
return
@pulumi_ws
def _import(self, pulumi_state_file):
"""Imports a Pulumi stack"""
pulumi_stack = self._get_pulumi_stack()
with open(pulumi_state_file, "r") as file:
state = json.loads(file.read())
deployment = pulumi.automation.Deployment(version=3, deployment=state)
pulumi_stack.import_stack(deployment)
return
@pulumi_ws
def set_config(self, key, value, secret):
"""Set a config or secret"""

View File

@ -1,6 +1,13 @@
import logging
import pprint
import pexpect
import pulumi
import tempfile
import rich.table
import rich.console
from .connection import BotoConnection
from .utils import dict_merge
from .jinja import read_config_file
from .stack import Stack
@ -25,7 +32,7 @@ class StackGroup(object):
for sg in self.sgs:
sg.dump_config()
logger.debug(
logger.info(
"StackGroup {}: {}".format(self.rel_path, pprint.pformat(self.config))
)
@ -135,3 +142,54 @@ class StackGroup(object):
return s
return None
def wrap(self, cmd):
"""
Set AWS environment based on profile before executing a custom command, eg. steampipe
"""
profile = self.config.get("profile", "default")
region = self.config.get("region", "global")
connection_manager = BotoConnection(profile, region)
connection_manager.exportProfileEnv()
child = pexpect.spawn(cmd)
child.interact()
def list_stacks(self):
project_name = self.config["parameters"]["Conglomerate"]
pulumi_backend = "{}/{}/{}".format(self.config["pulumi"]["backend"], project_name, self.config["region"])
project_settings = pulumi.automation.ProjectSettings(
name=project_name, runtime="python", backend=pulumi.automation.ProjectBackend(url=pulumi_backend)
)
work_dir = tempfile.mkdtemp(
dir=tempfile.gettempdir(), prefix="cloudbender-"
)
# AWS setup
profile = self.config.get("profile", "default")
region = self.config.get("region", "global")
connection_manager = BotoConnection(profile, region)
connection_manager.exportProfileEnv()
pulumi_workspace = pulumi.automation.LocalWorkspace(
work_dir=work_dir,
project_settings=project_settings
)
stacks = pulumi_workspace.list_stacks()
table = rich.table.Table(title="Pulumi stacks")
table.add_column("Name")
table.add_column("Last Update")
table.add_column("Resources")
for s in stacks:
table.add_row(s.name, str(s.last_update), str(s.resource_count))
console = rich.console.Console()
console.print(table)

View File

@ -11,7 +11,7 @@ authors = [
description = "Deploy and maintain infrastructure in automated and trackable manner"
readme = "README.md"
license = "AGPL-3.0-or-later"
requires-python = ">=3.9"
requires-python = ">=3.12"
dependencies = [
"boto3==1.35.70",
"mock==5.1.0",
@ -21,6 +21,7 @@ dependencies = [
"python-minifier==2.11.3",
"cfn-lint==1.20.1",
"ruamel.yaml==0.18.6",
"rich==13.9.4",
"pulumi==3.142.0",
"pulumi-aws==6.61.0",
"pulumi-aws-native==1.11.0",