From c4a203e64896ce6d26873a0f7731881e2c31c0b4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 22 Aug 2023 08:24:31 -0700 Subject: [PATCH] Rename to Kamal --- CODE_OF_CONDUCT.md | 4 +- CONTRIBUTING.md | 22 +-- Dockerfile | 18 +- Gemfile.lock | 4 +- README.md | 172 +++++++++--------- bin/{mrsk => kamal} | 4 +- bin/release | 10 +- mrsk.gemspec => kamal.gemspec | 10 +- lib/{mrsk.rb => kamal.rb} | 4 +- lib/{mrsk => kamal}/cli.rb | 4 +- lib/{mrsk => kamal}/cli/accessory.rb | 30 +-- lib/{mrsk => kamal}/cli/app.rb | 136 +++++++------- lib/{mrsk => kamal}/cli/base.rb | 44 ++--- lib/{mrsk => kamal}/cli/build.rb | 32 ++-- lib/kamal/cli/healthcheck.rb | 20 ++ lib/{mrsk => kamal}/cli/lock.rb | 8 +- lib/{mrsk => kamal}/cli/main.rb | 106 +++++------ lib/kamal/cli/prune.rb | 30 +++ lib/{mrsk => kamal}/cli/registry.rb | 8 +- lib/{mrsk => kamal}/cli/server.rb | 12 +- lib/{mrsk => kamal}/cli/templates/deploy.yml | 2 +- .../templates/sample_hooks/post-deploy.sample | 14 ++ .../templates/sample_hooks/pre-build.sample | 16 +- .../templates/sample_hooks/pre-connect.sample | 16 +- .../templates/sample_hooks/pre-deploy.sample | 18 +- lib/kamal/cli/templates/template.env | 2 + lib/{mrsk => kamal}/cli/traefik.rb | 56 +++--- lib/{mrsk => kamal}/commander.rb | 26 +-- lib/kamal/commands.rb | 2 + lib/{mrsk => kamal}/commands/accessory.rb | 2 +- lib/{mrsk => kamal}/commands/app.rb | 4 +- lib/{mrsk => kamal}/commands/auditor.rb | 4 +- lib/{mrsk => kamal}/commands/base.rb | 6 +- lib/{mrsk => kamal}/commands/builder.rb | 14 +- lib/{mrsk => kamal}/commands/builder/base.rb | 4 +- .../commands/builder/multiarch.rb | 4 +- .../commands/builder/multiarch/remote.rb | 2 +- .../commands/builder/native.rb | 2 +- .../commands/builder/native/cached.rb | 2 +- .../commands/builder/native/remote.rb | 4 +- lib/{mrsk => kamal}/commands/docker.rb | 2 +- lib/{mrsk => kamal}/commands/healthcheck.rb | 4 +- lib/{mrsk => kamal}/commands/hook.rb | 2 +- lib/{mrsk => kamal}/commands/lock.rb | 4 +- lib/{mrsk => kamal}/commands/prune.rb | 2 +- lib/{mrsk => kamal}/commands/registry.rb | 2 +- lib/{mrsk => kamal}/commands/traefik.rb | 4 +- lib/{mrsk => kamal}/configuration.rb | 28 +-- .../configuration/accessory.rb | 4 +- lib/{mrsk => kamal}/configuration/boot.rb | 2 +- lib/{mrsk => kamal}/configuration/builder.rb | 2 +- lib/{mrsk => kamal}/configuration/role.rb | 4 +- lib/{mrsk => kamal}/configuration/ssh.rb | 2 +- lib/{mrsk => kamal}/configuration/sshkit.rb | 2 +- lib/{mrsk => kamal}/sshkit_with_ext.rb | 0 lib/{mrsk => kamal}/tags.rb | 4 +- lib/{mrsk => kamal}/utils.rb | 4 +- .../utils/healthcheck_poller.rb | 6 +- lib/{mrsk => kamal}/utils/sensitive.rb | 2 +- lib/{mrsk => kamal}/version.rb | 2 +- lib/mrsk/cli/healthcheck.rb | 20 -- lib/mrsk/cli/prune.rb | 30 --- .../templates/sample_hooks/post-deploy.sample | 14 -- lib/mrsk/cli/templates/template.env | 2 - lib/mrsk/commands.rb | 2 - test/cli/accessory_test.rb | 50 ++--- test/cli/app_test.rb | 18 +- test/cli/build_test.rb | 20 +- test/cli/cli_test_case.rb | 34 ++-- test/cli/healthcheck_test.rb | 10 +- test/cli/lock_test.rb | 2 +- test/cli/main_test.rb | 118 ++++++------ test/cli/prune_test.rb | 6 +- test/cli/registry_test.rb | 2 +- test/cli/server_test.rb | 2 +- test/cli/traefik_test.rb | 18 +- test/commander_test.rb | 50 ++--- test/commands/accessory_test.rb | 2 +- test/commands/app_test.rb | 22 +-- test/commands/auditor_test.rb | 10 +- test/commands/builder_test.rb | 14 +- test/commands/docker_test.rb | 2 +- test/commands/healthcheck_test.rb | 12 +- test/commands/hook_test.rb | 20 +- test/commands/lock_test.rb | 8 +- test/commands/prune_test.rb | 2 +- test/commands/registry_test.rb | 14 +- test/commands/traefik_test.rb | 4 +- test/configuration/accessory_test.rb | 12 +- test/configuration/builder_test.rb | 10 +- test/configuration/role_test.rb | 18 +- test/configuration/ssh_test.rb | 10 +- test/configuration/sshkit_test.rb | 6 +- test/configuration_test.rb | 66 +++---- test/integration/accessory_test.rb | 14 +- test/integration/app_test.rb | 22 +-- test/integration/docker-compose.yml | 4 +- test/integration/docker/deployer/setup.sh | 6 +- test/integration/integration_test.rb | 8 +- test/integration/lock_test.rb | 10 +- test/integration/main_test.rb | 14 +- test/integration/traefik_test.rb | 22 +-- test/test_helper.rb | 2 +- test/utils_test.rb | 48 ++--- 104 files changed, 870 insertions(+), 870 deletions(-) rename bin/{mrsk => kamal} (89%) rename mrsk.gemspec => kamal.gemspec (81%) rename lib/{mrsk.rb => kamal.rb} (68%) rename lib/{mrsk => kamal}/cli.rb (76%) rename lib/{mrsk => kamal}/cli/accessory.rb (86%) rename lib/{mrsk => kamal}/cli/app.rb (59%) rename lib/{mrsk => kamal}/cli/base.rb (75%) rename lib/{mrsk => kamal}/cli/build.rb (68%) create mode 100644 lib/kamal/cli/healthcheck.rb rename lib/{mrsk => kamal}/cli/lock.rb (69%) rename lib/{mrsk => kamal}/cli/main.rb (63%) create mode 100644 lib/kamal/cli/prune.rb rename lib/{mrsk => kamal}/cli/registry.rb (59%) rename lib/{mrsk => kamal}/cli/server.rb (55%) rename lib/{mrsk => kamal}/cli/templates/deploy.yml (98%) create mode 100755 lib/kamal/cli/templates/sample_hooks/post-deploy.sample rename lib/{mrsk => kamal}/cli/templates/sample_hooks/pre-build.sample (76%) rename lib/{mrsk => kamal}/cli/templates/sample_hooks/pre-connect.sample (83%) rename lib/{mrsk => kamal}/cli/templates/sample_hooks/pre-deploy.sample (90%) create mode 100644 lib/kamal/cli/templates/template.env rename lib/{mrsk => kamal}/cli/traefik.rb (56%) rename lib/{mrsk => kamal}/commander.rb (80%) create mode 100644 lib/kamal/commands.rb rename lib/{mrsk => kamal}/commands/accessory.rb (97%) rename lib/{mrsk => kamal}/commands/app.rb (97%) rename lib/{mrsk => kamal}/commands/auditor.rb (76%) rename lib/{mrsk => kamal}/commands/base.rb (92%) rename lib/{mrsk => kamal}/commands/builder.rb (66%) rename lib/{mrsk => kamal}/commands/builder/base.rb (92%) rename lib/{mrsk => kamal}/commands/builder/multiarch.rb (79%) rename lib/{mrsk => kamal}/commands/builder/multiarch/remote.rb (93%) rename lib/{mrsk => kamal}/commands/builder/native.rb (81%) rename lib/{mrsk => kamal}/commands/builder/native/cached.rb (75%) rename lib/{mrsk => kamal}/commands/builder/native/remote.rb (89%) rename lib/{mrsk => kamal}/commands/docker.rb (90%) rename lib/{mrsk => kamal}/commands/healthcheck.rb (91%) rename lib/{mrsk => kamal}/commands/hook.rb (82%) rename lib/{mrsk => kamal}/commands/lock.rb (92%) rename lib/{mrsk => kamal}/commands/prune.rb (96%) rename lib/{mrsk => kamal}/commands/registry.rb (87%) rename lib/{mrsk => kamal}/commands/traefik.rb (96%) rename lib/{mrsk => kamal}/configuration.rb (87%) rename lib/{mrsk => kamal}/configuration/accessory.rb (98%) rename lib/{mrsk => kamal}/configuration/boot.rb (90%) rename lib/{mrsk => kamal}/configuration/builder.rb (98%) rename lib/{mrsk => kamal}/configuration/role.rb (98%) rename lib/{mrsk => kamal}/configuration/ssh.rb (96%) rename lib/{mrsk => kamal}/configuration/sshkit.rb (89%) rename lib/{mrsk => kamal}/sshkit_with_ext.rb (100%) rename lib/{mrsk => kamal}/tags.rb (90%) rename lib/{mrsk => kamal}/utils.rb (98%) rename lib/{mrsk => kamal}/utils/healthcheck_poller.rb (83%) rename lib/{mrsk => kamal}/utils/sensitive.rb (93%) rename lib/{mrsk => kamal}/version.rb (65%) delete mode 100644 lib/mrsk/cli/healthcheck.rb delete mode 100644 lib/mrsk/cli/prune.rb delete mode 100755 lib/mrsk/cli/templates/sample_hooks/post-deploy.sample delete mode 100644 lib/mrsk/cli/templates/template.env delete mode 100644 lib/mrsk/commands.rb diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index f849cd2dd..7acae0d55 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,10 +1,10 @@ # Contributor Code of Conduct -As contributors and maintainers of the MRSK project, we pledge to create a welcoming and inclusive environment for everyone. We value the participation of each member of our community and want all contributors to feel respected and valued. +As contributors and maintainers of the Kamal project, we pledge to create a welcoming and inclusive environment for everyone. We value the participation of each member of our community and want all contributors to feel respected and valued. We are committed to providing a harassment-free experience for everyone, regardless of gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, age, or religion (or lack thereof). We do not tolerate harassment of participants in any form. -This code of conduct applies to all MRSK project spaces, including but not limited to project code, issue trackers, chat rooms, and mailing lists. Violations of this code of conduct may result in removal from the project community. +This code of conduct applies to all Kamal project spaces, including but not limited to project code, issue trackers, chat rooms, and mailing lists. Violations of this code of conduct may result in removal from the project community. ## Our standards diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e7936fefd..7b7d4ec13 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,18 +1,18 @@ -# Contributing to MRSK development +# Contributing to Kamal development -Thank you for considering contributing to MRSK! This document outlines some guidelines for contributing to this open source project. +Thank you for considering contributing to Kamal! This document outlines some guidelines for contributing to this open source project. -Please make sure to review our [Code of Conduct](CODE_OF_CONDUCT.md) before contributing to MRSK. +Please make sure to review our [Code of Conduct](CODE_OF_CONDUCT.md) before contributing to Kamal. There are several ways you can contribute to the betterment of the project: -- **Report an issue?** - If the issue isn’t reported, we can’t fix it. Please report any bugs, feature, and/or improvement requests on the [MRSK GitHub Issues tracker](https://github.com/mrsked/mrsk/issues). -- **Submit patches** - Do you have a new feature or a fix you'd like to share? [Submit a pull request](https://github.com/mrsked/mrsk/pulls)! -- **Write blog articles** - Are you using MRSK? We'd love to hear how you're using it with your projects. Write a tutorial and post it on your blog! +- **Report an issue?** - If the issue isn’t reported, we can’t fix it. Please report any bugs, feature, and/or improvement requests on the [Kamal GitHub Issues tracker](https://github.com/basecamp/kamal/issues). +- **Submit patches** - Do you have a new feature or a fix you'd like to share? [Submit a pull request](https://github.com/basecamp/kamal/pulls)! +- **Write blog articles** - Are you using Kamal? We'd love to hear how you're using it with your projects. Write a tutorial and post it on your blog! ## Issues -If you encounter any issues with the project, please check the [existing issues](https://github.com/mrsked/mrsk/issues) first to see if the issue has already been reported. If the issue hasn't been reported, please open a new issue with a clear description of the problem and steps to reproduce it. +If you encounter any issues with the project, please check the [existing issues](https://github.com/basecamp/kamal/issues) first to see if the issue has already been reported. If the issue hasn't been reported, please open a new issue with a clear description of the problem and steps to reproduce it. ## Pull Requests @@ -33,17 +33,17 @@ A good commit message should describe what changed and why. ## Development -The `main` branch is regularly built and tested, but it is not guaranteed to be completely stable. Tags are created regularly from release branches to indicate new official, stable release versions of MRSK. +The `main` branch is regularly built and tested, but it is not guaranteed to be completely stable. Tags are created regularly from release branches to indicate new official, stable release versions of Kamal. -MRSK is written in Ruby. You should have Ruby 3.2+ installed on your machine in order to work on MRSK. If that's already setup, run `bundle` in the root directory to install all dependencies. Then you can run `bin/test` to run all tests. +Kamal is written in Ruby. You should have Ruby 3.2+ installed on your machine in order to work on Kamal. If that's already setup, run `bundle` in the root directory to install all dependencies. Then you can run `bin/test` to run all tests. 1. Fork the project repository. 2. Create a new branch for your contribution. 3. Write your code or make the desired changes. 4. **Ensure that your code passes the project's minitests by running ./bin/test.** 5. Commit your changes and push them to your forked repository. -6. [Open a pull request](https://github.com/mrsked/mrsk/pulls) to the main project repository with a detailed description of your changes. +6. [Open a pull request](https://github.com/basecamp/kamal/pulls) to the main project repository with a detailed description of your changes. ## License -MRSK is released under the MIT License. By contributing to this project, you agree to license your contributions under the same license. +Kamal is released under the MIT License. By contributing to this project, you agree to license your contributions under the same license. diff --git a/Dockerfile b/Dockerfile index dc8c02300..72640a3e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,14 +4,14 @@ FROM ruby:3.2.0-alpine # Install docker/buildx-bin COPY --from=docker/buildx-bin /buildx /usr/libexec/docker/cli-plugins/docker-buildx -# Set the working directory to /mrsk -WORKDIR /mrsk +# Set the working directory to /kamal +WORKDIR /kamal # Copy the Gemfile, Gemfile.lock into the container -COPY Gemfile Gemfile.lock mrsk.gemspec ./ +COPY Gemfile Gemfile.lock kamal.gemspec ./ -# Required in mrsk.gemspec -COPY lib/mrsk/version.rb /mrsk/lib/mrsk/version.rb +# Required in kamal.gemspec +COPY lib/kamal/version.rb /kamal/lib/kamal/version.rb # Install system dependencies RUN apk add --no-cache --update build-base git docker openrc openssh-client-default \ @@ -25,8 +25,8 @@ RUN apk add --no-cache --update build-base git docker openrc openssh-client-defa COPY . . # Install the gem locally from the project folder -RUN gem build mrsk.gemspec && \ - gem install ./mrsk-*.gem --no-document +RUN gem build kamal.gemspec && \ + gem install ./kamal-*.gem --no-document # Set the working directory to /workdir WORKDIR /workdir @@ -36,5 +36,5 @@ WORKDIR /workdir RUN git config --global --add safe.directory /workdir # Set the entrypoint to run the installed binary in /workdir -# Example: docker run -it -v "$PWD:/workdir" mrsk init -ENTRYPOINT ["mrsk"] +# Example: docker run -it -v "$PWD:/workdir" kamal init +ENTRYPOINT ["kamal"] diff --git a/Gemfile.lock b/Gemfile.lock index 2765ecd48..1c33c967e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - mrsk (0.15.1) + kamal (0.15.1) activesupport (>= 7.0) bcrypt_pbkdf (~> 1.0) concurrent-ruby (~> 1.2) @@ -100,7 +100,7 @@ PLATFORMS DEPENDENCIES debug mocha - mrsk! + kamal! railties BUNDLED WITH diff --git a/README.md b/README.md index 8a8dd088f..edfe391e9 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,28 @@ -# MRSK +# Kamal -MRSK deploys web apps anywhere from bare metal to cloud VMs using Docker with zero downtime. It uses the dynamic reverse-proxy Traefik to hold requests while the new application container is started and the old one is stopped. It works seamlessly across multiple hosts, using SSHKit to execute commands. It was built for Rails applications, but works with any type of web app that can be containerized with Docker. +Kamal deploys web apps anywhere from bare metal to cloud VMs using Docker with zero downtime. It uses the dynamic reverse-proxy Traefik to hold requests while the new application container is started and the old one is stopped. It works seamlessly across multiple hosts, using SSHKit to execute commands. It was built for Rails applications, but works with any type of web app that can be containerized with Docker. Watch the screencast: https://www.youtube.com/watch?v=LL1cV2FXZ5I Join us on Discord: https://discord.gg/YgHVT7GCXS -Ask questions: https://github.com/mrsked/mrsk/discussions +Ask questions: https://github.com/basecamp/kamal/discussions ## Installation -If you have a Ruby environment available, you can install MRSK globally with: +If you have a Ruby environment available, you can install Kamal globally with: ```sh -gem install mrsk +gem install kamal ``` ...otherwise, you can run a dockerized version via an alias (add this to your .bashrc or similar to simplify re-use): ```sh -alias mrsk='docker run --rm -it -v $HOME/.ssh:/root/.ssh -v /var/run/docker.sock:/var/run/docker.sock -v ${PWD}/:/workdir ghcr.io/mrsked/mrsk' +alias kamal='docker run --rm -it -v $HOME/.ssh:/root/.ssh -v /var/run/docker.sock:/var/run/docker.sock -v ${PWD}/:/workdir ghcr.io/basecamp/kamal' ``` -Then, inside your app directory, run `mrsk init` (or `mrsk init --bundle` within Rails 7+ apps where you want a bin/mrsk binstub). Now edit the new file `config/deploy.yml`. It could look as simple as this: +Then, inside your app directory, run `kamal init` (or `kamal init --bundle` within Rails 7+ apps where you want a bin/kamal binstub). Now edit the new file `config/deploy.yml`. It could look as simple as this: ```yaml service: hey @@ -33,18 +33,18 @@ servers: registry: username: registry-user-name password: - - MRSK_REGISTRY_PASSWORD + - KAMAL_REGISTRY_PASSWORD env: secret: - RAILS_MASTER_KEY ``` -Then edit your `.env` file to add your registry password as `MRSK_REGISTRY_PASSWORD` (and your `RAILS_MASTER_KEY` for production with a Rails app). +Then edit your `.env` file to add your registry password as `KAMAL_REGISTRY_PASSWORD` (and your `RAILS_MASTER_KEY` for production with a Rails app). Now you're ready to deploy to the servers: ``` -mrsk setup +kamal setup ``` This will: @@ -61,64 +61,64 @@ This will: 10. Stop the old container running the previous version of the app. 11. Prune unused images and stopped containers to ensure servers don't fill up. -Voila! All the servers are now serving the app on port 80. If you're just running a single server, you're ready to go. If you're running multiple servers, you need to put a load balancer in front of them. For subsequent deploys, or if your servers already have Docker and curl installed, you can just run `mrsk deploy`. +Voila! All the servers are now serving the app on port 80. If you're just running a single server, you're ready to go. If you're running multiple servers, you need to put a load balancer in front of them. For subsequent deploys, or if your servers already have Docker and curl installed, you can just run `kamal deploy`. ### Rails <7 usage -MRSK is not needed to be in your application Gemfile to be used. However, if you want to guarantee specific MRSK version in your CI/CD workflows, you can create a separate Gemfile for MRSK, for example, `gemfile/mrsk.gemfile`: +Kamal is not needed to be in your application Gemfile to be used. However, if you want to guarantee specific Kamal version in your CI/CD workflows, you can create a separate Gemfile for Kamal, for example, `gemfile/kamal.gemfile`: ```ruby source 'https://rubygems.org' -gem 'mrsk', '~> 0.14' +gem 'kamal', '~> 0.14' ``` -Bundle with `BUNDLE_GEMFILE=gemfiles/mrsk.gemfile bundle`. +Bundle with `BUNDLE_GEMFILE=gemfiles/kamal.gemfile bundle`. -After this MRSK can be used for deployment: +After this Kamal can be used for deployment: ```sh -BUNDLE_GEMFILE=gemfiles/mrsk.gemfile bundle exec mrsk deploy +BUNDLE_GEMFILE=gemfiles/kamal.gemfile bundle exec kamal deploy ``` ## Vision In the past decade+, there's been an explosion in commercial offerings that make deploying web apps easier. Heroku kicked it off with an incredible offering that stayed ahead of the competition seemingly forever. These days we have excellent alternatives like Fly.io and Render. And hosted Kubernetes is making things easier too on AWS, GCP, Digital Ocean, and elsewhere. But these are all offerings that have you renting computers in the cloud at a premium. If you want to run on your own hardware, or even just have a clear migration path to do so in the future, you need to carefully consider how locked in you get to these commercial platforms. Preferably before the bills swallow your business whole! -MRSK seeks to bring the advance in ergonomics pioneered by these commercial offerings to deploying web apps anywhere. Whether that's low-cost cloud options without the managed-service markup from the likes of Digital Ocean, Hetzner, OVH, etc., or it's your own colocated bare metal. To MRSK, it's all the same. Feed the config file a list of IP addresses with vanilla Ubuntu servers that have seen no prep beyond an added SSH key, and you'll be running in literally minutes. +Kamal seeks to bring the advance in ergonomics pioneered by these commercial offerings to deploying web apps anywhere. Whether that's low-cost cloud options without the managed-service markup from the likes of Digital Ocean, Hetzner, OVH, etc., or it's your own colocated bare metal. To Kamal, it's all the same. Feed the config file a list of IP addresses with vanilla Ubuntu servers that have seen no prep beyond an added SSH key, and you'll be running in literally minutes. This approach gives you enormous portability. You can have your web app deployed on several clouds at ease like this. Or you can buy the baseline with your own hardware, then deploy to a cloud before a big seasonal spike to get more capacity. When you're not locked into a single provider from a tooling perspective, there are a lot of compelling options available. -Ultimately, MRSK is meant to compress the complexity of going to production using open source tooling that isn't tied to any commercial offering. Not to zero, mind you. You're probably still better off with a fully managed service if basic Linux or Docker is still difficult, but as soon as those concepts are familiar, you'll be ready to go with MRSK. +Ultimately, Kamal is meant to compress the complexity of going to production using open source tooling that isn't tied to any commercial offering. Not to zero, mind you. You're probably still better off with a fully managed service if basic Linux or Docker is still difficult, but as soon as those concepts are familiar, you'll be ready to go with Kamal. ## Why not just run Capistrano, Kubernetes or Docker Swarm? -MRSK basically is Capistrano for Containers, without the need to carefully prepare servers in advance. No need to ensure that the servers have just the right version of Ruby or other dependencies you need. That all lives in the Docker image now. You can boot a brand new Ubuntu (or whatever) server, add it to the list of servers in MRSK, and it'll be auto-provisioned with Docker, and run right away. Docker's layer caching also speeds up deployments with less mucking about on the server. And the images built for MRSK can be used for CI or later introspection. +Kamal basically is Capistrano for Containers, without the need to carefully prepare servers in advance. No need to ensure that the servers have just the right version of Ruby or other dependencies you need. That all lives in the Docker image now. You can boot a brand new Ubuntu (or whatever) server, add it to the list of servers in Kamal, and it'll be auto-provisioned with Docker, and run right away. Docker's layer caching also speeds up deployments with less mucking about on the server. And the images built for Kamal can be used for CI or later introspection. -Kubernetes is a beast. Running it yourself on your own hardware is not for the faint of heart. It's a fine option if you want to run on someone else's platform, either transparently [like Render](https://thenewstack.io/render-cloud-deployment-with-less-engineering/) or explicitly on AWS/GCP, but if you'd like the freedom to move between cloud and your own hardware, or even mix the two, MRSK is much simpler. You can see everything that's going on, it's just basic Docker commands being called. +Kubernetes is a beast. Running it yourself on your own hardware is not for the faint of heart. It's a fine option if you want to run on someone else's platform, either transparently [like Render](https://thenewstack.io/render-cloud-deployment-with-less-engineering/) or explicitly on AWS/GCP, but if you'd like the freedom to move between cloud and your own hardware, or even mix the two, Kamal is much simpler. You can see everything that's going on, it's just basic Docker commands being called. -Docker Swarm is much simpler than Kubernetes, but it's still built on the same declarative model that uses state reconciliation. MRSK is intentionally designed around imperative commands, like Capistrano. +Docker Swarm is much simpler than Kubernetes, but it's still built on the same declarative model that uses state reconciliation. Kamal is intentionally designed around imperative commands, like Capistrano. Ultimately, there are a myriad of ways to deploy web apps, but this is the toolkit we're using at [37signals](https://37signals.com) to bring [HEY](https://www.hey.com) [home from the cloud](https://world.hey.com/dhh/why-we-re-leaving-the-cloud-654b47e0) without losing the advantages of modern containerization tooling. -## Running MRSK from Docker +## Running Kamal from Docker -MRSK is packaged up in a Docker container similarly to [rails/docked](https://github.com/rails/docked). This will allow you to run MRSK (from your application directory) without having to install any dependencies other than Docker. Add the following alias to your profile configuration to make working with the container more convenient: +Kamal is packaged up in a Docker container similarly to [rails/docked](https://github.com/rails/docked). This will allow you to run Kamal (from your application directory) without having to install any dependencies other than Docker. Add the following alias to your profile configuration to make working with the container more convenient: ```bash -alias mrsk="docker run -it --rm -v '${PWD}:/workdir' -v '${SSH_AUTH_SOCK}:/ssh-agent' -v /var/run/docker.sock:/var/run/docker.sock -e 'SSH_AUTH_SOCK=/ssh-agent' ghcr.io/mrsked/mrsk:latest" +alias kamal="docker run -it --rm -v '${PWD}:/workdir' -v '${SSH_AUTH_SOCK}:/ssh-agent' -v /var/run/docker.sock:/var/run/docker.sock -e 'SSH_AUTH_SOCK=/ssh-agent' ghcr.io/basecamp/kamal:latest" ``` -Since MRSK uses SSH to establish a remote connection, it will need access to your SSH agent. The above command uses a volume mount to make it available inside the container and configures the SSH agent inside the container to make use of it. +Since Kamal uses SSH to establish a remote connection, it will need access to your SSH agent. The above command uses a volume mount to make it available inside the container and configures the SSH agent inside the container to make use of it. ## Configuration ### Using .env file to load required environment variables -MRSK uses [dotenv](https://github.com/bkeepers/dotenv) to automatically load environment variables set in the `.env` file present in the application root. This file can be used to set variables like `MRSK_REGISTRY_PASSWORD` or database passwords. But for this reason you must ensure that .env files are not checked into Git or included in your Dockerfile! The format is just key-value like: +Kamal uses [dotenv](https://github.com/bkeepers/dotenv) to automatically load environment variables set in the `.env` file present in the application root. This file can be used to set variables like `KAMAL_REGISTRY_PASSWORD` or database passwords. But for this reason you must ensure that .env files are not checked into Git or included in your Dockerfile! The format is just key-value like: ```bash -MRSK_REGISTRY_PASSWORD=pw +KAMAL_REGISTRY_PASSWORD=pw DB_PASSWORD=secret123 ``` @@ -129,17 +129,17 @@ DB_PASSWORD=secret123 If you're using a centralized secret store, like 1Password, you can create `.env.erb` as a template which looks up the secrets. Example of a .env.erb file: ```erb -<% if (session_token = `op signin --account my-one-password-account --raw`.strip) != "" %># Generated by mrsk envify +<% if (session_token = `op signin --account my-one-password-account --raw`.strip) != "" %># Generated by kamal envify GITHUB_TOKEN=<%= `gh config get -h github.com oauth_token`.strip %> -MRSK_REGISTRY_PASSWORD=<%= `op read "op://Vault/Docker Hub/password" -n --session #{session_token}` %> +KAMAL_REGISTRY_PASSWORD=<%= `op read "op://Vault/Docker Hub/password" -n --session #{session_token}` %> RAILS_MASTER_KEY=<%= `op read "op://Vault/My App/RAILS_MASTER_SECRET" -n --session #{session_token}` %> MYSQL_ROOT_PASSWORD=<%= `op read "op://Vault/My App/MYSQL_ROOT_PASSWORD" -n --session #{session_token}` %> <% else raise ArgumentError, "Session token missing" end %> ``` -This template can safely be checked into git. Then everyone deploying the app can run `mrsk envify` when they setup the app for the first time or passwords change to get the correct `.env` file. +This template can safely be checked into git. Then everyone deploying the app can run `kamal envify` when they setup the app for the first time or passwords change to get the correct `.env` file. -If you need separate env variables for different destinations, you can set them with `.env.destination.erb` for the template, which will generate `.env.staging` when run with `mrsk envify -d staging`. +If you need separate env variables for different destinations, you can set them with `.env.destination.erb` for the template, which will generate `.env.staging` when run with `kamal envify -d staging`. Note: If you utilize biometrics with 1Password you can remove the `session_token` related parts in the example and just call `op read op://Vault/Docker Hub/password -n`. @@ -181,12 +181,12 @@ and extract the `id` of `SOME_SECRET` from the `json` above and use in the `erb` Example `.env.erb` file: ```erb -<% if (session_token=`bw unlock --raw`.strip) != "" %># Generated by mrsk envify +<% if (session_token=`bw unlock --raw`.strip) != "" %># Generated by kamal envify SOME_SECRET=<%= `bw get notes 123123123-1232-4224-222f-234234234234 --session #{session_token}` %> <% else raise ArgumentError, "session_token token missing" end %> ``` -Then everyone deploying the app can run `mrsk envify` and mrsk will generate `.env` +Then everyone deploying the app can run `kamal envify` and kamal will generate `.env` ### Using another registry than Docker Hub @@ -202,7 +202,7 @@ registry: - DOCKER_REGISTRY_TOKEN ``` -A reference to secret `DOCKER_REGISTRY_TOKEN` will look for `ENV["DOCKER_REGISTRY_TOKEN"]` on the machine running MRSK. +A reference to secret `DOCKER_REGISTRY_TOKEN` will look for `ENV["DOCKER_REGISTRY_TOKEN"]` on the machine running Kamal. #### Using AWS ECR as the container registry @@ -226,7 +226,7 @@ ssh: user: app ``` -If you are using non-root user (`app` as above example), you need to bootstrap your servers manually, before using them with MRSK. On Ubuntu, you'd do: +If you are using non-root user (`app` as above example), you need to bootstrap your servers manually, before using them with Kamal. On Ubuntu, you'd do: ```bash sudo apt update @@ -290,11 +290,11 @@ env: - REDIS_PASSWORD ``` -The list of secret env variables will be expanded at run time from your local machine. So a reference to a secret `DATABASE_PASSWORD` will look for `ENV["DATABASE_PASSWORD"]` on the machine running MRSK. Just like with build secrets. +The list of secret env variables will be expanded at run time from your local machine. So a reference to a secret `DATABASE_PASSWORD` will look for `ENV["DATABASE_PASSWORD"]` on the machine running Kamal. Just like with build secrets. If the referenced secret ENVs are missing, the configuration will be halted with a `KeyError` exception. -Note: Marking an ENV as secret currently only redacts its value in the output for MRSK. The ENV is still injected in the clear into the container at runtime. +Note: Marking an ENV as secret currently only redacts its value in the output for Kamal. The ENV is still injected in the clear into the container at runtime. ### Using volumes @@ -305,11 +305,11 @@ volumes: - "/local/path:/container/path" ``` -### MRSK env variables +### Kamal env variables The following env variables are set when your container runs: -`MRSK_CONTAINER_NAME` : this contains the current container name and version +`KAMAL_CONTAINER_NAME` : this contains the current container name and version ### Using different roles for servers @@ -410,7 +410,7 @@ That'll start the job containers with `docker run ... --cap-add --cpu-count 4 .. ### Setting a minimum version -You can set the minimum MRSK version with: +You can set the minimum Kamal version with: ```yaml minimum_version: 0.13.3 @@ -443,7 +443,7 @@ stop_wait_time: 30 ### Using remote builder for native multi-arch -If you're developing on ARM64 (like Apple Silicon), but you want to deploy on AMD64 (x86 64-bit), you can use multi-architecture images. By default, MRSK will setup a local buildx configuration that does this through QEMU emulation. But this can be quite slow, especially on the first build. +If you're developing on ARM64 (like Apple Silicon), but you want to deploy on AMD64 (x86 64-bit), you can use multi-architecture images. By default, Kamal will setup a local buildx configuration that does this through QEMU emulation. But this can be quite slow, especially on the first build. If you want to speed up this process by using a remote AMD64 host to natively build the AMD64 part of the image, while natively building the ARM64 part locally, you can do so using builder options: @@ -479,7 +479,7 @@ builder: multiarch: false ``` -This is also a good option if you're running MRSK from a CI server that shares architecture with the deployment servers. +This is also a good option if you're running Kamal from a CI server that shares architecture with the deployment servers. ### Using a different Dockerfile or context when building @@ -503,7 +503,7 @@ builder: ### Using multistage builder cache -Docker multistage build cache can singlehandedly speed up your builds by a lot. Currently MRSK only supports using the GHA cache or the Registry cache: +Docker multistage build cache can singlehandedly speed up your builds by a lot. Currently Kamal only supports using the GHA cache or the Registry cache: ```yaml # Using GHA cache @@ -579,7 +579,7 @@ traefik: ### Traefik version, upgrades, and custom images -MRSK runs the traefik:v2.9 image to track Traefik 2.9.x releases. +Kamal runs the traefik:v2.9 image to track Traefik 2.9.x releases. To pin Traefik to a specific version or an image published to your registry, specify `image`: @@ -593,7 +593,7 @@ This is useful for downgrading Traefik if there's an unexpected breaking change in a minor version release, upgrading Traefik to test forthcoming releases, or running your own Traefik-derived image. -MRSK has not been tested for compatibility with Traefik 3 betas. Please do! +Kamal has not been tested for compatibility with Traefik 3 betas. Please do! ### Traefik container configuration @@ -654,11 +654,11 @@ traefik: If you make changes to Traefik args or labels, you'll need to reboot with: -`mrsk traefik reboot` +`kamal traefik reboot` In production, reboot the Traefik containers one by one with a slower but safer approach, using a rolling reboot: -`mrsk traefik reboot --rolling` +`kamal traefik reboot --rolling` ### Configuring build args for new images @@ -679,7 +679,7 @@ FROM ruby:$RUBY_VERSION-slim as base ### Using accessories for database, cache, search services -You can manage your accessory services via MRSK as well. Accessories are long-lived services that your app depends on. They are not updated when you deploy. +You can manage your accessory services via Kamal as well. Accessories are long-lived services that your app depends on. They are not updated when you deploy. ```yaml accessories: @@ -728,7 +728,7 @@ The hosts that the accessories will run on can be specified by hosts or roles: - jobs ``` -Now run `mrsk accessory start mysql` to start the MySQL server on 1.1.1.3. See `mrsk accessory` for all the commands possible. +Now run `kamal accessory start mysql` to start the MySQL server on 1.1.1.3. See `kamal accessory` for all the commands possible. Accessory images must be public or tagged in your private registry. @@ -749,7 +749,7 @@ This assumes the Cron settings are stored in `config/crontab`. ### Healthcheck -MRSK uses Docker healthchecks to check the health of your application during deployment. Traefik uses this same healthcheck status to determine when a container is ready to receive traffic. +Kamal uses Docker healthchecks to check the health of your application during deployment. Traefik uses this same healthcheck status to determine when a container is ready to receive traffic. The healthcheck defaults to testing the HTTP response to the path `/up` on port 3000, up to 7 times. You can tailor this behaviour with the `healthcheck` setting: @@ -761,7 +761,7 @@ healthcheck: interval: 20s ``` -This will ensure your application is configured with a traefik label for the healthcheck against `/healthz` and that the pre-deploy healthcheck that MRSK performs is done against the same path on port 4000. +This will ensure your application is configured with a traefik label for the healthcheck against `/healthz` and that the pre-deploy healthcheck that Kamal performs is done against the same path on port 4000. You can also specify a custom healthcheck command, which is useful for non-HTTP services: @@ -795,7 +795,7 @@ You can execute one-off commands on the servers: ```bash # Runs command on all servers -mrsk app exec 'ruby -v' +kamal app exec 'ruby -v' App Host: 192.168.0.1 ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux] @@ -803,12 +803,12 @@ App Host: 192.168.0.2 ruby 3.1.3p185 (2022-11-24 revision 1a6b16756e) [x86_64-linux] # Runs command on primary server -mrsk app exec --primary 'cat .ruby-version' +kamal app exec --primary 'cat .ruby-version' App Host: 192.168.0.1 3.1.3 # Runs Rails command on all servers -mrsk app exec 'bin/rails about' +kamal app exec 'bin/rails about' App Host: 192.168.0.1 About your application's environment Rails version 7.1.0.alpha @@ -834,7 +834,7 @@ Database adapter sqlite3 Database schema version 20221231233303 # Run Rails runner on primary server -mrsk app exec -p 'bin/rails runner "puts Rails.application.config.time_zone"' +kamal app exec -p 'bin/rails runner "puts Rails.application.config.time_zone"' UTC ``` @@ -844,19 +844,19 @@ You can run interactive commands, like a Rails console or a bash session, on a s ```bash # Starts a bash session in a new container made from the most recent app image -mrsk app exec -i bash +kamal app exec -i bash # Starts a bash session in the currently running container for the app -mrsk app exec -i --reuse bash +kamal app exec -i --reuse bash # Starts a Rails console in a new container made from the most recent app image -mrsk app exec -i 'bin/rails console' +kamal app exec -i 'bin/rails console' ``` ### Running details to show state of containers -You can see the state of your servers by running `mrsk details`: +You can see the state of your servers by running `kamal details`: ``` Traefik Host: 192.168.0.1 @@ -876,11 +876,11 @@ CONTAINER ID IMAGE 1d3c91ed1f55 registry.digitalocean.com/user/app:6ef8a6a84c525b123c5245345a8483f86d05a123 "/rails/bin/docker-e…" 13 minutes ago Up 13 minutes 3000/tcp chat-6ef8a6a84c525b123c5245345a8483f86d05a123 ``` -You can also see just info for app containers with `mrsk app details` or just for Traefik with `mrsk traefik details`. +You can also see just info for app containers with `kamal app details` or just for Traefik with `kamal traefik details`. ### Running rollback to fix a bad deploy -If you've discovered a bad deploy, you can quickly rollback by reactivating the old, paused container image. You can see what old containers are available for rollback by running `mrsk app containers`. It'll give you a presentation similar to `mrsk app details`, but include all the old containers as well. Showing something like this: +If you've discovered a bad deploy, you can quickly rollback by reactivating the old, paused container image. You can see what old containers are available for rollback by running `kamal app containers`. It'll give you a presentation similar to `kamal app details`, but include all the old containers as well. Showing something like this: ``` App Host: 192.168.0.1 @@ -894,22 +894,22 @@ badb1aa51db4 registry.digitalocean.com/user/app:6ef8a6a84c525b123c5245345a8483 6f170d1172ae registry.digitalocean.com/user/app:e5d9d7c2b898289dfbc5f7f1334140d984eedae4 "/rails/bin/docker-e…" 31 minutes ago Exited (1) 27 minutes ago chat-e5d9d7c2b898289dfbc5f7f1334140d984eedae4 ``` -From the example above, we can see that `e5d9d7c2b898289dfbc5f7f1334140d984eedae4` was the last version, so it's available as a rollback target. We can perform this rollback by running `mrsk rollback e5d9d7c2b898289dfbc5f7f1334140d984eedae4`. That'll stop `6ef8a6a84c525b123c5245345a8483f86d05a123` and then start `e5d9d7c2b898289dfbc5f7f1334140d984eedae4`. Because the old container is still available, this is very quick. Nothing to download from the registry. +From the example above, we can see that `e5d9d7c2b898289dfbc5f7f1334140d984eedae4` was the last version, so it's available as a rollback target. We can perform this rollback by running `kamal rollback e5d9d7c2b898289dfbc5f7f1334140d984eedae4`. That'll stop `6ef8a6a84c525b123c5245345a8483f86d05a123` and then start `e5d9d7c2b898289dfbc5f7f1334140d984eedae4`. Because the old container is still available, this is very quick. Nothing to download from the registry. -Note that by default old containers are pruned after 3 days when you run `mrsk deploy`. +Note that by default old containers are pruned after 3 days when you run `kamal deploy`. ### Running removal to clean up servers -If you wish to remove the entire application, including Traefik, containers, images, and registry session, you can run `mrsk remove`. This will leave the servers clean. +If you wish to remove the entire application, including Traefik, containers, images, and registry session, you can run `kamal remove`. This will leave the servers clean. ## Locking -Commands that are unsafe to run concurrently will take a deploy lock while they run. The lock is the `mrsk_lock-` directory on the primary server. +Commands that are unsafe to run concurrently will take a deploy lock while they run. The lock is the `kamal_lock-` directory on the primary server. You can check the lock status with: ``` -mrsk lock status +kamal lock status Locked by: AN Other at 2023-03-24 09:49:03 UTC Version: 77f45c0686811c68989d6576748475a60bf53fc2 @@ -919,18 +919,18 @@ Message: Automatic deploy lock You can also manually acquire and release the lock ``` -mrsk lock acquire -m "Doing maintenance" +kamal lock acquire -m "Doing maintenance" ``` ``` -mrsk lock release +kamal lock release ``` ## Rolling deployments When deploying to large numbers of hosts, you might prefer not to restart your services on every host at the same time. -MRSK's default is to boot new containers on all hosts in parallel. But you can control this by configuring `boot/limit` and `boot/wait` as options: +Kamal's default is to boot new containers on all hosts in parallel. But you can control this by configuring `boot/limit` and `boot/wait` as options: ```yaml service: myservice @@ -940,32 +940,32 @@ boot: wait: 2 ``` -When `limit` is specified, containers will be booted on, at most, `limit` hosts at once. MRSK will pause for `wait` seconds between batches. +When `limit` is specified, containers will be booted on, at most, `limit` hosts at once. Kamal will pause for `wait` seconds between batches. -These settings only apply when booting containers (using `mrsk deploy`, or `mrsk app boot`). For other commands, MRSK continues to run commands in parallel across all hosts. +These settings only apply when booting containers (using `kamal deploy`, or `kamal app boot`). For other commands, Kamal continues to run commands in parallel across all hosts. ## Hooks You can run custom scripts at specific points with hooks. -Hooks should be stored in the .mrsk/hooks folder. Running mrsk init will build that folder and add some sample scripts. +Hooks should be stored in the .kamal/hooks folder. Running kamal init will build that folder and add some sample scripts. You can change their location by setting `hooks_path` in the configuration file. If the script returns a non-zero exit code the command will be aborted. -`MRSK_*` environment variables are available to the hooks command for +`KAMAL_*` environment variables are available to the hooks command for fine-grained audit reporting, e.g. for triggering deployment reports or firing a JSON webhook. These variables include: -- `MRSK_RECORDED_AT` - UTC timestamp in ISO 8601 format, e.g. `2023-04-14T17:07:31Z` -- `MRSK_PERFORMER` - the local user performing the command (from `whoami`) -- `MRSK_SERVICE_VERSION` - an abbreviated service and version for use in messages, e.g. app@150b24f -- `MRSK_VERSION` - the full version being deployed -- `MRSK_HOSTS` - a comma-separated list of the hosts targeted by the command -- `MRSK_COMMAND` - The command we are running -- `MRSK_SUBCOMMAND` - optional: The subcommand we are running -- `MRSK_DESTINATION` - optional: destination, e.g. "staging" -- `MRSK_ROLE` - optional: role targeted, e.g. "web" +- `KAMAL_RECORDED_AT` - UTC timestamp in ISO 8601 format, e.g. `2023-04-14T17:07:31Z` +- `KAMAL_PERFORMER` - the local user performing the command (from `whoami`) +- `KAMAL_SERVICE_VERSION` - an abbreviated service and version for use in messages, e.g. app@150b24f +- `KAMAL_VERSION` - the full version being deployed +- `KAMAL_HOSTS` - a comma-separated list of the hosts targeted by the command +- `KAMAL_COMMAND` - The command we are running +- `KAMAL_SUBCOMMAND` - optional: The subcommand we are running +- `KAMAL_DESTINATION` - optional: destination, e.g. "staging" +- `KAMAL_ROLE` - optional: role targeted, e.g. "web" There are four hooks: @@ -979,7 +979,7 @@ Used for pre-build checks - e.g. there are no uncommitted changes or that CI has For final checks before deploying, e.g. checking CI completed 3. post-deploy - run after a deploy, redeploy or rollback. -This hook is also passed a `MRSK_RUNTIME` env variable set to the total seconds the deploy took. +This hook is also passed a `KAMAL_RUNTIME` env variable set to the total seconds the deploy took. This could be used to broadcast a deployment message, or register the new version with an APM. @@ -987,7 +987,7 @@ The command could look something like: ```bash #!/usr/bin/env bash -curl -q -d content="[My App] ${MRSK_PERFORMER} Rolled back to version ${MRSK_VERSION}" https://3.basecamp.com/XXXXX/integrations/XXXXX/buckets/XXXXX/chats/XXXXX/lines +curl -q -d content="[My App] ${KAMAL_PERFORMER} Rolled back to version ${KAMAL_VERSION}" https://3.basecamp.com/XXXXX/integrations/XXXXX/buckets/XXXXX/chats/XXXXX/lines ``` That'll post a line like the following to a preconfigured chatbot in Basecamp: @@ -1000,7 +1000,7 @@ Set `--skip_hooks` to avoid running the hooks. ## SSH connection management -Creating SSH connections concurrently can be an issue when deploying to many servers. By default MRSK will limit concurrent connection starts to 30 at a time. +Creating SSH connections concurrently can be an issue when deploying to many servers. By default Kamal will limit concurrent connection starts to 30 at a time. It also sets a long idle timeout of 900 seconds on connections to prevent re-connection storms after a long idle period, like building an image or waiting for CI. @@ -1018,4 +1018,4 @@ This is beta software. Commands may still move around. But we're live in product ## License -MRSK is released under the [MIT License](https://opensource.org/licenses/MIT). +Kamal is released under the [MIT License](https://opensource.org/licenses/MIT). diff --git a/bin/mrsk b/bin/kamal similarity index 89% rename from bin/mrsk rename to bin/kamal index f2eadfae0..96c0dc640 100755 --- a/bin/mrsk +++ b/bin/kamal @@ -3,10 +3,10 @@ # Prevent failures from being reported twice. Thread.report_on_exception = false -require "mrsk" +require "kamal" begin - Mrsk::Cli::Main.start(ARGV) + Kamal::Cli::Main.start(ARGV) rescue SSHKit::Runner::ExecuteError => e puts " \e[31mERROR (#{e.cause.class}): #{e.message}\e[0m" puts e.cause.backtrace if ENV["VERBOSE"] diff --git a/bin/release b/bin/release index 605ce6c16..7cb488645 100755 --- a/bin/release +++ b/bin/release @@ -2,13 +2,13 @@ VERSION=$1 -printf "module Mrsk\n VERSION = \"$VERSION\"\nend\n" > ./lib/mrsk/version.rb +printf "module Kamal\n VERSION = \"$VERSION\"\nend\n" > ./lib/kamal/version.rb bundle -git add Gemfile.lock lib/mrsk/version.rb +git add Gemfile.lock lib/kamal/version.rb git commit -m "Bump version for $VERSION" git push git tag v$VERSION git push --tags -gem build mrsk.gemspec -gem push "mrsk-$VERSION.gem" --host https://rubygems.org -rm "mrsk-$VERSION.gem" +gem build kamal.gemspec +gem push "kamal-$VERSION.gem" --host https://rubygems.org +rm "kamal-$VERSION.gem" diff --git a/mrsk.gemspec b/kamal.gemspec similarity index 81% rename from mrsk.gemspec rename to kamal.gemspec index 7a10c2beb..9c357e9ca 100644 --- a/mrsk.gemspec +++ b/kamal.gemspec @@ -1,16 +1,16 @@ -require_relative "lib/mrsk/version" +require_relative "lib/kamal/version" Gem::Specification.new do |spec| - spec.name = "mrsk" - spec.version = Mrsk::VERSION + spec.name = "kamal" + spec.version = Kamal::VERSION spec.authors = [ "David Heinemeier Hansson" ] spec.email = "dhh@hey.com" - spec.homepage = "https://github.com/rails/mrsk" + spec.homepage = "https://github.com/rails/kamal" spec.summary = "Deploy web apps in containers to servers running Docker with zero downtime." spec.license = "MIT" spec.files = Dir["lib/**/*", "MIT-LICENSE", "README.md"] - spec.executables = %w[ mrsk ] + spec.executables = %w[ kamal ] spec.add_dependency "activesupport", ">= 7.0" spec.add_dependency "sshkit", "~> 1.21" diff --git a/lib/mrsk.rb b/lib/kamal.rb similarity index 68% rename from lib/mrsk.rb rename to lib/kamal.rb index 70cbad40a..f5f538052 100644 --- a/lib/mrsk.rb +++ b/lib/kamal.rb @@ -1,10 +1,10 @@ -module Mrsk +module Kamal end require "active_support" require "zeitwerk" loader = Zeitwerk::Loader.for_gem -loader.ignore("#{__dir__}/mrsk/sshkit_with_ext.rb") +loader.ignore("#{__dir__}/kamal/sshkit_with_ext.rb") loader.setup loader.eager_load # We need all commands loaded. diff --git a/lib/mrsk/cli.rb b/lib/kamal/cli.rb similarity index 76% rename from lib/mrsk/cli.rb rename to lib/kamal/cli.rb index bc541d06c..c9a2a886b 100644 --- a/lib/mrsk/cli.rb +++ b/lib/kamal/cli.rb @@ -1,7 +1,7 @@ -module Mrsk::Cli +module Kamal::Cli class LockError < StandardError; end class HookError < StandardError; end end # SSHKit uses instance eval, so we need a global const for ergonomics -MRSK = Mrsk::Commander.new +Kamal = Kamal::Commander.new diff --git a/lib/mrsk/cli/accessory.rb b/lib/kamal/cli/accessory.rb similarity index 86% rename from lib/mrsk/cli/accessory.rb rename to lib/kamal/cli/accessory.rb index f597a2a63..8006da1cb 100644 --- a/lib/mrsk/cli/accessory.rb +++ b/lib/kamal/cli/accessory.rb @@ -1,17 +1,17 @@ -class Mrsk::Cli::Accessory < Mrsk::Cli::Base +class Kamal::Cli::Accessory < Kamal::Cli::Base desc "boot [NAME]", "Boot new accessory service on host (use NAME=all to boot all accessories)" def boot(name, login: true) mutating do if name == "all" - MRSK.accessory_names.each { |accessory_name| boot(accessory_name) } + KAMAL.accessory_names.each { |accessory_name| boot(accessory_name) } else with_accessory(name) do |accessory| directories(name) upload(name) on(accessory.hosts) do - execute *MRSK.registry.login if login - execute *MRSK.auditor.record("Booted #{name} accessory"), verbosity: :debug + execute *KAMAL.registry.login if login + execute *KAMAL.auditor.record("Booted #{name} accessory"), verbosity: :debug execute *accessory.run end end @@ -54,7 +54,7 @@ def reboot(name) mutating do with_accessory(name) do |accessory| on(accessory.hosts) do - execute *MRSK.registry.login + execute *KAMAL.registry.login end stop(name) @@ -69,7 +69,7 @@ def start(name) mutating do with_accessory(name) do |accessory| on(accessory.hosts) do - execute *MRSK.auditor.record("Started #{name} accessory"), verbosity: :debug + execute *KAMAL.auditor.record("Started #{name} accessory"), verbosity: :debug execute *accessory.start end end @@ -81,7 +81,7 @@ def stop(name) mutating do with_accessory(name) do |accessory| on(accessory.hosts) do - execute *MRSK.auditor.record("Stopped #{name} accessory"), verbosity: :debug + execute *KAMAL.auditor.record("Stopped #{name} accessory"), verbosity: :debug execute *accessory.stop, raise_on_non_zero_exit: false end end @@ -101,7 +101,7 @@ def restart(name) desc "details [NAME]", "Show details about accessory on host (use NAME=all to show all accessories)" def details(name) if name == "all" - MRSK.accessory_names.each { |accessory_name| details(accessory_name) } + KAMAL.accessory_names.each { |accessory_name| details(accessory_name) } else with_accessory(name) do |accessory| on(accessory.hosts) { puts capture_with_info(*accessory.info) } @@ -126,14 +126,14 @@ def exec(name, cmd) when options[:reuse] say "Launching command from existing container...", :magenta on(accessory.hosts) do - execute *MRSK.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug + execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug capture_with_info(*accessory.execute_in_existing_container(cmd)) end else say "Launching command from new container...", :magenta on(accessory.hosts) do - execute *MRSK.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug + execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on #{name} accessory"), verbosity: :debug capture_with_info(*accessory.execute_in_new_container(cmd)) end end @@ -171,7 +171,7 @@ def logs(name) def remove(name) mutating do if name == "all" - MRSK.accessory_names.each { |accessory_name| remove(accessory_name) } + KAMAL.accessory_names.each { |accessory_name| remove(accessory_name) } else if options[:confirmed] || ask("This will remove all containers, images and data directories for #{name}. Are you sure?", limited_to: %w( y N ), default: "N") == "y" with_accessory(name) do @@ -190,7 +190,7 @@ def remove_container(name) mutating do with_accessory(name) do |accessory| on(accessory.hosts) do - execute *MRSK.auditor.record("Remove #{name} accessory container"), verbosity: :debug + execute *KAMAL.auditor.record("Remove #{name} accessory container"), verbosity: :debug execute *accessory.remove_container end end @@ -202,7 +202,7 @@ def remove_image(name) mutating do with_accessory(name) do |accessory| on(accessory.hosts) do - execute *MRSK.auditor.record("Removed #{name} accessory image"), verbosity: :debug + execute *KAMAL.auditor.record("Removed #{name} accessory image"), verbosity: :debug execute *accessory.remove_image end end @@ -222,7 +222,7 @@ def remove_service_directory(name) private def with_accessory(name) - if accessory = MRSK.accessory(name) + if accessory = KAMAL.accessory(name) yield accessory else error_on_missing_accessory(name) @@ -230,7 +230,7 @@ def with_accessory(name) end def error_on_missing_accessory(name) - options = MRSK.accessory_names.presence + options = KAMAL.accessory_names.presence error \ "No accessory by the name of '#{name}'" + diff --git a/lib/mrsk/cli/app.rb b/lib/kamal/cli/app.rb similarity index 59% rename from lib/mrsk/cli/app.rb rename to lib/kamal/cli/app.rb index 629fdbcbb..532871faa 100644 --- a/lib/mrsk/cli/app.rb +++ b/lib/kamal/cli/app.rb @@ -1,23 +1,23 @@ -class Mrsk::Cli::App < Mrsk::Cli::Base +class Kamal::Cli::App < Kamal::Cli::Base desc "boot", "Boot app on servers (or reboot app if already running)" def boot mutating do hold_lock_on_error do say "Get most recent version available as an image...", :magenta unless options[:version] using_version(version_or_latest) do |version| - say "Start container with version #{version} using a #{MRSK.config.readiness_delay}s readiness delay (or reboot if already running)...", :magenta + say "Start container with version #{version} using a #{KAMAL.config.readiness_delay}s readiness delay (or reboot if already running)...", :magenta - on(MRSK.hosts) do - execute *MRSK.auditor.record("Tagging #{MRSK.config.absolute_image} as the latest image"), verbosity: :debug - execute *MRSK.app.tag_current_as_latest + on(KAMAL.hosts) do + execute *KAMAL.auditor.record("Tagging #{KAMAL.config.absolute_image} as the latest image"), verbosity: :debug + execute *KAMAL.app.tag_current_as_latest end - on(MRSK.hosts, **MRSK.boot_strategy) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts, **KAMAL.boot_strategy) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| - app = MRSK.app(role: role) - auditor = MRSK.auditor(role: role) + app = KAMAL.app(role: role) + auditor = KAMAL.auditor(role: role) if capture_with_info(*app.container_id_for_version(version, only_running: true), raise_on_non_zero_exit: false).present? tmp_version = "#{version}_replaced_#{SecureRandom.hex(8)}" @@ -31,7 +31,7 @@ def boot old_version = capture_with_info(*app.current_running_version, raise_on_non_zero_exit: false).strip execute *app.start_or_run(hostname: "#{host}-#{SecureRandom.hex(6)}") - Mrsk::Utils::HealthcheckPoller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) } + Kamal::Utils::HealthcheckPoller.wait_for_healthy(pause_after_ready: true) { capture_with_info(*app.status(version: version)) } execute *app.stop(version: old_version), raise_on_non_zero_exit: false if old_version.present? end @@ -44,12 +44,12 @@ def boot desc "start", "Start existing app container on servers" def start mutating do - on(MRSK.hosts) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| - execute *MRSK.auditor.record("Started app version #{MRSK.config.version}"), verbosity: :debug - execute *MRSK.app(role: role).start, raise_on_non_zero_exit: false + execute *KAMAL.auditor.record("Started app version #{KAMAL.config.version}"), verbosity: :debug + execute *KAMAL.app(role: role).start, raise_on_non_zero_exit: false end end end @@ -58,12 +58,12 @@ def start desc "stop", "Stop app container on servers" def stop mutating do - on(MRSK.hosts) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| - execute *MRSK.auditor.record("Stopped app", role: role), verbosity: :debug - execute *MRSK.app(role: role).stop, raise_on_non_zero_exit: false + execute *KAMAL.auditor.record("Stopped app", role: role), verbosity: :debug + execute *KAMAL.app(role: role).stop, raise_on_non_zero_exit: false end end end @@ -72,11 +72,11 @@ def stop # FIXME: Drop in favor of just containers? desc "details", "Show details about app containers" def details - on(MRSK.hosts) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| - puts_by_host host, capture_with_info(*MRSK.app(role: role).info) + puts_by_host host, capture_with_info(*KAMAL.app(role: role).info) end end end @@ -89,15 +89,15 @@ def exec(cmd) when options[:interactive] && options[:reuse] say "Get current version of running container...", :magenta unless options[:version] using_version(options[:version] || current_running_version) do |version| - say "Launching interactive command with version #{version} via SSH from existing container on #{MRSK.primary_host}...", :magenta - run_locally { exec MRSK.app(role: "web").execute_in_existing_container_over_ssh(cmd, host: MRSK.primary_host) } + say "Launching interactive command with version #{version} via SSH from existing container on #{KAMAL.primary_host}...", :magenta + run_locally { exec KAMAL.app(role: "web").execute_in_existing_container_over_ssh(cmd, host: KAMAL.primary_host) } end when options[:interactive] say "Get most recent version available as an image...", :magenta unless options[:version] using_version(version_or_latest) do |version| - say "Launching interactive command with version #{version} via SSH from new container on #{MRSK.primary_host}...", :magenta - run_locally { exec MRSK.app(role: MRSK.primary_host.roles.first).execute_in_new_container_over_ssh(cmd, host: MRSK.primary_host) } + say "Launching interactive command with version #{version} via SSH from new container on #{KAMAL.primary_host}...", :magenta + run_locally { exec KAMAL.app(role: KAMAL.primary_host.roles.first).execute_in_new_container_over_ssh(cmd, host: KAMAL.primary_host) } end when options[:reuse] @@ -105,12 +105,12 @@ def exec(cmd) using_version(options[:version] || current_running_version) do |version| say "Launching command with version #{version} from existing container...", :magenta - on(MRSK.hosts) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| - execute *MRSK.auditor.record("Executed cmd '#{cmd}' on app version #{version}", role: role), verbosity: :debug - puts_by_host host, capture_with_info(*MRSK.app(role: role).execute_in_existing_container(cmd)) + execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on app version #{version}", role: role), verbosity: :debug + puts_by_host host, capture_with_info(*KAMAL.app(role: role).execute_in_existing_container(cmd)) end end end @@ -119,9 +119,9 @@ def exec(cmd) say "Get most recent version available as an image...", :magenta unless options[:version] using_version(version_or_latest) do |version| say "Launching command with version #{version} from new container...", :magenta - on(MRSK.hosts) do |host| - execute *MRSK.auditor.record("Executed cmd '#{cmd}' on app version #{version}"), verbosity: :debug - puts_by_host host, capture_with_info(*MRSK.app.execute_in_new_container(cmd)) + on(KAMAL.hosts) do |host| + execute *KAMAL.auditor.record("Executed cmd '#{cmd}' on app version #{version}"), verbosity: :debug + puts_by_host host, capture_with_info(*KAMAL.app.execute_in_new_container(cmd)) end end end @@ -129,7 +129,7 @@ def exec(cmd) desc "containers", "Show app containers on servers" def containers - on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.list_containers) } + on(KAMAL.hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.app.list_containers) } end desc "stale_containers", "Detect app stale containers" @@ -140,16 +140,16 @@ def stale_containers cli = self - on(MRSK.hosts) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| cli.send(:stale_versions, host: host, role: role).each do |version| if stop puts_by_host host, "Stopping stale container for role #{role} with version #{version}" - execute *MRSK.app(role: role).stop(version: version), raise_on_non_zero_exit: false + execute *KAMAL.app(role: role).stop(version: version), raise_on_non_zero_exit: false else - puts_by_host host, "Detected stale container for role #{role} with version #{version} (use `mrsk app stale_containers --stop` to stop)" + puts_by_host host, "Detected stale container for role #{role} with version #{version} (use `kamal app stale_containers --stop` to stop)" end end end @@ -159,7 +159,7 @@ def stale_containers desc "images", "Show app images on servers" def images - on(MRSK.hosts) { |host| puts_by_host host, capture_with_info(*MRSK.app.list_images) } + on(KAMAL.hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.app.list_images) } end desc "logs", "Show log lines from app on servers (use --help to show options)" @@ -174,24 +174,24 @@ def logs if options[:follow] run_locally do - info "Following logs on #{MRSK.primary_host}..." + info "Following logs on #{KAMAL.primary_host}..." - MRSK.specific_roles ||= ["web"] - role = MRSK.roles_on(MRSK.primary_host).first + KAMAL.specific_roles ||= ["web"] + role = KAMAL.roles_on(KAMAL.primary_host).first - info MRSK.app(role: role).follow_logs(host: MRSK.primary_host, grep: grep) - exec MRSK.app(role: role).follow_logs(host: MRSK.primary_host, grep: grep) + info KAMAL.app(role: role).follow_logs(host: KAMAL.primary_host, grep: grep) + exec KAMAL.app(role: role).follow_logs(host: KAMAL.primary_host, grep: grep) end else since = options[:since] lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set - on(MRSK.hosts) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| begin - puts_by_host host, capture_with_info(*MRSK.app(role: role).logs(since: since, lines: lines, grep: grep)) + puts_by_host host, capture_with_info(*KAMAL.app(role: role).logs(since: since, lines: lines, grep: grep)) rescue SSHKit::Command::Failed puts_by_host host, "Nothing found" end @@ -212,12 +212,12 @@ def remove desc "remove_container [VERSION]", "Remove app container with given version from servers", hide: true def remove_container(version) mutating do - on(MRSK.hosts) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| - execute *MRSK.auditor.record("Removed app container with version #{version}", role: role), verbosity: :debug - execute *MRSK.app(role: role).remove_container(version: version) + execute *KAMAL.auditor.record("Removed app container with version #{version}", role: role), verbosity: :debug + execute *KAMAL.app(role: role).remove_container(version: version) end end end @@ -226,12 +226,12 @@ def remove_container(version) desc "remove_containers", "Remove all app containers from servers", hide: true def remove_containers mutating do - on(MRSK.hosts) do |host| - roles = MRSK.roles_on(host) + on(KAMAL.hosts) do |host| + roles = KAMAL.roles_on(host) roles.each do |role| - execute *MRSK.auditor.record("Removed all app containers", role: role), verbosity: :debug - execute *MRSK.app(role: role).remove_containers + execute *KAMAL.auditor.record("Removed all app containers", role: role), verbosity: :debug + execute *KAMAL.app(role: role).remove_containers end end end @@ -240,18 +240,18 @@ def remove_containers desc "remove_images", "Remove all app images from servers", hide: true def remove_images mutating do - on(MRSK.hosts) do - execute *MRSK.auditor.record("Removed all app images"), verbosity: :debug - execute *MRSK.app.remove_images + on(KAMAL.hosts) do + execute *KAMAL.auditor.record("Removed all app images"), verbosity: :debug + execute *KAMAL.app.remove_images end end end desc "version", "Show app version currently running on servers" def version - on(MRSK.hosts) do |host| - role = MRSK.roles_on(host).first - puts_by_host host, capture_with_info(*MRSK.app(role: role).current_running_version).strip + on(KAMAL.hosts) do |host| + role = KAMAL.roles_on(host).first + puts_by_host host, capture_with_info(*KAMAL.app(role: role).current_running_version).strip end end @@ -259,22 +259,22 @@ def version def using_version(new_version) if new_version begin - old_version = MRSK.config.version - MRSK.config.version = new_version + old_version = KAMAL.config.version + KAMAL.config.version = new_version yield new_version ensure - MRSK.config.version = old_version + KAMAL.config.version = old_version end else - yield MRSK.config.version + yield KAMAL.config.version end end - def current_running_version(host: MRSK.primary_host) + def current_running_version(host: KAMAL.primary_host) version = nil on(host) do - role = MRSK.roles_on(host).first - version = capture_with_info(*MRSK.app(role: role).current_running_version).strip + role = KAMAL.roles_on(host).first + version = capture_with_info(*KAMAL.app(role: role).current_running_version).strip end version.presence end @@ -283,7 +283,7 @@ def stale_versions(host:, role:) versions = nil on(host) do versions = \ - capture_with_info(*MRSK.app(role: role).list_versions, raise_on_non_zero_exit: false) + capture_with_info(*KAMAL.app(role: role).list_versions, raise_on_non_zero_exit: false) .split("\n") .drop(1) end diff --git a/lib/mrsk/cli/base.rb b/lib/kamal/cli/base.rb similarity index 75% rename from lib/mrsk/cli/base.rb rename to lib/kamal/cli/base.rb index 44df756ea..9f38241a1 100644 --- a/lib/mrsk/cli/base.rb +++ b/lib/kamal/cli/base.rb @@ -1,8 +1,8 @@ require "thor" require "dotenv" -require "mrsk/sshkit_with_ext" +require "kamal/sshkit_with_ext" -module Mrsk::Cli +module Kamal::Cli class Base < Thor include SSHKit::DSL @@ -42,7 +42,7 @@ def options_with_subcommand_class_options end def initialize_commander(options) - MRSK.tap do |commander| + KAMAL.tap do |commander| if options[:verbose] ENV["VERBOSE"] = "1" # For backtraces via cli/start commander.verbosity = :debug @@ -73,9 +73,9 @@ def print_runtime end def mutating - return yield if MRSK.holding_lock? + return yield if KAMAL.holding_lock? - MRSK.config.ensure_env_available + KAMAL.config.ensure_env_available run_hook "pre-connect" @@ -84,7 +84,7 @@ def mutating begin yield rescue - if MRSK.hold_lock_on_error? + if KAMAL.hold_lock_on_error? error " \e[31mDeploy lock was not released\e[0m" else release_lock @@ -99,24 +99,24 @@ def mutating def acquire_lock raise_if_locked do say "Acquiring the deploy lock...", :magenta - on(MRSK.primary_host) { execute *MRSK.lock.acquire("Automatic deploy lock", MRSK.config.version), verbosity: :debug } + on(KAMAL.primary_host) { execute *KAMAL.lock.acquire("Automatic deploy lock", KAMAL.config.version), verbosity: :debug } end - MRSK.holding_lock = true + KAMAL.holding_lock = true end def release_lock say "Releasing the deploy lock...", :magenta - on(MRSK.primary_host) { execute *MRSK.lock.release, verbosity: :debug } + on(KAMAL.primary_host) { execute *KAMAL.lock.release, verbosity: :debug } - MRSK.holding_lock = false + KAMAL.holding_lock = false end def raise_if_locked yield rescue SSHKit::Runner::ExecuteError => e if e.message =~ /cannot create directory/ - on(MRSK.primary_host) { puts capture_with_debug(*MRSK.lock.status) } + on(KAMAL.primary_host) { puts capture_with_debug(*KAMAL.lock.status) } raise LockError, "Deploy lock found" else raise e @@ -124,22 +124,22 @@ def raise_if_locked end def hold_lock_on_error - if MRSK.hold_lock_on_error? + if KAMAL.hold_lock_on_error? yield else - MRSK.hold_lock_on_error = true + KAMAL.hold_lock_on_error = true yield - MRSK.hold_lock_on_error = false + KAMAL.hold_lock_on_error = false end end def run_hook(hook, **extra_details) - if !options[:skip_hooks] && MRSK.hook.hook_exists?(hook) - details = { hosts: MRSK.hosts.join(","), command: command, subcommand: subcommand } + if !options[:skip_hooks] && KAMAL.hook.hook_exists?(hook) + details = { hosts: KAMAL.hosts.join(","), command: command, subcommand: subcommand } say "Running the #{hook} hook...", :magenta run_locally do - MRSK.with_verbosity(:debug) { execute *MRSK.hook.run(hook, **details, **extra_details) } + KAMAL.with_verbosity(:debug) { execute *KAMAL.hook.run(hook, **details, **extra_details) } rescue SSHKit::Command::Failed raise HookError.new("Hook `#{hook}` failed") end @@ -147,20 +147,20 @@ def run_hook(hook, **extra_details) end def command - @mrsk_command ||= begin + @kamal_command ||= begin invocation_class, invocation_commands = *first_invocation - if invocation_class == Mrsk::Cli::Main + if invocation_class == Kamal::Cli::Main invocation_commands[0] else - Mrsk::Cli::Main.subcommand_classes.find { |command, clazz| clazz == invocation_class }[0] + Kamal::Cli::Main.subcommand_classes.find { |command, clazz| clazz == invocation_class }[0] end end end def subcommand - @mrsk_subcommand ||= begin + @kamal_subcommand ||= begin invocation_class, invocation_commands = *first_invocation - invocation_commands[0] if invocation_class != Mrsk::Cli::Main + invocation_commands[0] if invocation_class != Kamal::Cli::Main end end diff --git a/lib/mrsk/cli/build.rb b/lib/kamal/cli/build.rb similarity index 68% rename from lib/mrsk/cli/build.rb rename to lib/kamal/cli/build.rb index e9aeec66e..9a23117db 100644 --- a/lib/mrsk/cli/build.rb +++ b/lib/kamal/cli/build.rb @@ -1,4 +1,4 @@ -class Mrsk::Cli::Build < Mrsk::Cli::Base +class Kamal::Cli::Build < Kamal::Cli::Base class BuildError < StandardError; end desc "deliver", "Build app and push app image to registry then pull image on servers" @@ -17,21 +17,21 @@ def push verify_local_dependencies run_hook "pre-build" - if (uncommitted_changes = Mrsk::Utils.uncommitted_changes).present? + if (uncommitted_changes = Kamal::Utils.uncommitted_changes).present? say "The following paths have uncommitted changes:\n #{uncommitted_changes}", :yellow end run_locally do begin - MRSK.with_verbosity(:debug) do - execute *MRSK.builder.push + KAMAL.with_verbosity(:debug) do + execute *KAMAL.builder.push end rescue SSHKit::Command::Failed => e if e.message =~ /(no builder)|(no such file or directory)/ error "Missing compatible builder, so creating a new one first" if cli.create - MRSK.with_verbosity(:debug) { execute *MRSK.builder.push } + KAMAL.with_verbosity(:debug) { execute *KAMAL.builder.push } end else raise @@ -44,10 +44,10 @@ def push desc "pull", "Pull app image from registry onto servers" def pull mutating do - on(MRSK.hosts) do - execute *MRSK.auditor.record("Pulled image with version #{MRSK.config.version}"), verbosity: :debug - execute *MRSK.builder.clean, raise_on_non_zero_exit: false - execute *MRSK.builder.pull + on(KAMAL.hosts) do + execute *KAMAL.auditor.record("Pulled image with version #{KAMAL.config.version}"), verbosity: :debug + execute *KAMAL.builder.clean, raise_on_non_zero_exit: false + execute *KAMAL.builder.pull end end end @@ -57,8 +57,8 @@ def create mutating do run_locally do begin - debug "Using builder: #{MRSK.builder.name}" - execute *MRSK.builder.create + debug "Using builder: #{KAMAL.builder.name}" + execute *KAMAL.builder.create rescue SSHKit::Command::Failed => e if e.message =~ /stderr=(.*)/ error "Couldn't create remote builder: #{$1}" @@ -75,8 +75,8 @@ def create def remove mutating do run_locally do - debug "Using builder: #{MRSK.builder.name}" - execute *MRSK.builder.remove + debug "Using builder: #{KAMAL.builder.name}" + execute *KAMAL.builder.remove end end end @@ -84,8 +84,8 @@ def remove desc "details", "Show build setup" def details run_locally do - puts "Builder: #{MRSK.builder.name}" - puts capture(*MRSK.builder.info) + puts "Builder: #{KAMAL.builder.name}" + puts capture(*KAMAL.builder.info) end end @@ -93,7 +93,7 @@ def details def verify_local_dependencies run_locally do begin - execute *MRSK.builder.ensure_local_dependencies_installed + execute *KAMAL.builder.ensure_local_dependencies_installed rescue SSHKit::Command::Failed => e build_error = e.message =~ /command not found/ ? "Docker is not installed locally" : diff --git a/lib/kamal/cli/healthcheck.rb b/lib/kamal/cli/healthcheck.rb new file mode 100644 index 000000000..24ae5a638 --- /dev/null +++ b/lib/kamal/cli/healthcheck.rb @@ -0,0 +1,20 @@ +class Kamal::Cli::Healthcheck < Kamal::Cli::Base + default_command :perform + + desc "perform", "Health check current app version" + def perform + on(KAMAL.primary_host) do + begin + execute *KAMAL.healthcheck.run + Kamal::Utils::HealthcheckPoller.wait_for_healthy { capture_with_info(*KAMAL.healthcheck.status) } + rescue Kamal::Utils::HealthcheckPoller::HealthcheckError => e + error capture_with_info(*KAMAL.healthcheck.logs) + error capture_with_pretty_json(*KAMAL.healthcheck.container_health_log) + raise + ensure + execute *KAMAL.healthcheck.stop, raise_on_non_zero_exit: false + execute *KAMAL.healthcheck.remove, raise_on_non_zero_exit: false + end + end + end +end diff --git a/lib/mrsk/cli/lock.rb b/lib/kamal/cli/lock.rb similarity index 69% rename from lib/mrsk/cli/lock.rb rename to lib/kamal/cli/lock.rb index 7e90a9175..c30e6f0fe 100644 --- a/lib/mrsk/cli/lock.rb +++ b/lib/kamal/cli/lock.rb @@ -1,8 +1,8 @@ -class Mrsk::Cli::Lock < Mrsk::Cli::Base +class Kamal::Cli::Lock < Kamal::Cli::Base desc "status", "Report lock status" def status handle_missing_lock do - on(MRSK.primary_host) { puts capture_with_debug(*MRSK.lock.status) } + on(KAMAL.primary_host) { puts capture_with_debug(*KAMAL.lock.status) } end end @@ -11,7 +11,7 @@ def status def acquire message = options[:message] raise_if_locked do - on(MRSK.primary_host) { execute *MRSK.lock.acquire(message, MRSK.config.version), verbosity: :debug } + on(KAMAL.primary_host) { execute *KAMAL.lock.acquire(message, KAMAL.config.version), verbosity: :debug } say "Acquired the deploy lock" end end @@ -19,7 +19,7 @@ def acquire desc "release", "Release the deploy lock" def release handle_missing_lock do - on(MRSK.primary_host) { execute *MRSK.lock.release, verbosity: :debug } + on(KAMAL.primary_host) { execute *KAMAL.lock.release, verbosity: :debug } say "Released the deploy lock" end end diff --git a/lib/mrsk/cli/main.rb b/lib/kamal/cli/main.rb similarity index 63% rename from lib/mrsk/cli/main.rb rename to lib/kamal/cli/main.rb index bf0d89171..29218d9d3 100644 --- a/lib/mrsk/cli/main.rb +++ b/lib/kamal/cli/main.rb @@ -1,10 +1,10 @@ -class Mrsk::Cli::Main < Mrsk::Cli::Base +class Kamal::Cli::Main < Kamal::Cli::Base desc "setup", "Setup all accessories and deploy app to servers" def setup print_runtime do mutating do - invoke "mrsk:cli:server:bootstrap" - invoke "mrsk:cli:accessory:boot", [ "all" ] + invoke "kamal:cli:server:bootstrap" + invoke "kamal:cli:accessory:boot", [ "all" ] deploy end end @@ -18,31 +18,31 @@ def deploy invoke_options = deploy_options say "Log into image registry...", :magenta - invoke "mrsk:cli:registry:login", [], invoke_options + invoke "kamal:cli:registry:login", [], invoke_options if options[:skip_push] say "Pull app image...", :magenta - invoke "mrsk:cli:build:pull", [], invoke_options + invoke "kamal:cli:build:pull", [], invoke_options else say "Build and push app image...", :magenta - invoke "mrsk:cli:build:deliver", [], invoke_options + invoke "kamal:cli:build:deliver", [], invoke_options end run_hook "pre-deploy" say "Ensure Traefik is running...", :magenta - invoke "mrsk:cli:traefik:boot", [], invoke_options + invoke "kamal:cli:traefik:boot", [], invoke_options say "Ensure app can pass healthcheck...", :magenta - invoke "mrsk:cli:healthcheck:perform", [], invoke_options + invoke "kamal:cli:healthcheck:perform", [], invoke_options say "Detect stale containers...", :magenta - invoke "mrsk:cli:app:stale_containers", [], invoke_options + invoke "kamal:cli:app:stale_containers", [], invoke_options - invoke "mrsk:cli:app:boot", [], invoke_options + invoke "kamal:cli:app:boot", [], invoke_options say "Prune old containers and images...", :magenta - invoke "mrsk:cli:prune:all", [], invoke_options + invoke "kamal:cli:prune:all", [], invoke_options end end @@ -58,21 +58,21 @@ def redeploy if options[:skip_push] say "Pull app image...", :magenta - invoke "mrsk:cli:build:pull", [], invoke_options + invoke "kamal:cli:build:pull", [], invoke_options else say "Build and push app image...", :magenta - invoke "mrsk:cli:build:deliver", [], invoke_options + invoke "kamal:cli:build:deliver", [], invoke_options end run_hook "pre-deploy" say "Ensure app can pass healthcheck...", :magenta - invoke "mrsk:cli:healthcheck:perform", [], invoke_options + invoke "kamal:cli:healthcheck:perform", [], invoke_options say "Detect stale containers...", :magenta - invoke "mrsk:cli:app:stale_containers", [], invoke_options + invoke "kamal:cli:app:stale_containers", [], invoke_options - invoke "mrsk:cli:app:boot", [], invoke_options + invoke "kamal:cli:app:boot", [], invoke_options end end @@ -86,16 +86,16 @@ def rollback(version) mutating do invoke_options = deploy_options - MRSK.config.version = version + KAMAL.config.version = version old_version = nil if container_available?(version) run_hook "pre-deploy" - invoke "mrsk:cli:app:boot", [], invoke_options.merge(version: version) + invoke "kamal:cli:app:boot", [], invoke_options.merge(version: version) rolled_back = true else - say "The app version '#{version}' is not available as a container (use 'mrsk app containers' for available versions)", :red + say "The app version '#{version}' is not available as a container (use 'kamal app containers' for available versions)", :red end end end @@ -105,27 +105,27 @@ def rollback(version) desc "details", "Show details about all containers" def details - invoke "mrsk:cli:traefik:details" - invoke "mrsk:cli:app:details" - invoke "mrsk:cli:accessory:details", [ "all" ] + invoke "kamal:cli:traefik:details" + invoke "kamal:cli:app:details" + invoke "kamal:cli:accessory:details", [ "all" ] end desc "audit", "Show audit log from servers" def audit - on(MRSK.hosts) do |host| - puts_by_host host, capture_with_info(*MRSK.auditor.reveal) + on(KAMAL.hosts) do |host| + puts_by_host host, capture_with_info(*KAMAL.auditor.reveal) end end desc "config", "Show combined config (including secrets!)" def config run_locally do - puts Mrsk::Utils.redacted(MRSK.config.to_h).to_yaml + puts Kamal::Utils.redacted(KAMAL.config.to_h).to_yaml end end desc "init", "Create config stub in config/deploy.yml and env stub in .env" - option :bundle, type: :boolean, default: false, desc: "Add MRSK to the Gemfile and create a bin/mrsk binstub" + option :bundle, type: :boolean, default: false, desc: "Add Kamal to the Gemfile and create a bin/kamal binstub" def init require "fileutils" @@ -142,24 +142,24 @@ def init puts "Created .env file" end - unless (hooks_dir = Pathname.new(File.expand_path(".mrsk/hooks"))).exist? + unless (hooks_dir = Pathname.new(File.expand_path(".kamal/hooks"))).exist? hooks_dir.mkpath Pathname.new(File.expand_path("templates/sample_hooks", __dir__)).each_child do |sample_hook| FileUtils.cp sample_hook, hooks_dir, preserve: true end - puts "Created sample hooks in .mrsk/hooks" + puts "Created sample hooks in .kamal/hooks" end if options[:bundle] - if (binstub = Pathname.new(File.expand_path("bin/mrsk"))).exist? - puts "Binstub already exists in bin/mrsk (remove first to create a new one)" + if (binstub = Pathname.new(File.expand_path("bin/kamal"))).exist? + puts "Binstub already exists in bin/kamal (remove first to create a new one)" else - puts "Adding MRSK to Gemfile and bundle..." + puts "Adding Kamal to Gemfile and bundle..." run_locally do - execute :bundle, :add, :mrsk - execute :bundle, :binstubs, :mrsk + execute :bundle, :add, :kamal + execute :bundle, :binstubs, :kamal end - puts "Created binstub file in bin/mrsk" + puts "Created binstub file in bin/kamal" end end end @@ -182,52 +182,52 @@ def envify def remove mutating do if options[:confirmed] || ask("This will remove all containers and images. Are you sure?", limited_to: %w( y N ), default: "N") == "y" - invoke "mrsk:cli:traefik:remove", [], options.without(:confirmed) - invoke "mrsk:cli:app:remove", [], options.without(:confirmed) - invoke "mrsk:cli:accessory:remove", [ "all" ], options - invoke "mrsk:cli:registry:logout", [], options.without(:confirmed) + invoke "kamal:cli:traefik:remove", [], options.without(:confirmed) + invoke "kamal:cli:app:remove", [], options.without(:confirmed) + invoke "kamal:cli:accessory:remove", [ "all" ], options + invoke "kamal:cli:registry:logout", [], options.without(:confirmed) end end end - desc "version", "Show MRSK version" + desc "version", "Show Kamal version" def version - puts Mrsk::VERSION + puts Kamal::VERSION end desc "accessory", "Manage accessories (db/redis/search)" - subcommand "accessory", Mrsk::Cli::Accessory + subcommand "accessory", Kamal::Cli::Accessory desc "app", "Manage application" - subcommand "app", Mrsk::Cli::App + subcommand "app", Kamal::Cli::App desc "build", "Build application image" - subcommand "build", Mrsk::Cli::Build + subcommand "build", Kamal::Cli::Build desc "healthcheck", "Healthcheck application" - subcommand "healthcheck", Mrsk::Cli::Healthcheck + subcommand "healthcheck", Kamal::Cli::Healthcheck desc "lock", "Manage the deploy lock" - subcommand "lock", Mrsk::Cli::Lock + subcommand "lock", Kamal::Cli::Lock desc "prune", "Prune old application images and containers" - subcommand "prune", Mrsk::Cli::Prune + subcommand "prune", Kamal::Cli::Prune desc "registry", "Login and -out of the image registry" - subcommand "registry", Mrsk::Cli::Registry + subcommand "registry", Kamal::Cli::Registry desc "server", "Bootstrap servers with curl and Docker" - subcommand "server", Mrsk::Cli::Server + subcommand "server", Kamal::Cli::Server desc "traefik", "Manage Traefik load balancer" - subcommand "traefik", Mrsk::Cli::Traefik + subcommand "traefik", Kamal::Cli::Traefik private def container_available?(version) begin - on(MRSK.hosts) do - MRSK.roles_on(host).each do |role| - container_id = capture_with_info(*MRSK.app(role: role).container_id_for_version(version)) + on(KAMAL.hosts) do + KAMAL.roles_on(host).each do |role| + container_id = capture_with_info(*KAMAL.app(role: role).container_id_for_version(version)) raise "Container not found" unless container_id.present? end end @@ -244,6 +244,6 @@ def container_available?(version) end def deploy_options - { "version" => MRSK.config.version }.merge(options.without("skip_push")) + { "version" => KAMAL.config.version }.merge(options.without("skip_push")) end end diff --git a/lib/kamal/cli/prune.rb b/lib/kamal/cli/prune.rb new file mode 100644 index 000000000..d11c39aeb --- /dev/null +++ b/lib/kamal/cli/prune.rb @@ -0,0 +1,30 @@ +class Kamal::Cli::Prune < Kamal::Cli::Base + desc "all", "Prune unused images and stopped containers" + def all + mutating do + containers + images + end + end + + desc "images", "Prune dangling images" + def images + mutating do + on(KAMAL.hosts) do + execute *KAMAL.auditor.record("Pruned images"), verbosity: :debug + execute *KAMAL.prune.dangling_images + execute *KAMAL.prune.tagged_images + end + end + end + + desc "containers", "Prune all stopped containers, except the last 5" + def containers + mutating do + on(KAMAL.hosts) do + execute *KAMAL.auditor.record("Pruned containers"), verbosity: :debug + execute *KAMAL.prune.containers + end + end + end +end diff --git a/lib/mrsk/cli/registry.rb b/lib/kamal/cli/registry.rb similarity index 59% rename from lib/mrsk/cli/registry.rb rename to lib/kamal/cli/registry.rb index dffcdff70..a8b671edc 100644 --- a/lib/mrsk/cli/registry.rb +++ b/lib/kamal/cli/registry.rb @@ -1,8 +1,8 @@ -class Mrsk::Cli::Registry < Mrsk::Cli::Base +class Kamal::Cli::Registry < Kamal::Cli::Base desc "login", "Log in to registry locally and remotely" def login - run_locally { execute *MRSK.registry.login } - on(MRSK.hosts) { execute *MRSK.registry.login } + run_locally { execute *KAMAL.registry.login } + on(KAMAL.hosts) { execute *KAMAL.registry.login } # FIXME: This rescue needed? rescue ArgumentError => e puts e.message @@ -10,7 +10,7 @@ def login desc "logout", "Log out of registry remotely" def logout - on(MRSK.hosts) { execute *MRSK.registry.logout } + on(KAMAL.hosts) { execute *KAMAL.registry.logout } # FIXME: This rescue needed? rescue ArgumentError => e puts e.message diff --git a/lib/mrsk/cli/server.rb b/lib/kamal/cli/server.rb similarity index 55% rename from lib/mrsk/cli/server.rb rename to lib/kamal/cli/server.rb index 6e05559c3..4cf23a5da 100644 --- a/lib/mrsk/cli/server.rb +++ b/lib/kamal/cli/server.rb @@ -1,13 +1,13 @@ -class Mrsk::Cli::Server < Mrsk::Cli::Base - desc "bootstrap", "Set up Docker to run MRSK apps" +class Kamal::Cli::Server < Kamal::Cli::Base + desc "bootstrap", "Set up Docker to run Kamal apps" def bootstrap missing = [] - on(MRSK.hosts | MRSK.accessory_hosts) do |host| - unless execute(*MRSK.docker.installed?, raise_on_non_zero_exit: false) - if execute(*MRSK.docker.superuser?, raise_on_non_zero_exit: false) + on(KAMAL.hosts | KAMAL.accessory_hosts) do |host| + unless execute(*KAMAL.docker.installed?, raise_on_non_zero_exit: false) + if execute(*KAMAL.docker.superuser?, raise_on_non_zero_exit: false) info "Missing Docker on #{host}. Installing…" - execute *MRSK.docker.install + execute *KAMAL.docker.install else missing << host end diff --git a/lib/mrsk/cli/templates/deploy.yml b/lib/kamal/cli/templates/deploy.yml similarity index 98% rename from lib/mrsk/cli/templates/deploy.yml rename to lib/kamal/cli/templates/deploy.yml index 45b987f52..362394b9c 100644 --- a/lib/mrsk/cli/templates/deploy.yml +++ b/lib/kamal/cli/templates/deploy.yml @@ -16,7 +16,7 @@ registry: # Always use an access token rather than real password when possible. password: - - MRSK_REGISTRY_PASSWORD + - KAMAL_REGISTRY_PASSWORD # Inject ENV variables into containers (secrets come from .env). # env: diff --git a/lib/kamal/cli/templates/sample_hooks/post-deploy.sample b/lib/kamal/cli/templates/sample_hooks/post-deploy.sample new file mode 100755 index 000000000..75efafc10 --- /dev/null +++ b/lib/kamal/cli/templates/sample_hooks/post-deploy.sample @@ -0,0 +1,14 @@ +#!/bin/sh + +# A sample post-deploy hook +# +# These environment variables are available: +# KAMAL_RECORDED_AT +# KAMAL_PERFORMER +# KAMAL_VERSION +# KAMAL_HOSTS +# KAMAL_ROLE (if set) +# KAMAL_DESTINATION (if set) +# KAMAL_RUNTIME + +echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds" diff --git a/lib/mrsk/cli/templates/sample_hooks/pre-build.sample b/lib/kamal/cli/templates/sample_hooks/pre-build.sample similarity index 76% rename from lib/mrsk/cli/templates/sample_hooks/pre-build.sample rename to lib/kamal/cli/templates/sample_hooks/pre-build.sample index 2902ea10c..218e29631 100755 --- a/lib/mrsk/cli/templates/sample_hooks/pre-build.sample +++ b/lib/kamal/cli/templates/sample_hooks/pre-build.sample @@ -9,12 +9,12 @@ # 4. The version we are deploying matches the remote # # These environment variables are available: -# MRSK_RECORDED_AT -# MRSK_PERFORMER -# MRSK_VERSION -# MRSK_HOSTS -# MRSK_ROLE (if set) -# MRSK_DESTINATION (if set) +# KAMAL_RECORDED_AT +# KAMAL_PERFORMER +# KAMAL_VERSION +# KAMAL_HOSTS +# KAMAL_ROLE (if set) +# KAMAL_DESTINATION (if set) if [ -n "$(git status --porcelain)" ]; then echo "Git checkout is not clean, aborting..." >&2 @@ -43,8 +43,8 @@ if [ -z "$remote_head" ]; then exit 1 fi -if [ "$MRSK_VERSION" != "$remote_head" ]; then - echo "Version ($MRSK_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2 +if [ "$KAMAL_VERSION" != "$remote_head" ]; then + echo "Version ($KAMAL_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2 exit 1 fi diff --git a/lib/mrsk/cli/templates/sample_hooks/pre-connect.sample b/lib/kamal/cli/templates/sample_hooks/pre-connect.sample similarity index 83% rename from lib/mrsk/cli/templates/sample_hooks/pre-connect.sample rename to lib/kamal/cli/templates/sample_hooks/pre-connect.sample index 557ecccbf..18e61d7e5 100755 --- a/lib/mrsk/cli/templates/sample_hooks/pre-connect.sample +++ b/lib/kamal/cli/templates/sample_hooks/pre-connect.sample @@ -5,15 +5,15 @@ # Warms DNS before connecting to hosts in parallel # # These environment variables are available: -# MRSK_RECORDED_AT -# MRSK_PERFORMER -# MRSK_VERSION -# MRSK_HOSTS -# MRSK_ROLE (if set) -# MRSK_DESTINATION (if set) -# MRSK_RUNTIME +# KAMAL_RECORDED_AT +# KAMAL_PERFORMER +# KAMAL_VERSION +# KAMAL_HOSTS +# KAMAL_ROLE (if set) +# KAMAL_DESTINATION (if set) +# KAMAL_RUNTIME -hosts = ENV["MRSK_HOSTS"].split(",") +hosts = ENV["KAMAL_HOSTS"].split(",") results = nil max = 3 diff --git a/lib/mrsk/cli/templates/sample_hooks/pre-deploy.sample b/lib/kamal/cli/templates/sample_hooks/pre-deploy.sample similarity index 90% rename from lib/mrsk/cli/templates/sample_hooks/pre-deploy.sample rename to lib/kamal/cli/templates/sample_hooks/pre-deploy.sample index 9443ba9b6..1b280c719 100755 --- a/lib/mrsk/cli/templates/sample_hooks/pre-deploy.sample +++ b/lib/kamal/cli/templates/sample_hooks/pre-deploy.sample @@ -7,17 +7,17 @@ # Fails unless the combined status is "success" # # These environment variables are available: -# MRSK_RECORDED_AT -# MRSK_PERFORMER -# MRSK_VERSION -# MRSK_HOSTS -# MRSK_COMMAND -# MRSK_SUBCOMMAND -# MRSK_ROLE (if set) -# MRSK_DESTINATION (if set) +# KAMAL_RECORDED_AT +# KAMAL_PERFORMER +# KAMAL_VERSION +# KAMAL_HOSTS +# KAMAL_COMMAND +# KAMAL_SUBCOMMAND +# KAMAL_ROLE (if set) +# KAMAL_DESTINATION (if set) # Only check the build status for production deployments -if ENV["MRSK_COMMAND"] == "rollback" || ENV["MRSK_DESTINATION"] != "production" +if ENV["KAMAL_COMMAND"] == "rollback" || ENV["KAMAL_DESTINATION"] != "production" exit 0 end diff --git a/lib/kamal/cli/templates/template.env b/lib/kamal/cli/templates/template.env new file mode 100644 index 000000000..89411448d --- /dev/null +++ b/lib/kamal/cli/templates/template.env @@ -0,0 +1,2 @@ +KAMAL_REGISTRY_PASSWORD=change-this +RAILS_MASTER_KEY=another-env diff --git a/lib/mrsk/cli/traefik.rb b/lib/kamal/cli/traefik.rb similarity index 56% rename from lib/mrsk/cli/traefik.rb rename to lib/kamal/cli/traefik.rb index a8458d6e7..9bc4f6448 100644 --- a/lib/mrsk/cli/traefik.rb +++ b/lib/kamal/cli/traefik.rb @@ -1,10 +1,10 @@ -class Mrsk::Cli::Traefik < Mrsk::Cli::Base +class Kamal::Cli::Traefik < Kamal::Cli::Base desc "boot", "Boot Traefik on servers" def boot mutating do - on(MRSK.traefik_hosts) do - execute *MRSK.registry.login - execute *MRSK.traefik.start_or_run + on(KAMAL.traefik_hosts) do + execute *KAMAL.registry.login + execute *KAMAL.traefik.start_or_run end end end @@ -13,12 +13,12 @@ def boot option :rolling, type: :boolean, default: false, desc: "Reboot traefik on hosts in sequence, rather than in parallel" def reboot mutating do - on(MRSK.traefik_hosts, in: options[:rolling] ? :sequence : :parallel) do - execute *MRSK.auditor.record("Rebooted traefik"), verbosity: :debug - execute *MRSK.registry.login - execute *MRSK.traefik.stop - execute *MRSK.traefik.remove_container - execute *MRSK.traefik.run + on(KAMAL.traefik_hosts, in: options[:rolling] ? :sequence : :parallel) do + execute *KAMAL.auditor.record("Rebooted traefik"), verbosity: :debug + execute *KAMAL.registry.login + execute *KAMAL.traefik.stop + execute *KAMAL.traefik.remove_container + execute *KAMAL.traefik.run end end end @@ -26,9 +26,9 @@ def reboot desc "start", "Start existing Traefik container on servers" def start mutating do - on(MRSK.traefik_hosts) do - execute *MRSK.auditor.record("Started traefik"), verbosity: :debug - execute *MRSK.traefik.start + on(KAMAL.traefik_hosts) do + execute *KAMAL.auditor.record("Started traefik"), verbosity: :debug + execute *KAMAL.traefik.start end end end @@ -36,9 +36,9 @@ def start desc "stop", "Stop existing Traefik container on servers" def stop mutating do - on(MRSK.traefik_hosts) do - execute *MRSK.auditor.record("Stopped traefik"), verbosity: :debug - execute *MRSK.traefik.stop + on(KAMAL.traefik_hosts) do + execute *KAMAL.auditor.record("Stopped traefik"), verbosity: :debug + execute *KAMAL.traefik.stop end end end @@ -53,7 +53,7 @@ def restart desc "details", "Show details about Traefik container from servers" def details - on(MRSK.traefik_hosts) { |host| puts_by_host host, capture_with_info(*MRSK.traefik.info), type: "Traefik" } + on(KAMAL.traefik_hosts) { |host| puts_by_host host, capture_with_info(*KAMAL.traefik.info), type: "Traefik" } end desc "logs", "Show log lines from Traefik on servers" @@ -66,16 +66,16 @@ def logs if options[:follow] run_locally do - info "Following logs on #{MRSK.primary_host}..." - info MRSK.traefik.follow_logs(host: MRSK.primary_host, grep: grep) - exec MRSK.traefik.follow_logs(host: MRSK.primary_host, grep: grep) + info "Following logs on #{KAMAL.primary_host}..." + info KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep) + exec KAMAL.traefik.follow_logs(host: KAMAL.primary_host, grep: grep) end else since = options[:since] lines = options[:lines].presence || ((since || grep) ? nil : 100) # Default to 100 lines if since or grep isn't set - on(MRSK.traefik_hosts) do |host| - puts_by_host host, capture(*MRSK.traefik.logs(since: since, lines: lines, grep: grep)), type: "Traefik" + on(KAMAL.traefik_hosts) do |host| + puts_by_host host, capture(*KAMAL.traefik.logs(since: since, lines: lines, grep: grep)), type: "Traefik" end end end @@ -92,9 +92,9 @@ def remove desc "remove_container", "Remove Traefik container from servers", hide: true def remove_container mutating do - on(MRSK.traefik_hosts) do - execute *MRSK.auditor.record("Removed traefik container"), verbosity: :debug - execute *MRSK.traefik.remove_container + on(KAMAL.traefik_hosts) do + execute *KAMAL.auditor.record("Removed traefik container"), verbosity: :debug + execute *KAMAL.traefik.remove_container end end end @@ -102,9 +102,9 @@ def remove_container desc "remove_image", "Remove Traefik image from servers", hide: true def remove_image mutating do - on(MRSK.traefik_hosts) do - execute *MRSK.auditor.record("Removed traefik image"), verbosity: :debug - execute *MRSK.traefik.remove_image + on(KAMAL.traefik_hosts) do + execute *KAMAL.auditor.record("Removed traefik image"), verbosity: :debug + execute *KAMAL.traefik.remove_image end end end diff --git a/lib/mrsk/commander.rb b/lib/kamal/commander.rb similarity index 80% rename from lib/mrsk/commander.rb rename to lib/kamal/commander.rb index 4812bc627..047951643 100644 --- a/lib/mrsk/commander.rb +++ b/lib/kamal/commander.rb @@ -1,7 +1,7 @@ require "active_support/core_ext/enumerable" require "active_support/core_ext/module/delegation" -class Mrsk::Commander +class Kamal::Commander attr_accessor :verbosity, :holding_lock, :hold_lock_on_error def initialize @@ -11,7 +11,7 @@ def initialize end def config - @config ||= Mrsk::Configuration.create_from(**@config_kwargs).tap do |config| + @config ||= Kamal::Configuration.create_from(**@config_kwargs).tap do |config| @config_kwargs = nil configure_sshkit_with(config) end @@ -77,47 +77,47 @@ def accessory_names def app(role: nil) - Mrsk::Commands::App.new(config, role: role) + Kamal::Commands::App.new(config, role: role) end def accessory(name) - Mrsk::Commands::Accessory.new(config, name: name) + Kamal::Commands::Accessory.new(config, name: name) end def auditor(**details) - Mrsk::Commands::Auditor.new(config, **details) + Kamal::Commands::Auditor.new(config, **details) end def builder - @builder ||= Mrsk::Commands::Builder.new(config) + @builder ||= Kamal::Commands::Builder.new(config) end def docker - @docker ||= Mrsk::Commands::Docker.new(config) + @docker ||= Kamal::Commands::Docker.new(config) end def healthcheck - @healthcheck ||= Mrsk::Commands::Healthcheck.new(config) + @healthcheck ||= Kamal::Commands::Healthcheck.new(config) end def hook - @hook ||= Mrsk::Commands::Hook.new(config) + @hook ||= Kamal::Commands::Hook.new(config) end def lock - @lock ||= Mrsk::Commands::Lock.new(config) + @lock ||= Kamal::Commands::Lock.new(config) end def prune - @prune ||= Mrsk::Commands::Prune.new(config) + @prune ||= Kamal::Commands::Prune.new(config) end def registry - @registry ||= Mrsk::Commands::Registry.new(config) + @registry ||= Kamal::Commands::Registry.new(config) end def traefik - @traefik ||= Mrsk::Commands::Traefik.new(config) + @traefik ||= Kamal::Commands::Traefik.new(config) end def with_verbosity(level) diff --git a/lib/kamal/commands.rb b/lib/kamal/commands.rb new file mode 100644 index 000000000..4fc6e3c50 --- /dev/null +++ b/lib/kamal/commands.rb @@ -0,0 +1,2 @@ +module Kamal::Commands +end diff --git a/lib/mrsk/commands/accessory.rb b/lib/kamal/commands/accessory.rb similarity index 97% rename from lib/mrsk/commands/accessory.rb rename to lib/kamal/commands/accessory.rb index 9ea7c0886..9252e2a27 100644 --- a/lib/mrsk/commands/accessory.rb +++ b/lib/kamal/commands/accessory.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Accessory < Mrsk::Commands::Base +class Kamal::Commands::Accessory < Kamal::Commands::Base attr_reader :accessory_config delegate :service_name, :image, :hosts, :port, :files, :directories, :cmd, :publish_args, :env_args, :volume_args, :label_args, :option_args, to: :accessory_config diff --git a/lib/mrsk/commands/app.rb b/lib/kamal/commands/app.rb similarity index 97% rename from lib/mrsk/commands/app.rb rename to lib/kamal/commands/app.rb index 5d95a300b..11d15fcc3 100644 --- a/lib/mrsk/commands/app.rb +++ b/lib/kamal/commands/app.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::App < Mrsk::Commands::Base +class Kamal::Commands::App < Kamal::Commands::Base ACTIVE_DOCKER_STATUSES = [ :running, :restarting ] attr_reader :role @@ -20,7 +20,7 @@ def run(hostname: nil) "--restart unless-stopped", "--name", container_name, *(["--hostname", hostname] if hostname), - "-e", "MRSK_CONTAINER_NAME=\"#{container_name}\"", + "-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"", *role.env_args, *role.health_check_args, *config.logging_args, diff --git a/lib/mrsk/commands/auditor.rb b/lib/kamal/commands/auditor.rb similarity index 76% rename from lib/mrsk/commands/auditor.rb rename to lib/kamal/commands/auditor.rb index 5089fb4db..0fefbbcb4 100644 --- a/lib/mrsk/commands/auditor.rb +++ b/lib/kamal/commands/auditor.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Auditor < Mrsk::Commands::Base +class Kamal::Commands::Auditor < Kamal::Commands::Base attr_reader :details def initialize(config, **details) @@ -19,7 +19,7 @@ def reveal private def audit_log_file - [ "mrsk", config.service, config.destination, "audit.log" ].compact.join("-") + [ "kamal", config.service, config.destination, "audit.log" ].compact.join("-") end def audit_tags(**details) diff --git a/lib/mrsk/commands/base.rb b/lib/kamal/commands/base.rb similarity index 92% rename from lib/mrsk/commands/base.rb rename to lib/kamal/commands/base.rb index 831f5994d..8a413b917 100644 --- a/lib/mrsk/commands/base.rb +++ b/lib/kamal/commands/base.rb @@ -1,6 +1,6 @@ -module Mrsk::Commands +module Kamal::Commands class Base - delegate :sensitive, :argumentize, to: Mrsk::Utils + delegate :sensitive, :argumentize, to: Kamal::Utils DOCKER_HEALTH_STATUS_FORMAT = "'{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}'" DOCKER_HEALTH_LOG_FORMAT = "'{{json .State.Health}}'" @@ -59,7 +59,7 @@ def docker(*args) end def tags(**details) - Mrsk::Tags.from_config(config, **details) + Kamal::Tags.from_config(config, **details) end end end diff --git a/lib/mrsk/commands/builder.rb b/lib/kamal/commands/builder.rb similarity index 66% rename from lib/mrsk/commands/builder.rb rename to lib/kamal/commands/builder.rb index 074890ceb..beb7e2895 100644 --- a/lib/mrsk/commands/builder.rb +++ b/lib/kamal/commands/builder.rb @@ -1,8 +1,8 @@ -class Mrsk::Commands::Builder < Mrsk::Commands::Base +class Kamal::Commands::Builder < Kamal::Commands::Base delegate :create, :remove, :push, :clean, :pull, :info, to: :target def name - target.class.to_s.remove("Mrsk::Commands::Builder::").underscore.inquiry + target.class.to_s.remove("Kamal::Commands::Builder::").underscore.inquiry end def target @@ -21,23 +21,23 @@ def target end def native - @native ||= Mrsk::Commands::Builder::Native.new(config) + @native ||= Kamal::Commands::Builder::Native.new(config) end def native_cached - @native ||= Mrsk::Commands::Builder::Native::Cached.new(config) + @native ||= Kamal::Commands::Builder::Native::Cached.new(config) end def native_remote - @native ||= Mrsk::Commands::Builder::Native::Remote.new(config) + @native ||= Kamal::Commands::Builder::Native::Remote.new(config) end def multiarch - @multiarch ||= Mrsk::Commands::Builder::Multiarch.new(config) + @multiarch ||= Kamal::Commands::Builder::Multiarch.new(config) end def multiarch_remote - @multiarch_remote ||= Mrsk::Commands::Builder::Multiarch::Remote.new(config) + @multiarch_remote ||= Kamal::Commands::Builder::Multiarch::Remote.new(config) end diff --git a/lib/mrsk/commands/builder/base.rb b/lib/kamal/commands/builder/base.rb similarity index 92% rename from lib/mrsk/commands/builder/base.rb rename to lib/kamal/commands/builder/base.rb index b45cee4d6..19d44935e 100644 --- a/lib/mrsk/commands/builder/base.rb +++ b/lib/kamal/commands/builder/base.rb @@ -1,8 +1,8 @@ -class Mrsk::Commands::Builder::Base < Mrsk::Commands::Base +class Kamal::Commands::Builder::Base < Kamal::Commands::Base class BuilderError < StandardError; end - delegate :argumentize, to: Mrsk::Utils + delegate :argumentize, to: Kamal::Utils delegate :args, :secrets, :dockerfile, :local_arch, :local_host, :remote_arch, :remote_host, :cache_from, :cache_to, to: :builder_config def clean diff --git a/lib/mrsk/commands/builder/multiarch.rb b/lib/kamal/commands/builder/multiarch.rb similarity index 79% rename from lib/mrsk/commands/builder/multiarch.rb rename to lib/kamal/commands/builder/multiarch.rb index 3ecd7b976..458c4ac67 100644 --- a/lib/mrsk/commands/builder/multiarch.rb +++ b/lib/kamal/commands/builder/multiarch.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Builder::Multiarch < Mrsk::Commands::Builder::Base +class Kamal::Commands::Builder::Multiarch < Kamal::Commands::Builder::Base def create docker :buildx, :create, "--use", "--name", builder_name end @@ -24,6 +24,6 @@ def info private def builder_name - "mrsk-#{config.service}-multiarch" + "kamal-#{config.service}-multiarch" end end diff --git a/lib/mrsk/commands/builder/multiarch/remote.rb b/lib/kamal/commands/builder/multiarch/remote.rb similarity index 93% rename from lib/mrsk/commands/builder/multiarch/remote.rb rename to lib/kamal/commands/builder/multiarch/remote.rb index 9e27b2f58..1f71979d1 100644 --- a/lib/mrsk/commands/builder/multiarch/remote.rb +++ b/lib/kamal/commands/builder/multiarch/remote.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Builder::Multiarch::Remote < Mrsk::Commands::Builder::Multiarch +class Kamal::Commands::Builder::Multiarch::Remote < Kamal::Commands::Builder::Multiarch def create combine \ create_contexts, diff --git a/lib/mrsk/commands/builder/native.rb b/lib/kamal/commands/builder/native.rb similarity index 81% rename from lib/mrsk/commands/builder/native.rb rename to lib/kamal/commands/builder/native.rb index e1b6880b3..d67d35192 100644 --- a/lib/mrsk/commands/builder/native.rb +++ b/lib/kamal/commands/builder/native.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Builder::Native < Mrsk::Commands::Builder::Base +class Kamal::Commands::Builder::Native < Kamal::Commands::Builder::Base def create # No-op on native without cache end diff --git a/lib/mrsk/commands/builder/native/cached.rb b/lib/kamal/commands/builder/native/cached.rb similarity index 75% rename from lib/mrsk/commands/builder/native/cached.rb rename to lib/kamal/commands/builder/native/cached.rb index f586203ff..f72d11923 100644 --- a/lib/mrsk/commands/builder/native/cached.rb +++ b/lib/kamal/commands/builder/native/cached.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Builder::Native::Cached < Mrsk::Commands::Builder::Native +class Kamal::Commands::Builder::Native::Cached < Kamal::Commands::Builder::Native def create docker :buildx, :create, "--use", "--driver=docker-container" end diff --git a/lib/mrsk/commands/builder/native/remote.rb b/lib/kamal/commands/builder/native/remote.rb similarity index 89% rename from lib/mrsk/commands/builder/native/remote.rb rename to lib/kamal/commands/builder/native/remote.rb index 2fc00e0f6..67d68e9f1 100644 --- a/lib/mrsk/commands/builder/native/remote.rb +++ b/lib/kamal/commands/builder/native/remote.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Builder::Native::Remote < Mrsk::Commands::Builder::Native +class Kamal::Commands::Builder::Native::Remote < Kamal::Commands::Builder::Native def create chain \ create_context, @@ -29,7 +29,7 @@ def info private def builder_name - "mrsk-#{config.service}-native-remote" + "kamal-#{config.service}-native-remote" end def builder_name_with_arch diff --git a/lib/mrsk/commands/docker.rb b/lib/kamal/commands/docker.rb similarity index 90% rename from lib/mrsk/commands/docker.rb rename to lib/kamal/commands/docker.rb index 85101d0f9..77070672a 100644 --- a/lib/mrsk/commands/docker.rb +++ b/lib/kamal/commands/docker.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Docker < Mrsk::Commands::Base +class Kamal::Commands::Docker < Kamal::Commands::Base # Install Docker using the https://github.com/docker/docker-install convenience script. def install pipe [ :curl, "-fsSL", "https://get.docker.com" ], :sh diff --git a/lib/mrsk/commands/healthcheck.rb b/lib/kamal/commands/healthcheck.rb similarity index 91% rename from lib/mrsk/commands/healthcheck.rb rename to lib/kamal/commands/healthcheck.rb index ad8070df6..d3c949233 100644 --- a/lib/mrsk/commands/healthcheck.rb +++ b/lib/kamal/commands/healthcheck.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Healthcheck < Mrsk::Commands::Base +class Kamal::Commands::Healthcheck < Kamal::Commands::Base EXPOSED_PORT = 3999 def run @@ -9,7 +9,7 @@ def run "--name", container_name_with_version, "--publish", "#{EXPOSED_PORT}:#{config.healthcheck["port"]}", "--label", "service=#{container_name}", - "-e", "MRSK_CONTAINER_NAME=\"#{container_name}\"", + "-e", "KAMAL_CONTAINER_NAME=\"#{container_name}\"", *web.env_args, *web.health_check_args, *config.volume_args, diff --git a/lib/mrsk/commands/hook.rb b/lib/kamal/commands/hook.rb similarity index 82% rename from lib/mrsk/commands/hook.rb rename to lib/kamal/commands/hook.rb index 912d44808..679021b2a 100644 --- a/lib/mrsk/commands/hook.rb +++ b/lib/kamal/commands/hook.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Hook < Mrsk::Commands::Base +class Kamal::Commands::Hook < Kamal::Commands::Base def run(hook, **details) [ hook_file(hook), env: tags(**details).env ] end diff --git a/lib/mrsk/commands/lock.rb b/lib/kamal/commands/lock.rb similarity index 92% rename from lib/mrsk/commands/lock.rb rename to lib/kamal/commands/lock.rb index 6166d4866..03b9abd27 100644 --- a/lib/mrsk/commands/lock.rb +++ b/lib/kamal/commands/lock.rb @@ -1,7 +1,7 @@ require "active_support/duration" require "time" -class Mrsk::Commands::Lock < Mrsk::Commands::Base +class Kamal::Commands::Lock < Kamal::Commands::Base def acquire(message, version) combine \ [:mkdir, lock_dir], @@ -40,7 +40,7 @@ def stat_lock_dir end def lock_dir - "mrsk_lock-#{config.service}" + "kamal_lock-#{config.service}" end def lock_details_file diff --git a/lib/mrsk/commands/prune.rb b/lib/kamal/commands/prune.rb similarity index 96% rename from lib/mrsk/commands/prune.rb rename to lib/kamal/commands/prune.rb index 92f80bab6..af363e815 100644 --- a/lib/mrsk/commands/prune.rb +++ b/lib/kamal/commands/prune.rb @@ -1,7 +1,7 @@ require "active_support/duration" require "active_support/core_ext/numeric/time" -class Mrsk::Commands::Prune < Mrsk::Commands::Base +class Kamal::Commands::Prune < Kamal::Commands::Base def dangling_images docker :image, :prune, "--force", "--filter", "label=service=#{config.service}", "--filter", "dangling=true" end diff --git a/lib/mrsk/commands/registry.rb b/lib/kamal/commands/registry.rb similarity index 87% rename from lib/mrsk/commands/registry.rb rename to lib/kamal/commands/registry.rb index 11172eaa3..eb02acadf 100644 --- a/lib/mrsk/commands/registry.rb +++ b/lib/kamal/commands/registry.rb @@ -1,4 +1,4 @@ -class Mrsk::Commands::Registry < Mrsk::Commands::Base +class Kamal::Commands::Registry < Kamal::Commands::Base delegate :registry, to: :config def login diff --git a/lib/mrsk/commands/traefik.rb b/lib/kamal/commands/traefik.rb similarity index 96% rename from lib/mrsk/commands/traefik.rb rename to lib/kamal/commands/traefik.rb index b64642110..2d886307d 100644 --- a/lib/mrsk/commands/traefik.rb +++ b/lib/kamal/commands/traefik.rb @@ -1,5 +1,5 @@ -class Mrsk::Commands::Traefik < Mrsk::Commands::Base - delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Mrsk::Utils +class Kamal::Commands::Traefik < Kamal::Commands::Base + delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Kamal::Utils DEFAULT_IMAGE = "traefik:v2.9" CONTAINER_PORT = 80 diff --git a/lib/mrsk/configuration.rb b/lib/kamal/configuration.rb similarity index 87% rename from lib/mrsk/configuration.rb rename to lib/kamal/configuration.rb index c35a98548..d6e8d7578 100644 --- a/lib/mrsk/configuration.rb +++ b/lib/kamal/configuration.rb @@ -5,9 +5,9 @@ require "erb" require "net/ssh/proxy/jump" -class Mrsk::Configuration +class Kamal::Configuration delegate :service, :image, :servers, :env, :labels, :registry, :stop_wait_time, :hooks_path, to: :raw_config, allow_nil: true - delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Mrsk::Utils + delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Kamal::Utils attr_accessor :destination attr_accessor :raw_config @@ -54,7 +54,7 @@ def version end def abbreviated_version - Mrsk::Utils.abbreviate_version(version) + Kamal::Utils.abbreviate_version(version) end @@ -67,7 +67,7 @@ def role(name) end def accessories - @accessories ||= raw_config.accessories&.keys&.collect { |name| Mrsk::Configuration::Accessory.new(name, config: self) } || [] + @accessories ||= raw_config.accessories&.keys&.collect { |name| Kamal::Configuration::Accessory.new(name, config: self) } || [] end def accessory(name) @@ -88,7 +88,7 @@ def traefik_hosts end def boot - Mrsk::Configuration::Boot.new(config: self) + Kamal::Configuration::Boot.new(config: self) end @@ -136,11 +136,11 @@ def logging_args def ssh - Mrsk::Configuration::Ssh.new(config: self) + Kamal::Configuration::Ssh.new(config: self) end def sshkit - Mrsk::Configuration::Sshkit.new(config: self) + Kamal::Configuration::Sshkit.new(config: self) end @@ -157,7 +157,7 @@ def minimum_version end def valid? - ensure_required_keys_present && ensure_valid_mrsk_version + ensure_required_keys_present && ensure_valid_kamal_version end @@ -186,11 +186,11 @@ def traefik end def hooks_path - raw_config.hooks_path || ".mrsk/hooks" + raw_config.hooks_path || ".kamal/hooks" end def builder - Mrsk::Configuration::Builder.new(config: self) + Kamal::Configuration::Builder.new(config: self) end # Will raise KeyError if any secret ENVs are missing @@ -225,9 +225,9 @@ def ensure_required_keys_present true end - def ensure_valid_mrsk_version - if minimum_version && Gem::Version.new(minimum_version) > Gem::Version.new(Mrsk::VERSION) - raise ArgumentError, "Current version is #{Mrsk::VERSION}, minimum required is #{minimum_version}" + def ensure_valid_kamal_version + if minimum_version && Gem::Version.new(minimum_version) > Gem::Version.new(Kamal::VERSION) + raise ArgumentError, "Current version is #{Kamal::VERSION}, minimum required is #{minimum_version}" end true @@ -241,7 +241,7 @@ def role_names def git_version @git_version ||= if system("git rev-parse") - uncommitted_suffix = Mrsk::Utils.uncommitted_changes.present? ? "_uncommitted_#{SecureRandom.hex(8)}" : "" + uncommitted_suffix = Kamal::Utils.uncommitted_changes.present? ? "_uncommitted_#{SecureRandom.hex(8)}" : "" "#{`git rev-parse HEAD`.strip}#{uncommitted_suffix}" else diff --git a/lib/mrsk/configuration/accessory.rb b/lib/kamal/configuration/accessory.rb similarity index 98% rename from lib/mrsk/configuration/accessory.rb rename to lib/kamal/configuration/accessory.rb index 595846a6c..4ffcfc4b2 100644 --- a/lib/mrsk/configuration/accessory.rb +++ b/lib/kamal/configuration/accessory.rb @@ -1,5 +1,5 @@ -class Mrsk::Configuration::Accessory - delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Mrsk::Utils +class Kamal::Configuration::Accessory + delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Kamal::Utils attr_accessor :name, :specifics diff --git a/lib/mrsk/configuration/boot.rb b/lib/kamal/configuration/boot.rb similarity index 90% rename from lib/mrsk/configuration/boot.rb rename to lib/kamal/configuration/boot.rb index 1332398a0..f6daa1fa2 100644 --- a/lib/mrsk/configuration/boot.rb +++ b/lib/kamal/configuration/boot.rb @@ -1,4 +1,4 @@ -class Mrsk::Configuration::Boot +class Kamal::Configuration::Boot def initialize(config:) @options = config.raw_config.boot || {} @host_count = config.all_hosts.count diff --git a/lib/mrsk/configuration/builder.rb b/lib/kamal/configuration/builder.rb similarity index 98% rename from lib/mrsk/configuration/builder.rb rename to lib/kamal/configuration/builder.rb index fbb6b42e1..c7d81922a 100644 --- a/lib/mrsk/configuration/builder.rb +++ b/lib/kamal/configuration/builder.rb @@ -1,4 +1,4 @@ -class Mrsk::Configuration::Builder +class Kamal::Configuration::Builder def initialize(config:) @options = config.raw_config.builder || {} @image = config.image diff --git a/lib/mrsk/configuration/role.rb b/lib/kamal/configuration/role.rb similarity index 98% rename from lib/mrsk/configuration/role.rb rename to lib/kamal/configuration/role.rb index 048efe16d..4302430dd 100644 --- a/lib/mrsk/configuration/role.rb +++ b/lib/kamal/configuration/role.rb @@ -1,5 +1,5 @@ -class Mrsk::Configuration::Role - delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Mrsk::Utils +class Kamal::Configuration::Role + delegate :argumentize, :argumentize_env_with_secrets, :optionize, to: Kamal::Utils attr_accessor :name diff --git a/lib/mrsk/configuration/ssh.rb b/lib/kamal/configuration/ssh.rb similarity index 96% rename from lib/mrsk/configuration/ssh.rb rename to lib/kamal/configuration/ssh.rb index f8ad0a3d2..c98fca716 100644 --- a/lib/mrsk/configuration/ssh.rb +++ b/lib/kamal/configuration/ssh.rb @@ -1,4 +1,4 @@ -class Mrsk::Configuration::Ssh +class Kamal::Configuration::Ssh LOGGER = ::Logger.new(STDERR) def initialize(config:) diff --git a/lib/mrsk/configuration/sshkit.rb b/lib/kamal/configuration/sshkit.rb similarity index 89% rename from lib/mrsk/configuration/sshkit.rb rename to lib/kamal/configuration/sshkit.rb index 5371e15d6..9631a9160 100644 --- a/lib/mrsk/configuration/sshkit.rb +++ b/lib/kamal/configuration/sshkit.rb @@ -1,4 +1,4 @@ -class Mrsk::Configuration::Sshkit +class Kamal::Configuration::Sshkit def initialize(config:) @options = config.raw_config.sshkit || {} end diff --git a/lib/mrsk/sshkit_with_ext.rb b/lib/kamal/sshkit_with_ext.rb similarity index 100% rename from lib/mrsk/sshkit_with_ext.rb rename to lib/kamal/sshkit_with_ext.rb diff --git a/lib/mrsk/tags.rb b/lib/kamal/tags.rb similarity index 90% rename from lib/mrsk/tags.rb rename to lib/kamal/tags.rb index c134a8f73..4538f28db 100644 --- a/lib/mrsk/tags.rb +++ b/lib/kamal/tags.rb @@ -1,6 +1,6 @@ require "time" -class Mrsk::Tags +class Kamal::Tags attr_reader :config, :tags class << self @@ -26,7 +26,7 @@ def initialize(**tags) end def env - tags.transform_keys { |detail| "MRSK_#{detail.upcase}" } + tags.transform_keys { |detail| "KAMAL_#{detail.upcase}" } end def to_s diff --git a/lib/mrsk/utils.rb b/lib/kamal/utils.rb similarity index 98% rename from lib/mrsk/utils.rb rename to lib/kamal/utils.rb index 939c92dd0..c2461373b 100644 --- a/lib/mrsk/utils.rb +++ b/lib/kamal/utils.rb @@ -1,4 +1,4 @@ -module Mrsk::Utils +module Kamal::Utils extend self DOLLAR_SIGN_WITHOUT_SHELL_EXPANSION_REGEX = /\$(?!{[^\}]*\})/ @@ -46,7 +46,7 @@ def flatten_args(args) # Pass `redaction:` to change the default `"[REDACTED]"` redaction, e.g. # `sensitive "#{arg}=#{secret}", redaction: "#{arg}=xxxx" def sensitive(...) - Mrsk::Utils::Sensitive.new(...) + Kamal::Utils::Sensitive.new(...) end def redacted(value) diff --git a/lib/mrsk/utils/healthcheck_poller.rb b/lib/kamal/utils/healthcheck_poller.rb similarity index 83% rename from lib/mrsk/utils/healthcheck_poller.rb rename to lib/kamal/utils/healthcheck_poller.rb index 3ef5b7a88..ddb09ec65 100644 --- a/lib/mrsk/utils/healthcheck_poller.rb +++ b/lib/kamal/utils/healthcheck_poller.rb @@ -1,4 +1,4 @@ -class Mrsk::Utils::HealthcheckPoller +class Kamal::Utils::HealthcheckPoller TRAEFIK_HEALTHY_DELAY = 2 class HealthcheckError < StandardError; end @@ -6,14 +6,14 @@ class HealthcheckError < StandardError; end class << self def wait_for_healthy(pause_after_ready: false, &block) attempt = 1 - max_attempts = MRSK.config.healthcheck["max_attempts"] + max_attempts = KAMAL.config.healthcheck["max_attempts"] begin case status = block.call when "healthy" sleep TRAEFIK_HEALTHY_DELAY if pause_after_ready when "running" # No health check configured - sleep MRSK.config.readiness_delay if pause_after_ready + sleep KAMAL.config.readiness_delay if pause_after_ready else raise HealthcheckError, "container not ready (#{status})" end diff --git a/lib/mrsk/utils/sensitive.rb b/lib/kamal/utils/sensitive.rb similarity index 93% rename from lib/mrsk/utils/sensitive.rb rename to lib/kamal/utils/sensitive.rb index 0d29fab46..2cf8bc3f0 100644 --- a/lib/mrsk/utils/sensitive.rb +++ b/lib/kamal/utils/sensitive.rb @@ -1,6 +1,6 @@ require "active_support/core_ext/module/delegation" -class Mrsk::Utils::Sensitive +class Kamal::Utils::Sensitive # So SSHKit knows to redact these values. include SSHKit::Redaction diff --git a/lib/mrsk/version.rb b/lib/kamal/version.rb similarity index 65% rename from lib/mrsk/version.rb rename to lib/kamal/version.rb index 6854e14d6..bfd11d967 100644 --- a/lib/mrsk/version.rb +++ b/lib/kamal/version.rb @@ -1,3 +1,3 @@ -module Mrsk +module Kamal VERSION = "0.15.1" end diff --git a/lib/mrsk/cli/healthcheck.rb b/lib/mrsk/cli/healthcheck.rb deleted file mode 100644 index 2db63ce75..000000000 --- a/lib/mrsk/cli/healthcheck.rb +++ /dev/null @@ -1,20 +0,0 @@ -class Mrsk::Cli::Healthcheck < Mrsk::Cli::Base - default_command :perform - - desc "perform", "Health check current app version" - def perform - on(MRSK.primary_host) do - begin - execute *MRSK.healthcheck.run - Mrsk::Utils::HealthcheckPoller.wait_for_healthy { capture_with_info(*MRSK.healthcheck.status) } - rescue Mrsk::Utils::HealthcheckPoller::HealthcheckError => e - error capture_with_info(*MRSK.healthcheck.logs) - error capture_with_pretty_json(*MRSK.healthcheck.container_health_log) - raise - ensure - execute *MRSK.healthcheck.stop, raise_on_non_zero_exit: false - execute *MRSK.healthcheck.remove, raise_on_non_zero_exit: false - end - end - end -end diff --git a/lib/mrsk/cli/prune.rb b/lib/mrsk/cli/prune.rb deleted file mode 100644 index 381ddfd79..000000000 --- a/lib/mrsk/cli/prune.rb +++ /dev/null @@ -1,30 +0,0 @@ -class Mrsk::Cli::Prune < Mrsk::Cli::Base - desc "all", "Prune unused images and stopped containers" - def all - mutating do - containers - images - end - end - - desc "images", "Prune dangling images" - def images - mutating do - on(MRSK.hosts) do - execute *MRSK.auditor.record("Pruned images"), verbosity: :debug - execute *MRSK.prune.dangling_images - execute *MRSK.prune.tagged_images - end - end - end - - desc "containers", "Prune all stopped containers, except the last 5" - def containers - mutating do - on(MRSK.hosts) do - execute *MRSK.auditor.record("Pruned containers"), verbosity: :debug - execute *MRSK.prune.containers - end - end - end -end diff --git a/lib/mrsk/cli/templates/sample_hooks/post-deploy.sample b/lib/mrsk/cli/templates/sample_hooks/post-deploy.sample deleted file mode 100755 index 806f7b06a..000000000 --- a/lib/mrsk/cli/templates/sample_hooks/post-deploy.sample +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -# A sample post-deploy hook -# -# These environment variables are available: -# MRSK_RECORDED_AT -# MRSK_PERFORMER -# MRSK_VERSION -# MRSK_HOSTS -# MRSK_ROLE (if set) -# MRSK_DESTINATION (if set) -# MRSK_RUNTIME - -echo "$MRSK_PERFORMER deployed $MRSK_VERSION to $MRSK_DESTINATION in $MRSK_RUNTIME seconds" diff --git a/lib/mrsk/cli/templates/template.env b/lib/mrsk/cli/templates/template.env deleted file mode 100644 index 315a5e00e..000000000 --- a/lib/mrsk/cli/templates/template.env +++ /dev/null @@ -1,2 +0,0 @@ -MRSK_REGISTRY_PASSWORD=change-this -RAILS_MASTER_KEY=another-env diff --git a/lib/mrsk/commands.rb b/lib/mrsk/commands.rb deleted file mode 100644 index 5551c8547..000000000 --- a/lib/mrsk/commands.rb +++ /dev/null @@ -1,2 +0,0 @@ -module Mrsk::Commands -end diff --git a/test/cli/accessory_test.rb b/test/cli/accessory_test.rb index 4f3210bbd..99dc6e7c1 100644 --- a/test/cli/accessory_test.rb +++ b/test/cli/accessory_test.rb @@ -2,8 +2,8 @@ class CliAccessoryTest < CliTestCase test "boot" do - Mrsk::Cli::Accessory.any_instance.expects(:directories).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:upload).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:directories).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:upload).with("mysql") run_command("boot", "mysql").tap do |output| assert_match /docker login.*on 1.1.1.3/, output @@ -12,10 +12,10 @@ class CliAccessoryTest < CliTestCase end test "boot all" do - Mrsk::Cli::Accessory.any_instance.expects(:directories).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:upload).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:directories).with("redis") - Mrsk::Cli::Accessory.any_instance.expects(:upload).with("redis") + Kamal::Cli::Accessory.any_instance.expects(:directories).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:upload).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:directories).with("redis") + Kamal::Cli::Accessory.any_instance.expects(:upload).with("redis") run_command("boot", "all").tap do |output| assert_match /docker login.*on 1.1.1.3/, output @@ -40,10 +40,10 @@ class CliAccessoryTest < CliTestCase end test "reboot" do - Mrsk::Commands::Registry.any_instance.expects(:login) - Mrsk::Cli::Accessory.any_instance.expects(:stop).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:boot).with("mysql", login: false) + Kamal::Commands::Registry.any_instance.expects(:login) + Kamal::Cli::Accessory.any_instance.expects(:stop).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:boot).with("mysql", login: false) run_command("reboot", "mysql") end @@ -57,8 +57,8 @@ class CliAccessoryTest < CliTestCase end test "restart" do - Mrsk::Cli::Accessory.any_instance.expects(:stop).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:start).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:stop).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:start).with("mysql") run_command("restart", "mysql") end @@ -103,23 +103,23 @@ class CliAccessoryTest < CliTestCase end test "remove with confirmation" do - Mrsk::Cli::Accessory.any_instance.expects(:stop).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:remove_image).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:remove_service_directory).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:stop).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:remove_image).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:remove_service_directory).with("mysql") run_command("remove", "mysql", "-y") end test "remove all with confirmation" do - Mrsk::Cli::Accessory.any_instance.expects(:stop).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:remove_image).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:remove_service_directory).with("mysql") - Mrsk::Cli::Accessory.any_instance.expects(:stop).with("redis") - Mrsk::Cli::Accessory.any_instance.expects(:remove_container).with("redis") - Mrsk::Cli::Accessory.any_instance.expects(:remove_image).with("redis") - Mrsk::Cli::Accessory.any_instance.expects(:remove_service_directory).with("redis") + Kamal::Cli::Accessory.any_instance.expects(:stop).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:remove_container).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:remove_image).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:remove_service_directory).with("mysql") + Kamal::Cli::Accessory.any_instance.expects(:stop).with("redis") + Kamal::Cli::Accessory.any_instance.expects(:remove_container).with("redis") + Kamal::Cli::Accessory.any_instance.expects(:remove_image).with("redis") + Kamal::Cli::Accessory.any_instance.expects(:remove_service_directory).with("redis") run_command("remove", "all", "-y") end @@ -138,6 +138,6 @@ class CliAccessoryTest < CliTestCase private def run_command(*command) - stdouted { Mrsk::Cli::Accessory.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + stdouted { Kamal::Cli::Accessory.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } end end diff --git a/test/cli/app_test.rb b/test/cli/app_test.rb index 828d7d489..8a90e90ab 100644 --- a/test/cli/app_test.rb +++ b/test/cli/app_test.rb @@ -11,7 +11,7 @@ class CliAppTest < CliTestCase end test "boot will rename if same version is already running" do - run_command("details") # Preheat MRSK const + run_command("details") # Preheat Kamal const SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) .with(:docker, :container, :ls, "--filter", "name=^app-web-latest$", "--quiet", raise_on_non_zero_exit: false) @@ -36,11 +36,11 @@ class CliAppTest < CliTestCase end test "boot uses group strategy when specified" do - Mrsk::Cli::App.any_instance.stubs(:on).with("1.1.1.1").twice # acquire & release lock - Mrsk::Cli::App.any_instance.stubs(:on).with([ "1.1.1.1" ]) # tag container + Kamal::Cli::App.any_instance.stubs(:on).with("1.1.1.1").twice # acquire & release lock + Kamal::Cli::App.any_instance.stubs(:on).with([ "1.1.1.1" ]) # tag container # Strategy is used when booting the containers - Mrsk::Cli::App.any_instance.expects(:on).with([ "1.1.1.1" ], in: :groups, limit: 3, wait: 2).with_block_given + Kamal::Cli::App.any_instance.expects(:on).with([ "1.1.1.1" ], in: :groups, limit: 3, wait: 2).with_block_given run_command("boot", config: :with_boot_strategy) end @@ -48,13 +48,13 @@ class CliAppTest < CliTestCase test "boot errors leave lock in place" do invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999" } - Mrsk::Cli::App.any_instance.expects(:using_version).raises(RuntimeError) + Kamal::Cli::App.any_instance.expects(:using_version).raises(RuntimeError) - assert !MRSK.holding_lock? + assert !KAMAL.holding_lock? assert_raises(RuntimeError) do stderred { run_command("boot") } end - assert MRSK.holding_lock? + assert KAMAL.holding_lock? end test "start" do @@ -169,14 +169,14 @@ class CliAppTest < CliTestCase test "version through main" do - stdouted { Mrsk::Cli::Main.start(["app", "version", "-c", "test/fixtures/deploy_with_accessories.yml", "--hosts", "1.1.1.1"]) }.tap do |output| + stdouted { Kamal::Cli::Main.start(["app", "version", "-c", "test/fixtures/deploy_with_accessories.yml", "--hosts", "1.1.1.1"]) }.tap do |output| assert_match "docker ps --filter label=service=app --filter label=role=web --filter status=running --filter status=restarting --latest --format \"{{.Names}}\" | while read line; do echo ${line#app-web-}; done", output end end private def run_command(*command, config: :with_accessories) - stdouted { Mrsk::Cli::App.start([*command, "-c", "test/fixtures/deploy_#{config}.yml", "--hosts", "1.1.1.1"]) } + stdouted { Kamal::Cli::App.start([*command, "-c", "test/fixtures/deploy_#{config}.yml", "--hosts", "1.1.1.1"]) } end def stub_running diff --git a/test/cli/build_test.rb b/test/cli/build_test.rb index 68b205097..4e09564cf 100644 --- a/test/cli/build_test.rb +++ b/test/cli/build_test.rb @@ -2,20 +2,20 @@ class CliBuildTest < CliTestCase test "deliver" do - Mrsk::Cli::Build.any_instance.expects(:push) - Mrsk::Cli::Build.any_instance.expects(:pull) + Kamal::Cli::Build.any_instance.expects(:push) + Kamal::Cli::Build.any_instance.expects(:pull) run_command("deliver") end test "push" do - Mrsk::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) + Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "build", subcommand: "push" } run_command("push").tap do |output| assert_hook_ran "pre-build", output, **hook_variables assert_match /docker --version && docker buildx version/, output - assert_match /docker buildx build --push --platform linux\/amd64,linux\/arm64 --builder mrsk-app-multiarch -t dhh\/app:999 -t dhh\/app:latest --label service="app" --file Dockerfile \. as .*@localhost/, output + assert_match /docker buildx build --push --platform linux\/amd64,linux\/arm64 --builder kamal-app-multiarch -t dhh\/app:999 -t dhh\/app:latest --label service="app" --file Dockerfile \. as .*@localhost/, output end end @@ -41,14 +41,14 @@ class CliBuildTest < CliTestCase .with(:docker, "--version", "&&", :docker, :buildx, "version") .raises(SSHKit::Command::Failed.new("no buildx")) - Mrsk::Commands::Builder.any_instance.stubs(:native_and_local?).returns(false) - assert_raises(Mrsk::Cli::Build::BuildError) { run_command("push") } + Kamal::Commands::Builder.any_instance.stubs(:native_and_local?).returns(false) + assert_raises(Kamal::Cli::Build::BuildError) { run_command("push") } end test "push pre-build hook failure" do fail_hook("pre-build") - assert_raises(Mrsk::Cli::HookError) { run_command("push") } + assert_raises(Kamal::Cli::HookError) { run_command("push") } assert @executions.none? { |args| args[0..2] == [:docker, :buildx, :build] } end @@ -62,7 +62,7 @@ class CliBuildTest < CliTestCase test "create" do run_command("create").tap do |output| - assert_match /docker buildx create --use --name mrsk-app-multiarch/, output + assert_match /docker buildx create --use --name kamal-app-multiarch/, output end end @@ -79,7 +79,7 @@ class CliBuildTest < CliTestCase test "remove" do run_command("remove").tap do |output| - assert_match /docker buildx rm mrsk-app-multiarch/, output + assert_match /docker buildx rm kamal-app-multiarch/, output end end @@ -96,7 +96,7 @@ class CliBuildTest < CliTestCase private def run_command(*command) - stdouted { Mrsk::Cli::Build.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + stdouted { Kamal::Cli::Build.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } end def stub_dependency_checks diff --git a/test/cli/cli_test_case.rb b/test/cli/cli_test_case.rb index f094378de..c7d946e96 100644 --- a/test/cli/cli_test_case.rb +++ b/test/cli/cli_test_case.rb @@ -5,8 +5,8 @@ class CliTestCase < ActiveSupport::TestCase ENV["VERSION"] = "999" ENV["RAILS_MASTER_KEY"] = "123" ENV["MYSQL_ROOT_PASSWORD"] = "secret123" - Object.send(:remove_const, :MRSK) - Object.const_set(:MRSK, Mrsk::Commander.new) + Object.send(:remove_const, :Kamal) + Object.const_set(:Kamal, Kamal::Commander.new) end teardown do @@ -18,20 +18,20 @@ class CliTestCase < ActiveSupport::TestCase private def fail_hook(hook) @executions = [] - Mrsk::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) + Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) SSHKit::Backend::Abstract.any_instance.stubs(:execute) - .with { |*args| @executions << args; args != [".mrsk/hooks/#{hook}"] } + .with { |*args| @executions << args; args != [".kamal/hooks/#{hook}"] } SSHKit::Backend::Abstract.any_instance.stubs(:execute) - .with { |*args| args.first == ".mrsk/hooks/#{hook}" } + .with { |*args| args.first == ".kamal/hooks/#{hook}" } .raises(SSHKit::Command::Failed.new("failed")) end def stub_locking SSHKit::Backend::Abstract.any_instance.stubs(:execute) - .with { |arg1, arg2| arg1 == :mkdir && arg2 == "mrsk_lock-app" } + .with { |arg1, arg2| arg1 == :mkdir && arg2 == "kamal_lock-app" } SSHKit::Backend::Abstract.any_instance.stubs(:execute) - .with { |arg1, arg2| arg1 == :rm && arg2 == "mrsk_lock-app/details" } + .with { |arg1, arg2| arg1 == :rm && arg2 == "kamal_lock-app/details" } end def assert_hook_ran(hook, output, version:, service_version:, hosts:, command:, subcommand: nil, runtime: nil) @@ -39,17 +39,17 @@ def assert_hook_ran(hook, output, version:, service_version:, hosts:, command:, assert_match "Running the #{hook} hook...\n", output - expected = %r{Running\s/usr/bin/env\s\.mrsk/hooks/#{hook}\sas\s#{performer}@localhost\n\s + expected = %r{Running\s/usr/bin/env\s\.kamal/hooks/#{hook}\sas\s#{performer}@localhost\n\s DEBUG\s\[[0-9a-f]*\]\sCommand:\s\(\sexport\s - MRSK_RECORDED_AT=\"\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ\"\s - MRSK_PERFORMER=\"#{performer}\"\s - MRSK_VERSION=\"#{version}\"\s - MRSK_SERVICE_VERSION=\"#{service_version}\"\s - MRSK_HOSTS=\"#{hosts}\"\s - MRSK_COMMAND=\"#{command}\"\s - #{"MRSK_SUBCOMMAND=\\\"#{subcommand}\\\"\\s" if subcommand} - #{"MRSK_RUNTIME=\\\"#{runtime}\\\"\\s" if runtime} - ;\s/usr/bin/env\s\.mrsk/hooks/#{hook} }x + KAMAL_RECORDED_AT=\"\d\d\d\d-\d\d-\d\dT\d\d:\d\d:\d\dZ\"\s + KAMAL_PERFORMER=\"#{performer}\"\s + KAMAL_VERSION=\"#{version}\"\s + KAMAL_SERVICE_VERSION=\"#{service_version}\"\s + KAMAL_HOSTS=\"#{hosts}\"\s + KAMAL_COMMAND=\"#{command}\"\s + #{"KAMAL_SUBCOMMAND=\\\"#{subcommand}\\\"\\s" if subcommand} + #{"KAMAL_RUNTIME=\\\"#{runtime}\\\"\\s" if runtime} + ;\s/usr/bin/env\s\.kamal/hooks/#{hook} }x assert_match expected, output end diff --git a/test/cli/healthcheck_test.rb b/test/cli/healthcheck_test.rb index 67c3314f3..9cef1c8f3 100644 --- a/test/cli/healthcheck_test.rb +++ b/test/cli/healthcheck_test.rb @@ -5,12 +5,12 @@ class CliHealthcheckTest < CliTestCase # Prevent expected failures from outputting to terminal Thread.report_on_exception = false - Mrsk::Utils::HealthcheckPoller.stubs(:sleep) # No sleeping when retrying + Kamal::Utils::HealthcheckPoller.stubs(:sleep) # No sleeping when retrying SSHKit::Backend::Abstract.any_instance.stubs(:execute) .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :stop, raise_on_non_zero_exit: false) SSHKit::Backend::Abstract.any_instance.stubs(:execute) - .with(:docker, :run, "--detach", "--name", "healthcheck-app-999", "--publish", "3999:3000", "--label", "service=healthcheck-app", "-e", "MRSK_CONTAINER_NAME=\"healthcheck-app\"", "--health-cmd", "\"curl -f http://localhost:3000/up || exit 1\"", "--health-interval", "\"1s\"", "dhh/app:999") + .with(:docker, :run, "--detach", "--name", "healthcheck-app-999", "--publish", "3999:3000", "--label", "service=healthcheck-app", "-e", "KAMAL_CONTAINER_NAME=\"healthcheck-app\"", "--health-cmd", "\"curl -f http://localhost:3000/up || exit 1\"", "--health-interval", "\"1s\"", "dhh/app:999") SSHKit::Backend::Abstract.any_instance.stubs(:execute) .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :container, :rm, raise_on_non_zero_exit: false) @@ -34,12 +34,12 @@ class CliHealthcheckTest < CliTestCase # Prevent expected failures from outputting to terminal Thread.report_on_exception = false - Mrsk::Utils::HealthcheckPoller.stubs(:sleep) # No sleeping when retrying + Kamal::Utils::HealthcheckPoller.stubs(:sleep) # No sleeping when retrying SSHKit::Backend::Abstract.any_instance.stubs(:execute) .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :stop, raise_on_non_zero_exit: false) SSHKit::Backend::Abstract.any_instance.stubs(:execute) - .with(:docker, :run, "--detach", "--name", "healthcheck-app-999", "--publish", "3999:3000", "--label", "service=healthcheck-app", "-e", "MRSK_CONTAINER_NAME=\"healthcheck-app\"", "--health-cmd", "\"curl -f http://localhost:3000/up || exit 1\"", "--health-interval", "\"1s\"", "dhh/app:999") + .with(:docker, :run, "--detach", "--name", "healthcheck-app-999", "--publish", "3999:3000", "--label", "service=healthcheck-app", "-e", "KAMAL_CONTAINER_NAME=\"healthcheck-app\"", "--health-cmd", "\"curl -f http://localhost:3000/up || exit 1\"", "--health-interval", "\"1s\"", "dhh/app:999") SSHKit::Backend::Abstract.any_instance.stubs(:execute) .with(:docker, :container, :ls, "--all", "--filter", "name=^healthcheck-app-999$", "--quiet", "|", :xargs, :docker, :container, :rm, raise_on_non_zero_exit: false) @@ -66,6 +66,6 @@ class CliHealthcheckTest < CliTestCase private def run_command(*command) - stdouted { Mrsk::Cli::Healthcheck.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + stdouted { Kamal::Cli::Healthcheck.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } end end diff --git a/test/cli/lock_test.rb b/test/cli/lock_test.rb index a5c45c2cd..9521480f0 100644 --- a/test/cli/lock_test.rb +++ b/test/cli/lock_test.rb @@ -15,6 +15,6 @@ class CliLockTest < CliTestCase private def run_command(*command) - stdouted { Mrsk::Cli::Lock.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + stdouted { Kamal::Cli::Lock.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } end end diff --git a/test/cli/main_test.rb b/test/cli/main_test.rb index f72ef34e7..888a66885 100644 --- a/test/cli/main_test.rb +++ b/test/cli/main_test.rb @@ -2,9 +2,9 @@ class CliMainTest < CliTestCase test "setup" do - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:server:bootstrap") - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:accessory:boot", [ "all" ]) - Mrsk::Cli::Main.any_instance.expects(:deploy) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:server:bootstrap") + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:boot", [ "all" ]) + Kamal::Cli::Main.any_instance.expects(:deploy) run_command("setup") end @@ -12,15 +12,15 @@ class CliMainTest < CliTestCase test "deploy" do invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false } - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:registry:login", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:deliver", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:traefik:boot", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:stale_containers", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:boot", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:prune:all", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:registry:login", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:build:deliver", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:traefik:boot", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:healthcheck:perform", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:stale_containers", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:prune:all", [], invoke_options) - Mrsk::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) + Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2", command: "deploy" } run_command("deploy").tap do |output| @@ -39,13 +39,13 @@ class CliMainTest < CliTestCase test "deploy with skip_push" do invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false } - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:registry:login", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:pull", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:traefik:boot", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:stale_containers", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:boot", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:prune:all", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:registry:login", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:build:pull", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:traefik:boot", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:healthcheck:perform", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:stale_containers", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:prune:all", [], invoke_options) run_command("deploy", "--skip_push").tap do |output| assert_match /Acquiring the deploy lock/, output @@ -63,13 +63,13 @@ class CliMainTest < CliTestCase Thread.report_on_exception = false SSHKit::Backend::Abstract.any_instance.stubs(:execute) - .with { |*arg| arg[0..1] == [:mkdir, 'mrsk_lock-app'] } - .raises(RuntimeError, "mkdir: cannot create directory ‘mrsk_lock-app’: File exists") + .with { |*arg| arg[0..1] == [:mkdir, 'kamal_lock-app'] } + .raises(RuntimeError, "mkdir: cannot create directory ‘kamal_lock-app’: File exists") SSHKit::Backend::Abstract.any_instance.expects(:capture_with_debug) - .with(:stat, 'mrsk_lock-app', ">", "/dev/null", "&&", :cat, "mrsk_lock-app/details", "|", :base64, "-d") + .with(:stat, 'kamal_lock-app', ">", "/dev/null", "&&", :cat, "kamal_lock-app/details", "|", :base64, "-d") - assert_raises(Mrsk::Cli::LockError) do + assert_raises(Kamal::Cli::LockError) do run_command("deploy") end end @@ -78,7 +78,7 @@ class CliMainTest < CliTestCase Thread.report_on_exception = false SSHKit::Backend::Abstract.any_instance.stubs(:execute) - .with { |*arg| arg[0..1] == [:mkdir, 'mrsk_lock-app'] } + .with { |*arg| arg[0..1] == [:mkdir, 'kamal_lock-app'] } .raises(SocketError, "getaddrinfo: nodename nor servname provided, or not known") assert_raises(SSHKit::Runner::ExecuteError) do @@ -89,27 +89,27 @@ class CliMainTest < CliTestCase test "deploy errors during outside section leave remove lock" do invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false } - Mrsk::Cli::Main.any_instance.expects(:invoke) - .with("mrsk:cli:registry:login", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke) + .with("kamal:cli:registry:login", [], invoke_options) .raises(RuntimeError) - assert !MRSK.holding_lock? + assert !KAMAL.holding_lock? assert_raises(RuntimeError) do stderred { run_command("deploy") } end - assert !MRSK.holding_lock? + assert !KAMAL.holding_lock? end test "deploy with skipped hooks" do invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => true } - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:registry:login", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:deliver", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:traefik:boot", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:stale_containers", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:boot", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:prune:all", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:registry:login", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:build:deliver", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:traefik:boot", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:healthcheck:perform", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:stale_containers", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:prune:all", [], invoke_options) run_command("deploy", "--skip_hooks") do refute_match /Running the post-deploy hook.../, output @@ -125,12 +125,12 @@ class CliMainTest < CliTestCase test "redeploy" do invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false } - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:deliver", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:stale_containers", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:boot", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:build:deliver", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:healthcheck:perform", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:stale_containers", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options) - Mrsk::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) + Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) hook_variables = { version: 999, service_version: "app@999", hosts: "1.1.1.1,1.1.1.2", command: "redeploy" } @@ -147,10 +147,10 @@ class CliMainTest < CliTestCase test "redeploy with skip_push" do invoke_options = { "config_file" => "test/fixtures/deploy_simple.yml", "version" => "999", "skip_hooks" => false } - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:build:pull", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:healthcheck:perform", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:stale_containers", [], invoke_options) - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:boot", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:build:pull", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:healthcheck:perform", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:stale_containers", [], invoke_options) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:boot", [], invoke_options) run_command("redeploy", "--skip_push").tap do |output| assert_match /Pull app image/, output @@ -161,7 +161,7 @@ class CliMainTest < CliTestCase test "rollback bad version" do Thread.report_on_exception = false - run_command("details") # Preheat MRSK const + run_command("details") # Preheat Kamal const run_command("rollback", "nonsense").tap do |output| assert_match /docker container ls --all --filter name=\^app-web-nonsense\$ --quiet/, output @@ -185,7 +185,7 @@ class CliMainTest < CliTestCase .returns("running").at_least_once # health check end - Mrsk::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) + Kamal::Commands::Hook.any_instance.stubs(:hook_exists?).returns(true) hook_variables = { version: 123, service_version: "app@123", hosts: "1.1.1.1,1.1.1.2,1.1.1.3,1.1.1.4", command: "rollback" } run_command("rollback", "123", config_file: "deploy_with_accessories").tap do |output| @@ -199,9 +199,9 @@ class CliMainTest < CliTestCase end test "rollback without old version" do - Mrsk::Cli::Main.any_instance.stubs(:container_available?).returns(true) + Kamal::Cli::Main.any_instance.stubs(:container_available?).returns(true) - Mrsk::Utils::HealthcheckPoller.stubs(:sleep) + Kamal::Utils::HealthcheckPoller.stubs(:sleep) SSHKit::Backend::Abstract.any_instance.expects(:capture_with_info) .with(:docker, :container, :ls, "--filter", "name=^app-web-123$", "--quiet", raise_on_non_zero_exit: false) @@ -221,16 +221,16 @@ class CliMainTest < CliTestCase end test "details" do - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:traefik:details") - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:app:details") - Mrsk::Cli::Main.any_instance.expects(:invoke).with("mrsk:cli:accessory:details", [ "all" ]) + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:traefik:details") + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:app:details") + Kamal::Cli::Main.any_instance.expects(:invoke).with("kamal:cli:accessory:details", [ "all" ]) run_command("details") end test "audit" do run_command("audit").tap do |output| - assert_match /tail -n 50 mrsk-app-audit.log on 1.1.1.1/, output + assert_match /tail -n 50 kamal-app-audit.log on 1.1.1.1/, output assert_match /App Host: 1.1.1.1/, output end end @@ -305,10 +305,10 @@ class CliMainTest < CliTestCase run_command("init", "--bundle").tap do |output| assert_match /Created configuration file in config\/deploy.yml/, output assert_match /Created \.env file/, output - assert_match /Adding MRSK to Gemfile and bundle/, output - assert_match /bundle add mrsk/, output - assert_match /bundle binstubs mrsk/, output - assert_match /Created binstub file in bin\/mrsk/, output + assert_match /Adding Kamal to Gemfile and bundle/, output + assert_match /bundle add kamal/, output + assert_match /bundle binstubs kamal/, output + assert_match /Created binstub file in bin\/kamal/, output end end @@ -321,7 +321,7 @@ class CliMainTest < CliTestCase run_command("init", "--bundle").tap do |output| assert_match /Config file already exists in config\/deploy.yml \(remove first to create a new one\)/, output - assert_match /Binstub already exists in bin\/mrsk \(remove first to create a new one\)/, output + assert_match /Binstub already exists in bin\/kamal \(remove first to create a new one\)/, output end end @@ -364,12 +364,12 @@ class CliMainTest < CliTestCase end test "version" do - version = stdouted { Mrsk::Cli::Main.new.version } - assert_equal Mrsk::VERSION, version + version = stdouted { Kamal::Cli::Main.new.version } + assert_equal Kamal::VERSION, version end private def run_command(*command, config_file: "deploy_simple") - stdouted { Mrsk::Cli::Main.start([*command, "-c", "test/fixtures/#{config_file}.yml"]) } + stdouted { Kamal::Cli::Main.start([*command, "-c", "test/fixtures/#{config_file}.yml"]) } end end diff --git a/test/cli/prune_test.rb b/test/cli/prune_test.rb index fdf6c66fb..c43fba7a2 100644 --- a/test/cli/prune_test.rb +++ b/test/cli/prune_test.rb @@ -2,8 +2,8 @@ class CliPruneTest < CliTestCase test "all" do - Mrsk::Cli::Prune.any_instance.expects(:containers) - Mrsk::Cli::Prune.any_instance.expects(:images) + Kamal::Cli::Prune.any_instance.expects(:containers) + Kamal::Cli::Prune.any_instance.expects(:images) run_command("all") end @@ -23,6 +23,6 @@ class CliPruneTest < CliTestCase private def run_command(*command) - stdouted { Mrsk::Cli::Prune.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + stdouted { Kamal::Cli::Prune.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } end end diff --git a/test/cli/registry_test.rb b/test/cli/registry_test.rb index 0647f8737..ebd8000aa 100644 --- a/test/cli/registry_test.rb +++ b/test/cli/registry_test.rb @@ -16,6 +16,6 @@ class CliRegistryTest < CliTestCase private def run_command(*command) - stdouted { Mrsk::Cli::Registry.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + stdouted { Kamal::Cli::Registry.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } end end diff --git a/test/cli/server_test.rb b/test/cli/server_test.rb index bf3886cc8..377f6cff9 100644 --- a/test/cli/server_test.rb +++ b/test/cli/server_test.rb @@ -30,6 +30,6 @@ class CliServerTest < CliTestCase private def run_command(*command) - stdouted { Mrsk::Cli::Server.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + stdouted { Kamal::Cli::Server.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } end end diff --git a/test/cli/traefik_test.rb b/test/cli/traefik_test.rb index aaad75d79..d5023230c 100644 --- a/test/cli/traefik_test.rb +++ b/test/cli/traefik_test.rb @@ -4,17 +4,17 @@ class CliTraefikTest < CliTestCase test "boot" do run_command("boot").tap do |output| assert_match "docker login", output - assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{Mrsk::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=\"DEBUG\"", output + assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{Kamal::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=\"DEBUG\"", output end end test "reboot" do - Mrsk::Commands::Registry.any_instance.expects(:login).twice + Kamal::Commands::Registry.any_instance.expects(:login).twice run_command("reboot").tap do |output| assert_match "docker container stop traefik", output assert_match "docker container prune --force --filter label=org.opencontainers.image.title=Traefik", output - assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{Mrsk::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=\"DEBUG\"", output + assert_match "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{Kamal::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=\"DEBUG\"", output end end @@ -37,8 +37,8 @@ class CliTraefikTest < CliTestCase end test "restart" do - Mrsk::Cli::Traefik.any_instance.expects(:stop) - Mrsk::Cli::Traefik.any_instance.expects(:start) + Kamal::Cli::Traefik.any_instance.expects(:stop) + Kamal::Cli::Traefik.any_instance.expects(:start) run_command("restart") end @@ -68,9 +68,9 @@ class CliTraefikTest < CliTestCase end test "remove" do - Mrsk::Cli::Traefik.any_instance.expects(:stop) - Mrsk::Cli::Traefik.any_instance.expects(:remove_container) - Mrsk::Cli::Traefik.any_instance.expects(:remove_image) + Kamal::Cli::Traefik.any_instance.expects(:stop) + Kamal::Cli::Traefik.any_instance.expects(:remove_container) + Kamal::Cli::Traefik.any_instance.expects(:remove_image) run_command("remove") end @@ -89,6 +89,6 @@ class CliTraefikTest < CliTestCase private def run_command(*command) - stdouted { Mrsk::Cli::Traefik.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } + stdouted { Kamal::Cli::Traefik.start([*command, "-c", "test/fixtures/deploy_with_accessories.yml"]) } end end diff --git a/test/commander_test.rb b/test/commander_test.rb index 246650a95..4b6dee7c0 100644 --- a/test/commander_test.rb +++ b/test/commander_test.rb @@ -6,74 +6,74 @@ class CommanderTest < ActiveSupport::TestCase end test "lazy configuration" do - assert_equal Mrsk::Configuration, @mrsk.config.class + assert_equal Kamal::Configuration, @kamal.config.class end test "overwriting hosts" do - assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts + assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @kamal.hosts - @mrsk.specific_hosts = [ "1.1.1.1", "1.1.1.2" ] - assert_equal [ "1.1.1.1", "1.1.1.2" ], @mrsk.hosts + @kamal.specific_hosts = [ "1.1.1.1", "1.1.1.2" ] + assert_equal [ "1.1.1.1", "1.1.1.2" ], @kamal.hosts end test "filtering hosts by filtering roles" do - assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts + assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @kamal.hosts - @mrsk.specific_roles = [ "web" ] - assert_equal [ "1.1.1.1", "1.1.1.2" ], @mrsk.hosts + @kamal.specific_roles = [ "web" ] + assert_equal [ "1.1.1.1", "1.1.1.2" ], @kamal.hosts end test "filtering roles" do - assert_equal [ "web", "workers" ], @mrsk.roles.map(&:name) + assert_equal [ "web", "workers" ], @kamal.roles.map(&:name) - @mrsk.specific_roles = [ "workers" ] - assert_equal [ "workers" ], @mrsk.roles.map(&:name) + @kamal.specific_roles = [ "workers" ] + assert_equal [ "workers" ], @kamal.roles.map(&:name) end test "filtering roles by filtering hosts" do - assert_equal [ "web", "workers" ], @mrsk.roles.map(&:name) + assert_equal [ "web", "workers" ], @kamal.roles.map(&:name) - @mrsk.specific_hosts = [ "1.1.1.3" ] - assert_equal [ "workers" ], @mrsk.roles.map(&:name) + @kamal.specific_hosts = [ "1.1.1.3" ] + assert_equal [ "workers" ], @kamal.roles.map(&:name) end test "overwriting hosts with primary" do - assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @mrsk.hosts + assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3", "1.1.1.4" ], @kamal.hosts - @mrsk.specific_primary! - assert_equal [ "1.1.1.1" ], @mrsk.hosts + @kamal.specific_primary! + assert_equal [ "1.1.1.1" ], @kamal.hosts end test "primary_host with specific hosts via role" do - @mrsk.specific_roles = "workers" - assert_equal "1.1.1.3", @mrsk.primary_host + @kamal.specific_roles = "workers" + assert_equal "1.1.1.3", @kamal.primary_host end test "roles_on" do - assert_equal [ "web" ], @mrsk.roles_on("1.1.1.1") - assert_equal [ "workers" ], @mrsk.roles_on("1.1.1.3") + assert_equal [ "web" ], @kamal.roles_on("1.1.1.1") + assert_equal [ "workers" ], @kamal.roles_on("1.1.1.3") end test "default group strategy" do - assert_empty @mrsk.boot_strategy + assert_empty @kamal.boot_strategy end test "specific limit group strategy" do configure_with(:deploy_with_boot_strategy) - assert_equal({ in: :groups, limit: 3, wait: 2 }, @mrsk.boot_strategy) + assert_equal({ in: :groups, limit: 3, wait: 2 }, @kamal.boot_strategy) end test "percentage-based group strategy" do configure_with(:deploy_with_percentage_boot_strategy) - assert_equal({ in: :groups, limit: 1, wait: 2 }, @mrsk.boot_strategy) + assert_equal({ in: :groups, limit: 1, wait: 2 }, @kamal.boot_strategy) end private def configure_with(variant) - @mrsk = Mrsk::Commander.new.tap do |mrsk| - mrsk.configure config_file: Pathname.new(File.expand_path("fixtures/#{variant}.yml", __dir__)) + @kamal = Kamal::Commander.new.tap do |kamal| + kamal.configure config_file: Pathname.new(File.expand_path("fixtures/#{variant}.yml", __dir__)) end end end diff --git a/test/commands/accessory_test.rb b/test/commands/accessory_test.rb index a7931a90f..89279ccc7 100644 --- a/test/commands/accessory_test.rb +++ b/test/commands/accessory_test.rb @@ -146,6 +146,6 @@ class CommandsAccessoryTest < ActiveSupport::TestCase private def new_command(accessory) - Mrsk::Commands::Accessory.new(Mrsk::Configuration.new(@config), name: accessory) + Kamal::Commands::Accessory.new(Kamal::Configuration.new(@config), name: accessory) end end diff --git a/test/commands/app_test.rb b/test/commands/app_test.rb index 0451f53b7..69060afe9 100644 --- a/test/commands/app_test.rb +++ b/test/commands/app_test.rb @@ -13,13 +13,13 @@ class CommandsAppTest < ActiveSupport::TestCase test "run" do assert_equal \ - "docker run --detach --restart unless-stopped --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.run.join(" ") end test "run with hostname" do assert_equal \ - "docker run --detach --restart unless-stopped --name app-web-999 --hostname myhost -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker run --detach --restart unless-stopped --name app-web-999 --hostname myhost -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.run(hostname: "myhost").join(" ") end @@ -27,7 +27,7 @@ class CommandsAppTest < ActiveSupport::TestCase @config[:volumes] = ["/local/path:/container/path" ] assert_equal \ - "docker run --detach --restart unless-stopped --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --volume /local/path:/container/path --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --volume /local/path:/container/path --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.run.join(" ") end @@ -35,7 +35,7 @@ class CommandsAppTest < ActiveSupport::TestCase @config[:healthcheck] = { "path" => "/healthz" } assert_equal \ - "docker run --detach --restart unless-stopped --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/healthz || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/healthz || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.run.join(" ") end @@ -43,7 +43,7 @@ class CommandsAppTest < ActiveSupport::TestCase @config[:healthcheck] = { "cmd" => "/bin/up" } assert_equal \ - "docker run --detach --restart unless-stopped --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"/bin/up\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"/bin/up\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.run.join(" ") end @@ -51,14 +51,14 @@ class CommandsAppTest < ActiveSupport::TestCase @config[:servers] = { "web" => { "hosts" => [ "1.1.1.1" ], "healthcheck" => { "cmd" => "/bin/healthy" } } } assert_equal \ - "docker run --detach --restart unless-stopped --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"/bin/healthy\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"/bin/healthy\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.run.join(" ") end test "run with custom options" do @config[:servers] = { "web" => [ "1.1.1.1" ], "jobs" => { "hosts" => [ "1.1.1.2" ], "cmd" => "bin/jobs", "options" => { "mount" => "somewhere", "cap-add" => true } } } assert_equal \ - "docker run --detach --restart unless-stopped --name app-jobs-999 -e MRSK_CONTAINER_NAME=\"app-jobs-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"jobs\" --mount \"somewhere\" --cap-add dhh/app:999 bin/jobs", + "docker run --detach --restart unless-stopped --name app-jobs-999 -e KAMAL_CONTAINER_NAME=\"app-jobs-999\" -e RAILS_MASTER_KEY=\"456\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"jobs\" --mount \"somewhere\" --cap-add dhh/app:999 bin/jobs", new_command(role: "jobs").run.join(" ") end @@ -66,7 +66,7 @@ class CommandsAppTest < ActiveSupport::TestCase @config[:logging] = { "driver" => "local", "options" => { "max-size" => "100m", "max-file" => "3" } } assert_equal \ - "docker run --detach --restart unless-stopped --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-driver \"local\" --log-opt max-size=\"100m\" --log-opt max-file=\"3\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-driver \"local\" --log-opt max-size=\"100m\" --log-opt max-file=\"3\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.run.join(" ") end @@ -85,13 +85,13 @@ class CommandsAppTest < ActiveSupport::TestCase test "start_or_run" do assert_equal \ - "docker start app-web-999 || docker run --detach --restart unless-stopped --name app-web-999 -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker start app-web-999 || docker run --detach --restart unless-stopped --name app-web-999 -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.start_or_run.join(" ") end test "start_or_run with hostname" do assert_equal \ - "docker start app-web-999 || docker run --detach --restart unless-stopped --name app-web-999 --hostname myhost -e MRSK_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", + "docker start app-web-999 || docker run --detach --restart unless-stopped --name app-web-999 --hostname myhost -e KAMAL_CONTAINER_NAME=\"app-web-999\" -e RAILS_MASTER_KEY=\"456\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --log-opt max-size=\"10m\" --label service=\"app\" --label role=\"web\" --label traefik.http.services.app-web.loadbalancer.server.scheme=\"http\" --label traefik.http.routers.app-web.rule=\"PathPrefix(\\`/\\`)\" --label traefik.http.middlewares.app-web-retry.retry.attempts=\"5\" --label traefik.http.middlewares.app-web-retry.retry.initialinterval=\"500ms\" --label traefik.http.routers.app-web.middlewares=\"app-web-retry@docker\" dhh/app:999", new_command.start_or_run(hostname: "myhost").join(" ") end @@ -336,6 +336,6 @@ class CommandsAppTest < ActiveSupport::TestCase private def new_command(role: "web") - Mrsk::Commands::App.new(Mrsk::Configuration.new(@config, destination: @destination, version: "999"), role: role) + Kamal::Commands::App.new(Kamal::Configuration.new(@config, destination: @destination, version: "999"), role: role) end end diff --git a/test/commands/auditor_test.rb b/test/commands/auditor_test.rb index 1a1b03e53..1ea061fba 100644 --- a/test/commands/auditor_test.rb +++ b/test/commands/auditor_test.rb @@ -21,7 +21,7 @@ class CommandsAuditorTest < ActiveSupport::TestCase :echo, "[#{@recorded_at}] [#{@performer}]", "app removed container", - ">>", "mrsk-app-audit.log" + ">>", "kamal-app-audit.log" ], @auditor.record("app removed container") end @@ -31,7 +31,7 @@ class CommandsAuditorTest < ActiveSupport::TestCase :echo, "[#{@recorded_at}] [#{@performer}] [staging]", "app removed container", - ">>", "mrsk-app-staging-audit.log" + ">>", "kamal-app-staging-audit.log" ], auditor.record("app removed container") end end @@ -42,7 +42,7 @@ class CommandsAuditorTest < ActiveSupport::TestCase :echo, "[#{@recorded_at}] [#{@performer}] [web]", "app removed container", - ">>", "mrsk-app-audit.log" + ">>", "kamal-app-audit.log" ], auditor.record("app removed container") end end @@ -52,13 +52,13 @@ class CommandsAuditorTest < ActiveSupport::TestCase :echo, "[#{@recorded_at}] [#{@performer}] [value]", "app removed container", - ">>", "mrsk-app-audit.log" + ">>", "kamal-app-audit.log" ], @auditor.record("app removed container", detail: "value") end private def new_command(destination: nil, **details) - Mrsk::Commands::Auditor.new(Mrsk::Configuration.new(@config, destination: destination, version: "123"), **details) + Kamal::Commands::Auditor.new(Kamal::Configuration.new(@config, destination: destination, version: "123"), **details) end end diff --git a/test/commands/builder_test.rb b/test/commands/builder_test.rb index f385d1270..1cc5939b1 100644 --- a/test/commands/builder_test.rb +++ b/test/commands/builder_test.rb @@ -9,7 +9,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase builder = new_builder_command(builder: { "cache" => { "type" => "gha" }}) assert_equal "multiarch", builder.name assert_equal \ - "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .", + "docker buildx build --push --platform linux/amd64,linux/arm64 --builder kamal-app-multiarch -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .", builder.push.join(" ") end @@ -33,7 +33,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase builder = new_builder_command(builder: { "local" => { }, "remote" => { }, "cache" => { "type" => "gha" } }) assert_equal "multiarch/remote", builder.name assert_equal \ - "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch-remote -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .", + "docker buildx build --push --platform linux/amd64,linux/arm64 --builder kamal-app-multiarch-remote -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .", builder.push.join(" ") end @@ -41,7 +41,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase builder = new_builder_command(builder: { "remote" => { "arch" => "amd64" }, "cache" => { "type" => "gha" } }) assert_equal "native/remote", builder.name assert_equal \ - "docker buildx build --push --platform linux/amd64 --builder mrsk-app-native-remote -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .", + "docker buildx build --push --platform linux/amd64 --builder kamal-app-native-remote -t dhh/app:123 -t dhh/app:latest --cache-to type=gha --cache-from type=gha --label service=\"app\" --file Dockerfile .", builder.push.join(" ") end @@ -70,7 +70,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase test "missing dockerfile" do Pathname.any_instance.expects(:exist?).returns(false).once builder = new_builder_command(builder: { "dockerfile" => "Dockerfile.xyz" }) - assert_raises(Mrsk::Commands::Builder::Base::BuilderError) do + assert_raises(Kamal::Commands::Builder::Base::BuilderError) do builder.target.build_options.join(" ") end end @@ -78,7 +78,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase test "build context" do builder = new_builder_command(builder: { "context" => ".." }) assert_equal \ - "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile ..", + "docker buildx build --push --platform linux/amd64,linux/arm64 --builder kamal-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --file Dockerfile ..", builder.push.join(" ") end @@ -92,7 +92,7 @@ class CommandsBuilderTest < ActiveSupport::TestCase test "multiarch push with build args" do builder = new_builder_command(builder: { "args" => { "a" => 1, "b" => 2 } }) assert_equal \ - "docker buildx build --push --platform linux/amd64,linux/arm64 --builder mrsk-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --build-arg a=\"1\" --build-arg b=\"2\" --file Dockerfile .", + "docker buildx build --push --platform linux/amd64,linux/arm64 --builder kamal-app-multiarch -t dhh/app:123 -t dhh/app:latest --label service=\"app\" --build-arg a=\"1\" --build-arg b=\"2\" --file Dockerfile .", builder.push.join(" ") end @@ -105,6 +105,6 @@ class CommandsBuilderTest < ActiveSupport::TestCase private def new_builder_command(additional_config = {}) - Mrsk::Commands::Builder.new(Mrsk::Configuration.new(@config.merge(additional_config), version: "123")) + Kamal::Commands::Builder.new(Kamal::Configuration.new(@config.merge(additional_config), version: "123")) end end diff --git a/test/commands/docker_test.rb b/test/commands/docker_test.rb index 71d1d798d..1433f32f7 100644 --- a/test/commands/docker_test.rb +++ b/test/commands/docker_test.rb @@ -5,7 +5,7 @@ class CommandsDockerTest < ActiveSupport::TestCase @config = { service: "app", image: "dhh/app", registry: { "username" => "dhh", "password" => "secret" }, servers: [ "1.1.1.1" ] } - @docker = Mrsk::Commands::Docker.new(Mrsk::Configuration.new(@config)) + @docker = Kamal::Commands::Docker.new(Kamal::Configuration.new(@config)) end test "install" do diff --git a/test/commands/healthcheck_test.rb b/test/commands/healthcheck_test.rb index 4bf46ac00..4fad7830a 100644 --- a/test/commands/healthcheck_test.rb +++ b/test/commands/healthcheck_test.rb @@ -10,7 +10,7 @@ class CommandsHealthcheckTest < ActiveSupport::TestCase test "run" do assert_equal \ - "docker run --detach --name healthcheck-app-123 --publish 3999:3000 --label service=healthcheck-app -e MRSK_CONTAINER_NAME=\"healthcheck-app\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" dhh/app:123", + "docker run --detach --name healthcheck-app-123 --publish 3999:3000 --label service=healthcheck-app -e KAMAL_CONTAINER_NAME=\"healthcheck-app\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" dhh/app:123", new_command.run.join(" ") end @@ -18,7 +18,7 @@ class CommandsHealthcheckTest < ActiveSupport::TestCase @config[:healthcheck] = { "port" => 3001 } assert_equal \ - "docker run --detach --name healthcheck-app-123 --publish 3999:3001 --label service=healthcheck-app -e MRSK_CONTAINER_NAME=\"healthcheck-app\" --health-cmd \"curl -f http://localhost:3001/up || exit 1\" --health-interval \"1s\" dhh/app:123", + "docker run --detach --name healthcheck-app-123 --publish 3999:3001 --label service=healthcheck-app -e KAMAL_CONTAINER_NAME=\"healthcheck-app\" --health-cmd \"curl -f http://localhost:3001/up || exit 1\" --health-interval \"1s\" dhh/app:123", new_command.run.join(" ") end @@ -26,7 +26,7 @@ class CommandsHealthcheckTest < ActiveSupport::TestCase @destination = "staging" assert_equal \ - "docker run --detach --name healthcheck-app-staging-123 --publish 3999:3000 --label service=healthcheck-app-staging -e MRSK_CONTAINER_NAME=\"healthcheck-app-staging\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" dhh/app:123", + "docker run --detach --name healthcheck-app-staging-123 --publish 3999:3000 --label service=healthcheck-app-staging -e KAMAL_CONTAINER_NAME=\"healthcheck-app-staging\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" dhh/app:123", new_command.run.join(" ") end @@ -34,14 +34,14 @@ class CommandsHealthcheckTest < ActiveSupport::TestCase @config[:healthcheck] = { "cmd" => "/bin/up" } assert_equal \ - "docker run --detach --name healthcheck-app-123 --publish 3999:3000 --label service=healthcheck-app -e MRSK_CONTAINER_NAME=\"healthcheck-app\" --health-cmd \"/bin/up\" --health-interval \"1s\" dhh/app:123", + "docker run --detach --name healthcheck-app-123 --publish 3999:3000 --label service=healthcheck-app -e KAMAL_CONTAINER_NAME=\"healthcheck-app\" --health-cmd \"/bin/up\" --health-interval \"1s\" dhh/app:123", new_command.run.join(" ") end test "run with custom options" do @config[:servers] = { "web" => { "hosts" => [ "1.1.1.1" ], "options" => { "mount" => "somewhere" } } } assert_equal \ - "docker run --detach --name healthcheck-app-123 --publish 3999:3000 --label service=healthcheck-app -e MRSK_CONTAINER_NAME=\"healthcheck-app\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --mount \"somewhere\" dhh/app:123", + "docker run --detach --name healthcheck-app-123 --publish 3999:3000 --label service=healthcheck-app -e KAMAL_CONTAINER_NAME=\"healthcheck-app\" --health-cmd \"curl -f http://localhost:3000/up || exit 1\" --health-interval \"1s\" --mount \"somewhere\" dhh/app:123", new_command.run.join(" ") end @@ -101,6 +101,6 @@ class CommandsHealthcheckTest < ActiveSupport::TestCase private def new_command - Mrsk::Commands::Healthcheck.new(Mrsk::Configuration.new(@config, destination: @destination, version: "123")) + Kamal::Commands::Healthcheck.new(Kamal::Configuration.new(@config, destination: @destination, version: "123")) end end diff --git a/test/commands/hook_test.rb b/test/commands/hook_test.rb index 726ef7d8f..688c71563 100644 --- a/test/commands/hook_test.rb +++ b/test/commands/hook_test.rb @@ -17,12 +17,12 @@ class CommandsHookTest < ActiveSupport::TestCase test "run" do assert_equal [ - ".mrsk/hooks/foo", + ".kamal/hooks/foo", { env: { - "MRSK_RECORDED_AT" => @recorded_at, - "MRSK_PERFORMER" => @performer, - "MRSK_VERSION" => "123", - "MRSK_SERVICE_VERSION" => "app@123" } } + "KAMAL_RECORDED_AT" => @recorded_at, + "KAMAL_PERFORMER" => @performer, + "KAMAL_VERSION" => "123", + "KAMAL_SERVICE_VERSION" => "app@123" } } ], new_command.run("foo") end @@ -30,15 +30,15 @@ class CommandsHookTest < ActiveSupport::TestCase assert_equal [ "custom/hooks/path/foo", { env: { - "MRSK_RECORDED_AT" => @recorded_at, - "MRSK_PERFORMER" => @performer, - "MRSK_VERSION" => "123", - "MRSK_SERVICE_VERSION" => "app@123" } } + "KAMAL_RECORDED_AT" => @recorded_at, + "KAMAL_PERFORMER" => @performer, + "KAMAL_VERSION" => "123", + "KAMAL_SERVICE_VERSION" => "app@123" } } ], new_command(hooks_path: "custom/hooks/path").run("foo") end private def new_command(**extra_config) - Mrsk::Commands::Hook.new(Mrsk::Configuration.new(@config.merge(**extra_config), version: "123")) + Kamal::Commands::Hook.new(Kamal::Configuration.new(@config.merge(**extra_config), version: "123")) end end diff --git a/test/commands/lock_test.rb b/test/commands/lock_test.rb index f32aac078..4ed4fe1f0 100644 --- a/test/commands/lock_test.rb +++ b/test/commands/lock_test.rb @@ -10,24 +10,24 @@ class CommandsLockTest < ActiveSupport::TestCase test "status" do assert_equal \ - "stat mrsk_lock-app > /dev/null && cat mrsk_lock-app/details | base64 -d", + "stat kamal_lock-app > /dev/null && cat kamal_lock-app/details | base64 -d", new_command.status.join(" ") end test "acquire" do assert_match \ - /mkdir mrsk_lock-app && echo ".*" > mrsk_lock-app\/details/m, + /mkdir kamal_lock-app && echo ".*" > kamal_lock-app\/details/m, new_command.acquire("Hello", "123").join(" ") end test "release" do assert_match \ - "rm mrsk_lock-app/details && rm -r mrsk_lock-app", + "rm kamal_lock-app/details && rm -r kamal_lock-app", new_command.release.join(" ") end private def new_command - Mrsk::Commands::Lock.new(Mrsk::Configuration.new(@config, version: "123")) + Kamal::Commands::Lock.new(Kamal::Configuration.new(@config, version: "123")) end end diff --git a/test/commands/prune_test.rb b/test/commands/prune_test.rb index 7fbb24a5a..939497cd8 100644 --- a/test/commands/prune_test.rb +++ b/test/commands/prune_test.rb @@ -28,6 +28,6 @@ class CommandsPruneTest < ActiveSupport::TestCase private def new_command - Mrsk::Commands::Prune.new(Mrsk::Configuration.new(@config, version: "123")) + Kamal::Commands::Prune.new(Kamal::Configuration.new(@config, version: "123")) end end diff --git a/test/commands/registry_test.rb b/test/commands/registry_test.rb index 0d62de8ec..83b73a7ba 100755 --- a/test/commands/registry_test.rb +++ b/test/commands/registry_test.rb @@ -10,7 +10,7 @@ class CommandsRegistryTest < ActiveSupport::TestCase }, servers: [ "1.1.1.1" ] } - @registry = Mrsk::Commands::Registry.new Mrsk::Configuration.new(@config) + @registry = Kamal::Commands::Registry.new Kamal::Configuration.new(@config) end test "registry login" do @@ -20,25 +20,25 @@ class CommandsRegistryTest < ActiveSupport::TestCase end test "registry login with ENV password" do - ENV["MRSK_REGISTRY_PASSWORD"] = "more-secret" - @config[:registry]["password"] = [ "MRSK_REGISTRY_PASSWORD" ] + ENV["KAMAL_REGISTRY_PASSWORD"] = "more-secret" + @config[:registry]["password"] = [ "KAMAL_REGISTRY_PASSWORD" ] assert_equal \ "docker login hub.docker.com -u dhh -p more-secret", @registry.login.join(" ") ensure - ENV.delete("MRSK_REGISTRY_PASSWORD") + ENV.delete("KAMAL_REGISTRY_PASSWORD") end test "registry login with ENV username" do - ENV["MRSK_REGISTRY_USERNAME"] = "also-secret" - @config[:registry]["username"] = [ "MRSK_REGISTRY_USERNAME" ] + ENV["KAMAL_REGISTRY_USERNAME"] = "also-secret" + @config[:registry]["username"] = [ "KAMAL_REGISTRY_USERNAME" ] assert_equal \ "docker login hub.docker.com -u also-secret -p secret", @registry.login.join(" ") ensure - ENV.delete("MRSK_REGISTRY_USERNAME") + ENV.delete("KAMAL_REGISTRY_USERNAME") end test "registry logout" do diff --git a/test/commands/traefik_test.rb b/test/commands/traefik_test.rb index 82d62d57b..368e166f1 100644 --- a/test/commands/traefik_test.rb +++ b/test/commands/traefik_test.rb @@ -86,7 +86,7 @@ class CommandsTraefikTest < ActiveSupport::TestCase @config.delete(:traefik) assert_equal \ - "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{Mrsk::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=\"DEBUG\"", + "docker run --name traefik --detach --restart unless-stopped --publish 80:80 --volume /var/run/docker.sock:/var/run/docker.sock --log-opt max-size=\"10m\" #{Kamal::Commands::Traefik::DEFAULT_IMAGE} --providers.docker --log.level=\"DEBUG\"", new_command.run.join(" ") end @@ -174,6 +174,6 @@ class CommandsTraefikTest < ActiveSupport::TestCase private def new_command - Mrsk::Commands::Traefik.new(Mrsk::Configuration.new(@config, version: "123")) + Kamal::Commands::Traefik.new(Kamal::Configuration.new(@config, version: "123")) end end diff --git a/test/configuration/accessory_test.rb b/test/configuration/accessory_test.rb index 35cc5dfe7..4f9623044 100644 --- a/test/configuration/accessory_test.rb +++ b/test/configuration/accessory_test.rb @@ -66,7 +66,7 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase } } - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) end test "service name" do @@ -87,7 +87,7 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase test "missing host" do @deploy[:accessories]["mysql"]["host"] = nil - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) assert_raises(ArgumentError) do @config.accessory(:mysql).hosts @@ -97,7 +97,7 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase test "setting host, hosts and roles" do @deploy[:accessories]["mysql"]["hosts"] = true @deploy[:accessories]["mysql"]["roles"] = true - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) exception = assert_raises(ArgumentError) do @config.accessory(:mysql).hosts @@ -114,8 +114,8 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase ENV["MYSQL_ROOT_PASSWORD"] = "secret123" @config.accessory(:mysql).env_args.tap do |env_args| - assert_equal ["-e", "MYSQL_ROOT_PASSWORD=\"secret123\"", "-e", "MYSQL_ROOT_HOST=\"%\""], Mrsk::Utils.unredacted(env_args) - assert_equal ["-e", "MYSQL_ROOT_PASSWORD=[REDACTED]", "-e", "MYSQL_ROOT_HOST=\"%\""], Mrsk::Utils.redacted(env_args) + assert_equal ["-e", "MYSQL_ROOT_PASSWORD=\"secret123\"", "-e", "MYSQL_ROOT_HOST=\"%\""], Kamal::Utils.unredacted(env_args) + assert_equal ["-e", "MYSQL_ROOT_PASSWORD=[REDACTED]", "-e", "MYSQL_ROOT_HOST=\"%\""], Kamal::Utils.redacted(env_args) end ensure ENV["MYSQL_ROOT_PASSWORD"] = nil @@ -132,7 +132,7 @@ class ConfigurationAccessoryTest < ActiveSupport::TestCase test "dynamic file expansion" do @deploy[:accessories]["mysql"]["files"] << "test/fixtures/files/structure.sql.erb:/docker-entrypoint-initdb.d/structure.sql" - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) assert_match "This was dynamically expanded", @config.accessory(:mysql).files.keys[2].read assert_match "%", @config.accessory(:mysql).files.keys[2].read diff --git a/test/configuration/builder_test.rb b/test/configuration/builder_test.rb index 08c6d483c..da30d9156 100644 --- a/test/configuration/builder_test.rb +++ b/test/configuration/builder_test.rb @@ -7,7 +7,7 @@ class ConfigurationBuilderTest < ActiveSupport::TestCase servers: [ "1.1.1.1" ] } - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) @deploy_with_builder_option = { service: "app", image: "dhh/app", registry: { "username" => "dhh", "password" => "secret" }, @@ -15,7 +15,7 @@ class ConfigurationBuilderTest < ActiveSupport::TestCase builder: {} } - @config_with_builder_option = Mrsk::Configuration.new(@deploy_with_builder_option) + @config_with_builder_option = Kamal::Configuration.new(@deploy_with_builder_option) end test "multiarch?" do @@ -103,10 +103,10 @@ class ConfigurationBuilderTest < ActiveSupport::TestCase end test "setting registry cache with image" do - @deploy_with_builder_option[:builder] = { "cache" => { "type" => "registry", "image" => "mrsk", "options" => "mode=max" } } + @deploy_with_builder_option[:builder] = { "cache" => { "type" => "registry", "image" => "kamal", "options" => "mode=max" } } - assert_equal "type=registry,ref=mrsk", @config_with_builder_option.builder.cache_from - assert_equal "type=registry,mode=max,ref=mrsk", @config_with_builder_option.builder.cache_to + assert_equal "type=registry,ref=kamal", @config_with_builder_option.builder.cache_from + assert_equal "type=registry,mode=max,ref=kamal", @config_with_builder_option.builder.cache_to end test "args" do diff --git a/test/configuration/role_test.rb b/test/configuration/role_test.rb index 7708bd9d4..c554965d9 100644 --- a/test/configuration/role_test.rb +++ b/test/configuration/role_test.rb @@ -8,7 +8,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase env: { "REDIS_URL" => "redis://x/y" } } - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) @deploy_with_roles = @deploy.dup.merge({ servers: { @@ -24,7 +24,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase } }) - @config_with_roles = Mrsk::Configuration.new(@deploy_with_roles) + @config_with_roles = Kamal::Configuration.new(@deploy_with_roles) end test "hosts" do @@ -62,7 +62,7 @@ class ConfigurationRoleTest < ActiveSupport::TestCase end test "default traefik label on non-web role" do - config = Mrsk::Configuration.new(@deploy_with_roles.tap { |c| + config = Kamal::Configuration.new(@deploy_with_roles.tap { |c| c[:servers]["beta"] = { "traefik" => "true", "hosts" => [ "1.1.1.5" ] } }) @@ -98,8 +98,8 @@ class ConfigurationRoleTest < ActiveSupport::TestCase ENV["DB_PASSWORD"] = "secret&\"123" @config_with_roles.role(:workers).env_args.tap do |env_args| - assert_equal ["-e", "REDIS_PASSWORD=\"secret456\"", "-e", "DB_PASSWORD=\"secret&\\\"123\"", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Mrsk::Utils.unredacted(env_args) - assert_equal ["-e", "REDIS_PASSWORD=[REDACTED]", "-e", "DB_PASSWORD=[REDACTED]", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Mrsk::Utils.redacted(env_args) + assert_equal ["-e", "REDIS_PASSWORD=\"secret456\"", "-e", "DB_PASSWORD=\"secret&\\\"123\"", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Kamal::Utils.unredacted(env_args) + assert_equal ["-e", "REDIS_PASSWORD=[REDACTED]", "-e", "DB_PASSWORD=[REDACTED]", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Kamal::Utils.redacted(env_args) end ensure ENV["REDIS_PASSWORD"] = nil @@ -120,8 +120,8 @@ class ConfigurationRoleTest < ActiveSupport::TestCase ENV["DB_PASSWORD"] = "secret123" @config_with_roles.role(:workers).env_args.tap do |env_args| - assert_equal ["-e", "DB_PASSWORD=\"secret123\"", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Mrsk::Utils.unredacted(env_args) - assert_equal ["-e", "DB_PASSWORD=[REDACTED]", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Mrsk::Utils.redacted(env_args) + assert_equal ["-e", "DB_PASSWORD=\"secret123\"", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Kamal::Utils.unredacted(env_args) + assert_equal ["-e", "DB_PASSWORD=[REDACTED]", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Kamal::Utils.redacted(env_args) end ensure ENV["DB_PASSWORD"] = nil @@ -140,8 +140,8 @@ class ConfigurationRoleTest < ActiveSupport::TestCase ENV["REDIS_PASSWORD"] = "secret456" @config_with_roles.role(:workers).env_args.tap do |env_args| - assert_equal ["-e", "REDIS_PASSWORD=\"secret456\"", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Mrsk::Utils.unredacted(env_args) - assert_equal ["-e", "REDIS_PASSWORD=[REDACTED]", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Mrsk::Utils.redacted(env_args) + assert_equal ["-e", "REDIS_PASSWORD=\"secret456\"", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Kamal::Utils.unredacted(env_args) + assert_equal ["-e", "REDIS_PASSWORD=[REDACTED]", "-e", "REDIS_URL=\"redis://a/b\"", "-e", "WEB_CONCURRENCY=\"4\""], Kamal::Utils.redacted(env_args) end ensure ENV["REDIS_PASSWORD"] = nil diff --git a/test/configuration/ssh_test.rb b/test/configuration/ssh_test.rb index d85abfd6f..cb3d5f5c9 100644 --- a/test/configuration/ssh_test.rb +++ b/test/configuration/ssh_test.rb @@ -10,27 +10,27 @@ class ConfigurationSshTest < ActiveSupport::TestCase volumes: ["/local/path:/container/path"] } - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) end test "ssh options" do assert_equal "root", @config.ssh.options[:user] - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "user" => "app" }) }) + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "user" => "app" }) }) assert_equal "app", config.ssh.options[:user] assert_equal 4, config.ssh.options[:logger].level - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "log_level" => "debug" }) }) + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "log_level" => "debug" }) }) assert_equal 0, config.ssh.options[:logger].level end test "ssh options with proxy host" do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "proxy" => "1.2.3.4" }) }) + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "proxy" => "1.2.3.4" }) }) assert_equal "root@1.2.3.4", config.ssh.options[:proxy].jump_proxies end test "ssh options with proxy host and user" do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "proxy" => "app@1.2.3.4" }) }) + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(ssh: { "proxy" => "app@1.2.3.4" }) }) assert_equal "app@1.2.3.4", config.ssh.options[:proxy].jump_proxies end end diff --git a/test/configuration/sshkit_test.rb b/test/configuration/sshkit_test.rb index 36c0e05dc..4ebb9dca0 100644 --- a/test/configuration/sshkit_test.rb +++ b/test/configuration/sshkit_test.rb @@ -10,18 +10,18 @@ class ConfigurationSshkitTest < ActiveSupport::TestCase volumes: ["/local/path:/container/path"] } - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) end test "sshkit max concurrent starts" do assert_equal 30, @config.sshkit.max_concurrent_starts - @config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(sshkit: { "max_concurrent_starts" => 50 }) }) + @config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(sshkit: { "max_concurrent_starts" => 50 }) }) assert_equal 50, @config.sshkit.max_concurrent_starts end test "sshkit pool idle timeout" do assert_equal 900, @config.sshkit.pool_idle_timeout - @config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(sshkit: { "pool_idle_timeout" => 600 }) }) + @config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(sshkit: { "pool_idle_timeout" => 600 }) }) assert_equal 600, @config.sshkit.pool_idle_timeout end end diff --git a/test/configuration_test.rb b/test/configuration_test.rb index 2167c0438..425407e57 100644 --- a/test/configuration_test.rb +++ b/test/configuration_test.rb @@ -13,12 +13,12 @@ class ConfigurationTest < ActiveSupport::TestCase volumes: ["/local/path:/container/path"] } - @config = Mrsk::Configuration.new(@deploy) + @config = Kamal::Configuration.new(@deploy) @deploy_with_roles = @deploy.dup.merge({ servers: { "web" => [ "1.1.1.1", "1.1.1.2" ], "workers" => { "hosts" => [ "1.1.1.1", "1.1.1.3" ] } } }) - @config_with_roles = Mrsk::Configuration.new(@deploy_with_roles) + @config_with_roles = Kamal::Configuration.new(@deploy_with_roles) end teardown do @@ -29,7 +29,7 @@ class ConfigurationTest < ActiveSupport::TestCase %i[ service image registry ].each do |key| test "#{key} config required" do assert_raise(ArgumentError) do - Mrsk::Configuration.new @deploy.tap { _1.delete key } + Kamal::Configuration.new @deploy.tap { _1.delete key } end end end @@ -37,7 +37,7 @@ class ConfigurationTest < ActiveSupport::TestCase %w[ username password ].each do |key| test "registry #{key} required" do assert_raise(ArgumentError) do - Mrsk::Configuration.new @deploy.tap { _1[:registry].delete key } + Kamal::Configuration.new @deploy.tap { _1[:registry].delete key } end end end @@ -67,7 +67,7 @@ class ConfigurationTest < ActiveSupport::TestCase assert_equal [ "1.1.1.1", "1.1.1.2" ], @config_with_roles.traefik_hosts @deploy_with_roles[:servers]["workers"]["traefik"] = true - config = Mrsk::Configuration.new(@deploy_with_roles) + config = Kamal::Configuration.new(@deploy_with_roles) assert_equal [ "1.1.1.1", "1.1.1.2", "1.1.1.3" ], config.traefik_hosts end @@ -84,7 +84,7 @@ class ConfigurationTest < ActiveSupport::TestCase ENV.delete("VERSION") @config.expects(:`).with("git rev-parse HEAD").returns("git-version") - Mrsk::Utils.expects(:uncommitted_changes).returns("") + Kamal::Utils.expects(:uncommitted_changes).returns("") assert_equal "git-version", @config.version end @@ -92,7 +92,7 @@ class ConfigurationTest < ActiveSupport::TestCase ENV.delete("VERSION") @config.expects(:`).with("git rev-parse HEAD").returns("git-version") - Mrsk::Utils.expects(:uncommitted_changes).returns("M file\n") + Kamal::Utils.expects(:uncommitted_changes).returns("M file\n") assert_match /^git-version_uncommitted_[0-9a-f]{16}$/, @config.version end @@ -109,14 +109,14 @@ class ConfigurationTest < ActiveSupport::TestCase test "repository" do assert_equal "dhh/app", @config.repository - config = Mrsk::Configuration.new(@deploy.tap { |c| c[:registry].merge!({ "server" => "ghcr.io" }) }) + config = Kamal::Configuration.new(@deploy.tap { |c| c[:registry].merge!({ "server" => "ghcr.io" }) }) assert_equal "ghcr.io/dhh/app", config.repository end test "absolute image" do assert_equal "dhh/app:missing", @config.absolute_image - config = Mrsk::Configuration.new(@deploy.tap { |c| c[:registry].merge!({ "server" => "ghcr.io" }) }) + config = Kamal::Configuration.new(@deploy.tap { |c| c[:registry].merge!({ "server" => "ghcr.io" }) }) assert_equal "ghcr.io/dhh/app:missing", config.absolute_image end @@ -131,18 +131,18 @@ class ConfigurationTest < ActiveSupport::TestCase test "env args with clear and secrets" do ENV["PASSWORD"] = "secret123" - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!({ env: { "clear" => { "PORT" => "3000" }, "secret" => [ "PASSWORD" ] } }) }) - assert_equal [ "-e", "PASSWORD=\"secret123\"", "-e", "PORT=\"3000\"" ], Mrsk::Utils.unredacted(config.env_args) - assert_equal [ "-e", "PASSWORD=[REDACTED]", "-e", "PORT=\"3000\"" ], Mrsk::Utils.redacted(config.env_args) + assert_equal [ "-e", "PASSWORD=\"secret123\"", "-e", "PORT=\"3000\"" ], Kamal::Utils.unredacted(config.env_args) + assert_equal [ "-e", "PASSWORD=[REDACTED]", "-e", "PORT=\"3000\"" ], Kamal::Utils.redacted(config.env_args) ensure ENV["PASSWORD"] = nil end test "env args with only clear" do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!({ env: { "clear" => { "PORT" => "3000" } } }) }) @@ -152,19 +152,19 @@ class ConfigurationTest < ActiveSupport::TestCase test "env args with only secrets" do ENV["PASSWORD"] = "secret123" - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!({ env: { "secret" => [ "PASSWORD" ] } }) }) - assert_equal [ "-e", "PASSWORD=\"secret123\"" ], Mrsk::Utils.unredacted(config.env_args) - assert_equal [ "-e", "PASSWORD=[REDACTED]" ], Mrsk::Utils.redacted(config.env_args) + assert_equal [ "-e", "PASSWORD=\"secret123\"" ], Kamal::Utils.unredacted(config.env_args) + assert_equal [ "-e", "PASSWORD=[REDACTED]" ], Kamal::Utils.redacted(config.env_args) ensure ENV["PASSWORD"] = nil end test "env args with missing secret" do assert_raises(KeyError) do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!({ + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!({ env: { "secret" => [ "PASSWORD" ] } }) }).ensure_env_available end @@ -178,32 +178,32 @@ class ConfigurationTest < ActiveSupport::TestCase test "hosts required for all roles" do # Empty server list for implied web role assert_raises(ArgumentError) do - Mrsk::Configuration.new @deploy.merge(servers: []) + Kamal::Configuration.new @deploy.merge(servers: []) end # Empty server list assert_raises(ArgumentError) do - Mrsk::Configuration.new @deploy.merge(servers: { "web" => [] }) + Kamal::Configuration.new @deploy.merge(servers: { "web" => [] }) end # Missing hosts key assert_raises(ArgumentError) do - Mrsk::Configuration.new @deploy.merge(servers: { "web" => {} }) + Kamal::Configuration.new @deploy.merge(servers: { "web" => {} }) end # Empty hosts list assert_raises(ArgumentError) do - Mrsk::Configuration.new @deploy.merge(servers: { "web" => { "hosts" => [] } }) + Kamal::Configuration.new @deploy.merge(servers: { "web" => { "hosts" => [] } }) end # Nil hosts assert_raises(ArgumentError) do - Mrsk::Configuration.new @deploy.merge(servers: { "web" => { "hosts" => nil } }) + Kamal::Configuration.new @deploy.merge(servers: { "web" => { "hosts" => nil } }) end # One role with hosts, one without assert_raises(ArgumentError) do - Mrsk::Configuration.new @deploy.merge(servers: { "web" => %w[ web ], "workers" => { "hosts" => %w[ ] } }) + Kamal::Configuration.new @deploy.merge(servers: { "web" => %w[ web ], "workers" => { "hosts" => %w[ ] } }) end end @@ -216,27 +216,27 @@ class ConfigurationTest < ActiveSupport::TestCase end test "logging args with configured options" do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(logging: { "options" => { "max-size" => "100m", "max-file" => 5 } }) }) + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(logging: { "options" => { "max-size" => "100m", "max-file" => 5 } }) }) assert_equal ["--log-opt", "max-size=\"100m\"", "--log-opt", "max-file=\"5\""], @config.logging_args end test "logging args with configured driver and options" do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(logging: { "driver" => "local", "options" => { "max-size" => "100m", "max-file" => 5 } }) }) + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(logging: { "driver" => "local", "options" => { "max-size" => "100m", "max-file" => 5 } }) }) assert_equal ["--log-driver", "\"local\"", "--log-opt", "max-size=\"100m\"", "--log-opt", "max-file=\"5\""], @config.logging_args end test "erb evaluation of yml config" do - config = Mrsk::Configuration.create_from config_file: Pathname.new(File.expand_path("fixtures/deploy.erb.yml", __dir__)) + config = Kamal::Configuration.create_from config_file: Pathname.new(File.expand_path("fixtures/deploy.erb.yml", __dir__)) assert_equal "my-user", config.registry["username"] end test "destination yml config merge" do dest_config_file = Pathname.new(File.expand_path("fixtures/deploy_for_dest.yml", __dir__)) - config = Mrsk::Configuration.create_from config_file: dest_config_file, destination: "world" + config = Kamal::Configuration.create_from config_file: dest_config_file, destination: "world" assert_equal "1.1.1.1", config.all_hosts.first - config = Mrsk::Configuration.create_from config_file: dest_config_file, destination: "mars" + config = Kamal::Configuration.create_from config_file: dest_config_file, destination: "mars" assert_equal "1.1.1.3", config.all_hosts.first end @@ -244,7 +244,7 @@ class ConfigurationTest < ActiveSupport::TestCase dest_config_file = Pathname.new(File.expand_path("fixtures/deploy_for_dest.yml", __dir__)) assert_raises(RuntimeError) do - config = Mrsk::Configuration.create_from config_file: dest_config_file, destination: "missing" + config = Kamal::Configuration.create_from config_file: dest_config_file, destination: "missing" end end @@ -269,18 +269,18 @@ class ConfigurationTest < ActiveSupport::TestCase end test "min version is lower" do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(minimum_version: "0.0.1") }) + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(minimum_version: "0.0.1") }) assert_equal "0.0.1", config.minimum_version end test "min version is equal" do - config = Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(minimum_version: Mrsk::VERSION) }) - assert_equal Mrsk::VERSION, config.minimum_version + config = Kamal::Configuration.new(@deploy.tap { |c| c.merge!(minimum_version: Kamal::VERSION) }) + assert_equal Kamal::VERSION, config.minimum_version end test "min version is higher" do assert_raises(ArgumentError) do - Mrsk::Configuration.new(@deploy.tap { |c| c.merge!(minimum_version: "10000.0.0") }) + Kamal::Configuration.new(@deploy.tap { |c| c.merge!(minimum_version: "10000.0.0") }) end end end diff --git a/test/integration/accessory_test.rb b/test/integration/accessory_test.rb index 151861a0a..102c02d39 100644 --- a/test/integration/accessory_test.rb +++ b/test/integration/accessory_test.rb @@ -2,22 +2,22 @@ class AccessoryTest < IntegrationTest test "boot, stop, start, restart, logs, remove" do - mrsk :accessory, :boot, :busybox + kamal :accessory, :boot, :busybox assert_accessory_running :busybox - mrsk :accessory, :stop, :busybox + kamal :accessory, :stop, :busybox assert_accessory_not_running :busybox - mrsk :accessory, :start, :busybox + kamal :accessory, :start, :busybox assert_accessory_running :busybox - mrsk :accessory, :restart, :busybox + kamal :accessory, :restart, :busybox assert_accessory_running :busybox - logs = mrsk :accessory, :logs, :busybox, capture: true + logs = kamal :accessory, :logs, :busybox, capture: true assert_match /Starting busybox.../, logs - mrsk :accessory, :remove, :busybox, "-y" + kamal :accessory, :remove, :busybox, "-y" assert_accessory_not_running :busybox end @@ -31,6 +31,6 @@ def assert_accessory_not_running(name) end def accessory_details(name) - mrsk :accessory, :details, name, capture: true + kamal :accessory, :details, name, capture: true end end diff --git a/test/integration/app_test.rb b/test/integration/app_test.rb index 13ba65dc8..1f5c5b1ce 100644 --- a/test/integration/app_test.rb +++ b/test/integration/app_test.rb @@ -2,52 +2,52 @@ class AppTest < IntegrationTest test "stop, start, boot, logs, images, containers, exec, remove" do - mrsk :deploy + kamal :deploy assert_app_is_up - mrsk :app, :stop + kamal :app, :stop # traefik is up and returns 404s when it can't match a route assert_app_not_found - mrsk :app, :start + kamal :app, :start - # mrsk app start does not wait + # kamal app start does not wait wait_for_app_to_be_up - mrsk :app, :boot + kamal :app, :boot wait_for_app_to_be_up - logs = mrsk :app, :logs, capture: true + logs = kamal :app, :logs, capture: true assert_match /App Host: vm1/, logs assert_match /App Host: vm2/, logs assert_match /GET \/ HTTP\/1.1/, logs - images = mrsk :app, :images, capture: true + images = kamal :app, :images, capture: true assert_match /App Host: vm1/, images assert_match /App Host: vm2/, images assert_match /registry:4443\/app\s+#{latest_app_version}/, images assert_match /registry:4443\/app\s+latest/, images - containers = mrsk :app, :containers, capture: true + containers = kamal :app, :containers, capture: true assert_match /App Host: vm1/, containers assert_match /App Host: vm2/, containers assert_match /registry:4443\/app:#{latest_app_version}/, containers assert_match /registry:4443\/app:latest/, containers - exec_output = mrsk :app, :exec, :ps, capture: true + exec_output = kamal :app, :exec, :ps, capture: true assert_match /App Host: vm1/, exec_output assert_match /App Host: vm2/, exec_output assert_match /1 root 0:\d\d ps/, exec_output - exec_output = mrsk :app, :exec, "--reuse", :ps, capture: true + exec_output = kamal :app, :exec, "--reuse", :ps, capture: true assert_match /App Host: vm1/, exec_output assert_match /App Host: vm2/, exec_output assert_match /1 root 0:\d\d nginx/, exec_output - mrsk :app, :remove + kamal :app, :remove # traefik is up and returns 404s when it can't match a route assert_app_not_found diff --git a/test/integration/docker-compose.yml b/test/integration/docker-compose.yml index 0a92d427a..01b5152f7 100644 --- a/test/integration/docker-compose.yml +++ b/test/integration/docker-compose.yml @@ -1,5 +1,5 @@ version: "3.7" -name: "mrsk-test" +name: "kamal-test" volumes: shared: @@ -20,7 +20,7 @@ services: environment: - TEST_ID=${TEST_ID} volumes: - - ../..:/mrsk + - ../..:/kamal - shared:/shared - registry:/registry - deployer_bundle:/usr/local/bundle/ diff --git a/test/integration/docker/deployer/setup.sh b/test/integration/docker/deployer/setup.sh index 3a0a8da7b..50af91bf4 100755 --- a/test/integration/docker/deployer/setup.sh +++ b/test/integration/docker/deployer/setup.sh @@ -1,7 +1,7 @@ #!/bin/bash -install_mrsk() { - cd /mrsk && gem build mrsk.gemspec -o /tmp/mrsk.gem && gem install /tmp/mrsk.gem +install_kamal() { + cd /kamal && gem build kamal.gemspec -o /tmp/kamal.gem && gem install /tmp/kamal.gem } # Push the images to a persistent volume on the registry container @@ -17,7 +17,7 @@ push_image_to_registry_4443() { fi } -install_mrsk +install_kamal push_image_to_registry_4443 nginx 1-alpine-slim push_image_to_registry_4443 traefik v2.9 push_image_to_registry_4443 busybox 1.36.0 diff --git a/test/integration/integration_test.rb b/test/integration/integration_test.rb index 00e73d62b..b352b7140 100644 --- a/test/integration/integration_test.rb +++ b/test/integration/integration_test.rb @@ -38,8 +38,8 @@ def deployer_exec(*commands, **options) docker_compose("exec deployer #{commands.join(" ")}", **options) end - def mrsk(*commands, **options) - deployer_exec(:mrsk, *commands, **options) + def kamal(*commands, **options) + deployer_exec(:kamal, *commands, **options) end def assert_app_is_down @@ -101,7 +101,7 @@ def assert_200(response) code = response.code if code != "200" puts "Got response code #{code}, here are the traefik logs:" - mrsk :traefik, :logs + kamal :traefik, :logs puts "And here are the load balancer logs" docker_compose :logs, :load_balancer puts "Tried to get the response code again and got #{app_response.code}" @@ -129,7 +129,7 @@ def debug_response_code(app_response, expected_code) code = app_response.code if code != expected_code puts "Got response code #{code}, here are the traefik logs:" - mrsk :traefik, :logs + kamal :traefik, :logs puts "And here are the load balancer logs" docker_compose :logs, :load_balancer puts "Tried to get the response code again and got #{app_response.code}" diff --git a/test/integration/lock_test.rb b/test/integration/lock_test.rb index 2740a2494..22795b378 100644 --- a/test/integration/lock_test.rb +++ b/test/integration/lock_test.rb @@ -2,17 +2,17 @@ class LockTest < IntegrationTest test "acquire, release, status" do - mrsk :lock, :acquire, "-m 'Integration Tests'" + kamal :lock, :acquire, "-m 'Integration Tests'" - status = mrsk :lock, :status, capture: true + status = kamal :lock, :status, capture: true assert_match /Locked by: Deployer at .*\nVersion: #{latest_app_version}\nMessage: Integration Tests/m, status - error = mrsk :deploy, capture: true, raise_on_error: false + error = kamal :deploy, capture: true, raise_on_error: false assert_match /Deploy lock found/m, error - mrsk :lock, :release + kamal :lock, :release - status = mrsk :lock, :status, capture: true + status = kamal :lock, :status, capture: true assert_match /There is no deploy lock/m, status end end diff --git a/test/integration/main_test.rb b/test/integration/main_test.rb index c215e0578..59d73e8f6 100644 --- a/test/integration/main_test.rb +++ b/test/integration/main_test.rb @@ -6,21 +6,21 @@ class MainTest < IntegrationTest assert_app_is_down - mrsk :deploy + kamal :deploy assert_app_is_up version: first_version assert_hooks_ran "pre-connect", "pre-build", "pre-deploy", "post-deploy" second_version = update_app_rev - mrsk :redeploy + kamal :redeploy assert_app_is_up version: second_version assert_hooks_ran "pre-connect", "pre-build", "pre-deploy", "post-deploy" - mrsk :rollback, first_version + kamal :rollback, first_version assert_hooks_ran "pre-connect", "pre-deploy", "post-deploy" assert_app_is_up version: first_version - details = mrsk :details, capture: true + details = kamal :details, capture: true assert_match /Traefik Host: vm1/, details assert_match /Traefik Host: vm2/, details assert_match /App Host: vm1/, details @@ -28,18 +28,18 @@ class MainTest < IntegrationTest assert_match /traefik:v2.9/, details assert_match /registry:4443\/app:#{first_version}/, details - audit = mrsk :audit, capture: true + audit = kamal :audit, capture: true assert_match /Booted app version #{first_version}.*Booted app version #{second_version}.*Booted app version #{first_version}.*/m, audit end test "envify" do - mrsk :envify + kamal :envify assert_equal "SECRET_TOKEN=1234", deployer_exec("cat .env", capture: true) end test "config" do - config = YAML.load(mrsk(:config, capture: true)) + config = YAML.load(kamal(:config, capture: true)) version = latest_app_version assert_equal [ "web" ], config[:roles] diff --git a/test/integration/traefik_test.rb b/test/integration/traefik_test.rb index 9ff1b9dc2..45a08e228 100644 --- a/test/integration/traefik_test.rb +++ b/test/integration/traefik_test.rb @@ -2,36 +2,36 @@ class TraefikTest < IntegrationTest test "boot, reboot, stop, start, restart, logs, remove" do - mrsk :traefik, :boot + kamal :traefik, :boot assert_traefik_running - mrsk :traefik, :reboot + kamal :traefik, :reboot assert_traefik_running - mrsk :traefik, :boot + kamal :traefik, :boot assert_traefik_running # Check booting when booted doesn't raise an error - mrsk :traefik, :stop + kamal :traefik, :stop assert_traefik_not_running # Check booting when stopped works - mrsk :traefik, :boot + kamal :traefik, :boot assert_traefik_running - mrsk :traefik, :stop + kamal :traefik, :stop assert_traefik_not_running - mrsk :traefik, :start + kamal :traefik, :start assert_traefik_running - mrsk :traefik, :restart + kamal :traefik, :restart assert_traefik_running - logs = mrsk :traefik, :logs, capture: true + logs = kamal :traefik, :logs, capture: true assert_match /Traefik version [\d.]+ built on/, logs - mrsk :traefik, :remove + kamal :traefik, :remove assert_traefik_not_running end @@ -45,6 +45,6 @@ def assert_traefik_not_running end def traefik_details - mrsk :traefik, :details, capture: true + kamal :traefik, :details, capture: true end end diff --git a/test/test_helper.rb b/test/test_helper.rb index f23f0a92b..5f7a25c4c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -6,7 +6,7 @@ require "mocha/minitest" # using #stubs that can alter returns require "minitest/autorun" # using #stub that take args require "sshkit" -require "mrsk" +require "kamal" ActiveSupport::LogSubscriber.logger = ActiveSupport::Logger.new(STDOUT) if ENV["VERBOSE"] diff --git a/test/utils_test.rb b/test/utils_test.rb index 0c42d72b9..3cc4af766 100644 --- a/test/utils_test.rb +++ b/test/utils_test.rb @@ -3,72 +3,72 @@ class UtilsTest < ActiveSupport::TestCase test "argumentize" do assert_equal [ "--label", "foo=\"\\`bar\\`\"", "--label", "baz=\"qux\"", "--label", :quux ], \ - Mrsk::Utils.argumentize("--label", { foo: "`bar`", baz: "qux", quux: nil }) + Kamal::Utils.argumentize("--label", { foo: "`bar`", baz: "qux", quux: nil }) end test "argumentize with redacted" do assert_kind_of SSHKit::Redaction, \ - Mrsk::Utils.argumentize("--label", { foo: "bar" }, sensitive: true).last + Kamal::Utils.argumentize("--label", { foo: "bar" }, sensitive: true).last end test "argumentize_env_with_secrets" do ENV.expects(:fetch).with("FOO").returns("secret") - args = Mrsk::Utils.argumentize_env_with_secrets({ "secret" => [ "FOO" ], "clear" => { BAZ: "qux" } }) + args = Kamal::Utils.argumentize_env_with_secrets({ "secret" => [ "FOO" ], "clear" => { BAZ: "qux" } }) - assert_equal [ "-e", "FOO=[REDACTED]", "-e", "BAZ=\"qux\"" ], Mrsk::Utils.redacted(args) - assert_equal [ "-e", "FOO=\"secret\"", "-e", "BAZ=\"qux\"" ], Mrsk::Utils.unredacted(args) + assert_equal [ "-e", "FOO=[REDACTED]", "-e", "BAZ=\"qux\"" ], Kamal::Utils.redacted(args) + assert_equal [ "-e", "FOO=\"secret\"", "-e", "BAZ=\"qux\"" ], Kamal::Utils.unredacted(args) end test "optionize" do assert_equal [ "--foo", "\"bar\"", "--baz", "\"qux\"", "--quux" ], \ - Mrsk::Utils.optionize({ foo: "bar", baz: "qux", quux: true }) + Kamal::Utils.optionize({ foo: "bar", baz: "qux", quux: true }) end test "optionize with" do assert_equal [ "--foo=\"bar\"", "--baz=\"qux\"", "--quux" ], \ - Mrsk::Utils.optionize({ foo: "bar", baz: "qux", quux: true }, with: "=") + Kamal::Utils.optionize({ foo: "bar", baz: "qux", quux: true }, with: "=") end test "no redaction from #to_s" do - assert_equal "secret", Mrsk::Utils.sensitive("secret").to_s + assert_equal "secret", Kamal::Utils.sensitive("secret").to_s end test "redact from #inspect" do - assert_equal "[REDACTED]".inspect, Mrsk::Utils.sensitive("secret").inspect + assert_equal "[REDACTED]".inspect, Kamal::Utils.sensitive("secret").inspect end test "redact from SSHKit output" do - assert_kind_of SSHKit::Redaction, Mrsk::Utils.sensitive("secret") + assert_kind_of SSHKit::Redaction, Kamal::Utils.sensitive("secret") end test "redact from YAML output" do - assert_equal "--- ! '[REDACTED]'\n", YAML.dump(Mrsk::Utils.sensitive("secret")) + assert_equal "--- ! '[REDACTED]'\n", YAML.dump(Kamal::Utils.sensitive("secret")) end test "escape_shell_value" do - assert_equal "\"foo\"", Mrsk::Utils.escape_shell_value("foo") - assert_equal "\"\\`foo\\`\"", Mrsk::Utils.escape_shell_value("`foo`") + assert_equal "\"foo\"", Kamal::Utils.escape_shell_value("foo") + assert_equal "\"\\`foo\\`\"", Kamal::Utils.escape_shell_value("`foo`") - assert_equal "\"${PWD}\"", Mrsk::Utils.escape_shell_value("${PWD}") - assert_equal "\"${cat /etc/hostname}\"", Mrsk::Utils.escape_shell_value("${cat /etc/hostname}") - assert_equal "\"\\${PWD]\"", Mrsk::Utils.escape_shell_value("${PWD]") - assert_equal "\"\\$(PWD)\"", Mrsk::Utils.escape_shell_value("$(PWD)") - assert_equal "\"\\$PWD\"", Mrsk::Utils.escape_shell_value("$PWD") + assert_equal "\"${PWD}\"", Kamal::Utils.escape_shell_value("${PWD}") + assert_equal "\"${cat /etc/hostname}\"", Kamal::Utils.escape_shell_value("${cat /etc/hostname}") + assert_equal "\"\\${PWD]\"", Kamal::Utils.escape_shell_value("${PWD]") + assert_equal "\"\\$(PWD)\"", Kamal::Utils.escape_shell_value("$(PWD)") + assert_equal "\"\\$PWD\"", Kamal::Utils.escape_shell_value("$PWD") assert_equal "\"^(https?://)www.example.com/(.*)\\$\"", - Mrsk::Utils.escape_shell_value("^(https?://)www.example.com/(.*)$") + Kamal::Utils.escape_shell_value("^(https?://)www.example.com/(.*)$") assert_equal "\"https://example.com/\\$2\"", - Mrsk::Utils.escape_shell_value("https://example.com/$2") + Kamal::Utils.escape_shell_value("https://example.com/$2") end test "uncommitted changes exist" do - Mrsk::Utils.expects(:`).with("git status --porcelain").returns("M file\n") - assert_equal "M file", Mrsk::Utils.uncommitted_changes + Kamal::Utils.expects(:`).with("git status --porcelain").returns("M file\n") + assert_equal "M file", Kamal::Utils.uncommitted_changes end test "uncommitted changes do not exist" do - Mrsk::Utils.expects(:`).with("git status --porcelain").returns("") - assert_equal "", Mrsk::Utils.uncommitted_changes + Kamal::Utils.expects(:`).with("git status --porcelain").returns("") + assert_equal "", Kamal::Utils.uncommitted_changes end end