Skip to content
This repository was archived by the owner on Dec 24, 2025. It is now read-only.

Commit f564479

Browse files
committed
Stop standalone applications
1 parent 9b5c392 commit f564479

7 files changed

Lines changed: 161 additions & 22 deletions

File tree

lib/makina.ex

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,3 @@
11
defmodule Makina do
2-
@moduledoc """
3-
4-
"""
5-
6-
@doc """
7-
Deploys a list of standalone application on a list of servers.
8-
9-
Standalone applications do not have dependencies among each other and therefore
10-
they are deployed as they are listed.
11-
Errors in the process will be collected and reported but those will not affect the deployment of other applications also on the same server.
12-
13-
Deployments happen sequentially server by server, application by application.
14-
"""
15-
defdelegate deploy_standalone_applications(servers, applications), to: Makina.Applications
2+
@moduledoc false
163
end

lib/makina/applications.ex

Lines changed: 83 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,104 @@ defmodule Makina.Applications do
1010
alias Makina.Docker
1111
alias Makina.IO
1212

13-
def deploy_standalone_applications(servers, applications)
13+
@doc """
14+
Deploys a list of application on a server or a list of servers
15+
16+
If a list of servers is provided the function iterates the list and
17+
connects to the server before deploying the application.
18+
Connection is established before triggering applications deployment
19+
and disconnection happens when all applications have been deployed.
20+
"""
21+
def deploy_applications(servers, applications)
1422
when is_list(servers) and is_list(applications) do
1523
for server <- servers do
1624
server = Servers.connect_to_server(server)
17-
deployment_result = deploy_applications_on_server(server, applications)
25+
deployment_result = deploy_applications(server, applications)
1826

1927
Servers.disconnect_from_server(server)
2028

2129
deployment_result
2230
end
2331
end
2432

25-
def deploy_applications_on_server(%Server{} = server, applications)
33+
def deploy_applications(%Server{} = server, applications)
2634
when is_list(applications) do
2735
for app <- applications do
28-
do_deploy_application(server, app)
36+
deploy_application(server, app)
2937
end
3038
end
3139

32-
defp do_deploy_application(%Server{} = server, %Application{} = app) do
40+
@doc """
41+
Stops all provided applications in all servers
42+
43+
If `servers` is a list then the function iterates on them and attempt to connect
44+
to the server.
45+
Servers and applications are processed sequentially.
46+
"""
47+
def stop_applications(servers, applications) when is_list(servers) and is_list(applications) do
48+
for server <- servers do
49+
server = Servers.connect_to_server(server)
50+
deployment_result = stop_applications(server, applications)
51+
52+
Servers.disconnect_from_server(server)
53+
54+
deployment_result
55+
end
56+
end
57+
58+
def stop_applications(%Server{} = server, applications) when is_list(applications) do
59+
for app <- applications do
60+
stop_application(server, app)
61+
end
62+
end
63+
64+
@doc """
65+
Deploys an application on a specific server
66+
67+
Note: The server has to have a connection at this point.
68+
"""
69+
def deploy_application(%Server{} = server, %Application{} = app) do
70+
if Server.connected?(server) do
71+
do_deploy(server, app)
72+
else
73+
connect_and_deploy(server, app)
74+
end
75+
end
76+
77+
@doc """
78+
Stops an application on a given server
79+
"""
80+
def stop_application(%Server{} = server, %Application{} = app) do
81+
if Server.connected?(server) do
82+
do_stop(server, app)
83+
else
84+
connect_and_stop(server, app)
85+
end
86+
end
87+
88+
defp do_stop(%Server{} = server, %Application{} = app) do
89+
IO.puts(" Stopping \"#{app.name}\"")
90+
91+
Docker.stop(server, app) |> SSH.execute()
92+
end
93+
94+
defp connect_and_stop(%Server{} = server, %Application{} = app) do
95+
server = Servers.connect_to_server(server)
96+
result = do_stop(server, app)
97+
Servers.disconnect_from_server(server)
98+
99+
result
100+
end
101+
102+
defp connect_and_deploy(%Server{} = server, %Application{} = app) do
103+
server = Servers.connect_to_server(server)
104+
result = do_deploy(server, app)
105+
Servers.disconnect_from_server(server)
106+
107+
result
108+
end
109+
110+
def do_deploy(%Server{} = server, %Application{} = app) do
33111
IO.puts(" Deploying \"#{app.name}\"")
34112

35113
with {:ok, _} <- maybe_login_to_registry(server, app),

