pyinfra-dev / pyinfra

pyinfra turns Python code into shell commands and runs them on your servers. Execute ad-hoc commands and write declarative operations. Target SSH servers, local machine and Docker containers. Fast and scales from one server to thousands.
https://pyinfra.com
MIT License
3.91k stars 382 forks source link

Deployments - easy way to run them? #723

Closed romanchyla closed 2 weeks ago

romanchyla commented 2 years ago

Is your feature request related to a problem? Please describe

I was really confused on how to execute Deployments. Documentation is very clear on how to write them, but not on how to execute them. https://docs.pyinfra.com/en/1.x/api/deploys.html

And being lazy (I didn't really like the idea of having to create config/state objects -- and didn't know how) I spent next few hours trying to discover a workaround...

I tried stepping through the code; figured that I can execute my deployments with pyinfra CLI via pyinfra <target> <package.package.module.deployment>

By default, it only allows module.function (either from pyinfra.operations.{0} or from a custom module). But I didn't want to have to force my deployments into top package either.

So I modified https://github.com/Fizzadar/pyinfra/blob/current/pyinfra_cli/main.py#L423

    # Operation w/optional args (<module>.<op> ARG1 ARG2 ...)
    elif len(operations[0].split(".")) == 2:

into:

    # Operation w/optional args (<module>.<op> ARG1 ARG2 ...)
    elif len(operations[0].split(".")) >= 2:

The only other change I had to make in my deployment is to allow for any **kwarg, like so:


@deploy("Diagnostic output")
def hello_world(state=None, host=None, *args, **kwargs):
    server.shell(
        name="Printing variables from: {}".format(host.data.cfit_home),
        commands=[
            'echo "hello from server: {}"'.format(host.fact.hostname),
            'echo "config from all: {}"'.format(host.data.backup_folder),
        ],
        state=state,
        host=host,
    )

And then: aaah, oh the relief! I could actually execute my deployments and step through them in a debugger. This is an immense productivity boost.

Any real reason why this should not be allowed for deployments? I'm sure additional type safety checks could be added (or just documented).

Describe the solution you'd like

I'd like to have an easy way to execute my deployments, preferably via pyinfra CLI. Without having to create host/state etc. And also without forcing us to place deployments into a strict (single-level) hieararchy; that is needlessly restrictive

THE BEST part, really, is that I can now debug deployments as a real code - inside debugger; without having to rely on thousands of print statements. Other good part is that I can organize deployments into packages that make most sense in my situation. I'm convinced documenting this feature would make people enjoy pyinfra so much more!

It is possible that this feature is somehow available; then perhaps make it more visible in the documentation? If interested, I can send a short howto

Fizzadar commented 2 years ago

@romanchyla I really like this idea and have considered it in the past but never implemented. This could even become the recommended way of writing and executing pyinfra code entirely.

I think combined with the removal of the state/host arguments everywhere this becomes a better way to write pyinfra operations than just in the top level of a file.

Will definitely add support for this asap and then can think about the above.

Fizzadar commented 2 weeks ago

I believe v3 addresses all of these issues, please re-open/ping me if not.