lib/makina/cli/commands/standalone.ex

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ defmodule Makina.Cli.Commands.Standalone do
44
import Makina.Cli.Utils
55

66
alias Makina.IO
7+
alias Makina.Applications
78

8-
@sub_commands ~w[deploy]a
9+
@sub_commands ~w[deploy stop]a
910

1011
def name(), do: "standalone"
1112

@@ -46,7 +47,7 @@ defmodule Makina.Cli.Commands.Standalone do
4647
servers = ctx.servers
4748

4849
deployment_result =
49-
Makina.deploy_standalone_applications(servers, ctx.standalone_applications)
50+
Applications.deploy_applications(servers, ctx.standalone_applications)
5051

5152
case deployment_errors?(deployment_result) do
5253
true ->
@@ -61,6 +62,29 @@ defmodule Makina.Cli.Commands.Standalone do
6162
:ok
6263
end
6364

65+
defp sub_command(:stop, options) do
66+
ctx =
67+
makinafile(options)
68+
|> fetch_context()
69+
70+
servers = ctx.servers
71+
72+
deployment_result =
73+
Applications.stop_applications(servers, ctx.standalone_applications)
74+
75+
case deployment_errors?(deployment_result) do
76+
true ->
77+
IO.puts_error("There were errors while stopping some applications.")
78+
79+
:ok
80+
81+
false ->
82+
IO.puts_success("All applications have been stopped!")
83+
end
84+
85+
:ok
86+
end
87+
6488
defp extract_subcommand([sub_command | _rest]) do
6589
sub_command = sub_command |> String.to_atom()
6690

lib/makina/docker.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ defmodule Makina.Docker do
7575
docker(server, "network", ["inspect", name])
7676
end
7777

78+
def stop(%Server{} = server, %Application{} = app) do
79+
docker(server, "stop", [app_name(app)])
80+
end
81+
7882
defp app_name(%Application{__scope__: []} = app) do
7983
app.name
8084
end

lib/makina/models/server.ex

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,10 @@ defmodule Makina.Models.Server do
2929

3030
%__MODULE__{server | __private__: private}
3131
end
32+
33+
def connected?(%__MODULE__{__private__: %{conn_ref: nil}}), do: false
34+
35+
def connected?(%__MODULE__{__private__: %{conn_ref: conn_ref}}) do
36+
Process.alive?(conn_ref)
37+
end
3238
end

lib/makina/servers.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ defmodule Makina.Servers do
122122
reverse_proxy(ctx.proxy_config)
123123
]
124124

125-
Applications.deploy_applications_on_server(server, system_applications)
125+
Applications.deploy_applications(server, system_applications)
126126

127127
server
128128
end

test/makina/models/docker_test.exs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
defmodule Makina.Models.DockerTest do
22
use ExUnit.Case
33

4+
alias Makina.Command
45
alias Makina.Models.Server
56
alias Makina.Models.Application
67

@@ -139,6 +140,36 @@ defmodule Makina.Models.DockerTest do
139140
end
140141
end
141142

143+
describe "stop/2" do
144+
test "returns the command to stop a given container" do
145+
app = basic_app_without_scope()
146+
147+
server =
148+
Server.new(host: "example.com")
149+
|> Server.put_private(:conn_ref, self())
150+
151+
cmd = Docker.stop(server, app)
152+
153+
assert is_struct(cmd, Command)
154+
155+
assert cmd.cmd == "docker stop foo"
156+
end
157+
158+
test "returns the command to stop a given container with scopes" do
159+
app = basic_app_with_scope()
160+
161+
server =
162+
Server.new(host: "example.com")
163+
|> Server.put_private(:conn_ref, self())
164+
165+
cmd = Docker.stop(server, app)
166+
167+
assert is_struct(cmd, Command)
168+
169+
assert cmd.cmd == "docker stop makina_app_foo"
170+
end
171+
end
172+
142173
describe "login/2" do
143174
test "returns a command to login into a private registry" do
144175
server =
@@ -185,4 +216,13 @@ defmodule Makina.Models.DockerTest do
185216
assert cmd.cmd == "docker network inspect foo"
186217
end
187218
end
219+
220+
defp basic_app_without_scope() do
221+
Application.new(name: "foo")
222+
end
223+
224+
defp basic_app_with_scope() do
225+
Application.new(name: "foo")
226+
|> Application.set_private(:__scope__, ["foo", :app, :makina])
227+
end
188228
end

0 commit comments

Comments
 (0)