bring back farmware repos.
This commit is contained in:
parent
ff37b75093
commit
43deb4aaf3
|
@ -38,6 +38,9 @@ config :farmbot, :behaviour,
|
|||
firmware_handler: Farmbot.Firmware.StubHandler,
|
||||
http_adapter: Farmbot.HTTP.HTTPoisonAdapter
|
||||
|
||||
config :farmbot, :farmware,
|
||||
first_part_farmware_manifest_url: "https://raw.githubusercontent.com/FarmBot-Labs/farmware_manifests/master/manifest.json"
|
||||
|
||||
case target do
|
||||
"host" ->
|
||||
import_config("host/#{env}.exs")
|
||||
|
|
|
@ -121,9 +121,10 @@ defmodule Farmbot.Bootstrap.Supervisor do
|
|||
ConfigStorage.update_config_value(:string, "authorization", "last_shutdown_reason", nil)
|
||||
|
||||
children = [
|
||||
supervisor(Farmbot.BotState.Supervisor, [token, [name: Farmbot.BotState.Supervisor]]),
|
||||
supervisor(Farmbot.HTTP.Supervisor, [token, [name: Farmbot.HTTP.Supervisor]]),
|
||||
supervisor(Farmbot.Repo.Supervisor, [token, [name: Farmbot.Repo.Supervisor]])
|
||||
supervisor(Farmbot.BotState.Supervisor, []),
|
||||
supervisor(Farmbot.HTTP.Supervisor, []),
|
||||
supervisor(Farmbot.Repo.Supervisor, []),
|
||||
supervisor(Farmbot.Farmware.Supervisor, [])
|
||||
]
|
||||
|
||||
opts = [strategy: :one_for_all]
|
||||
|
|
|
@ -22,8 +22,9 @@ defmodule Farmbot.BotState do
|
|||
user_env: %{},
|
||||
process_info: %{}
|
||||
|
||||
def start_link(opts) do
|
||||
GenStage.start_link(__MODULE__, [], opts)
|
||||
@doc false
|
||||
def start_link() do
|
||||
GenStage.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init([]) do
|
||||
|
|
|
@ -2,15 +2,16 @@ defmodule Farmbot.BotState.Supervisor do
|
|||
@moduledoc false
|
||||
use Supervisor
|
||||
|
||||
def start_link(token, opts) do
|
||||
Supervisor.start_link(__MODULE__, token, opts)
|
||||
@doc false
|
||||
def start_link() do
|
||||
Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init(_token) do
|
||||
def init([]) do
|
||||
children = [
|
||||
supervisor(Farmbot.Firmware.Supervisor, [[name: Farmbot.Firmware.Supervisor]]),
|
||||
worker(Farmbot.BotState, [[name: Farmbot.BotState]]),
|
||||
worker(Farmbot.Logger, [[name: Farmbot.Logger]]),
|
||||
supervisor(Farmbot.Firmware.Supervisor, []),
|
||||
worker(Farmbot.BotState, []),
|
||||
worker(Farmbot.Logger, []),
|
||||
supervisor(Farmbot.BotState.Transport.Supervisor, [])
|
||||
]
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@ defmodule Farmbot.BotState.Transport.GenMQTT do
|
|||
require Logger
|
||||
alias Farmbot.BotState.Transport.GenMQTT.Client
|
||||
|
||||
@doc "Start the MQTT Transport."
|
||||
def start_link(opts) do
|
||||
GenStage.start_link(__MODULE__, [], opts)
|
||||
@doc false
|
||||
def start_link do
|
||||
GenStage.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init([]) do
|
||||
|
|
|
@ -4,13 +4,13 @@ defmodule Farmbot.BotState.Transport.Supervisor do
|
|||
use Supervisor
|
||||
|
||||
def start_link do
|
||||
Supervisor.start_link(__MODULE__, [], name: __MODULE__)
|
||||
Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init([]) do
|
||||
:farmbot
|
||||
|> Application.get_env(:transport)
|
||||
|> Enum.map(&worker(&1, [[name: &1]]))
|
||||
|> Enum.map(&worker(&1, []))
|
||||
|> supervise(strategy: :one_for_one)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,8 +3,7 @@ defmodule Farmbot.Farmware do
|
|||
|
||||
defmodule Meta do
|
||||
@moduledoc "Metadata about a Farmware."
|
||||
|
||||
defstruct [:author,:language,:description]
|
||||
defstruct [:author, :language,:description]
|
||||
end
|
||||
|
||||
defstruct [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
defmodule Farmbot.Farmware.Installer do
|
||||
@moduledoc "Install Farmware from a URL."
|
||||
@moduledoc "Handles installation of Farmwares and syncronization of Farmware Repos."
|
||||
|
||||
alias Farmbot.Farmware
|
||||
alias Farmbot.Farmware.Installer.Repository
|
||||
|
@ -25,18 +25,36 @@ defmodule Farmbot.Farmware.Installer do
|
|||
install_path(name, version)
|
||||
end
|
||||
|
||||
@doc "Enable a repo from a url."
|
||||
def enable_repo(url_or_repo_struct, acc \\ [])
|
||||
@doc "Add a repository to the database."
|
||||
def add_repo(url) do
|
||||
with {:ok, %{status_code: code, body: body}} when code > 199 and code < 300 <- HTTP.get(url),
|
||||
{:ok, json_map} <- Poison.decode(body),
|
||||
{:ok, manifest} <- Repository.new(json_map)
|
||||
do
|
||||
Repository.changeset(manifest, %{url: url}) |> Farmbot.System.ConfigStorage.insert()
|
||||
end
|
||||
rescue
|
||||
e in Sqlite.DbConnection.Error ->
|
||||
st = System.stacktrace
|
||||
if String.contains?(Exception.message(e), "UNIQUE constraint") do
|
||||
{:error, :repo_already_exists}
|
||||
else
|
||||
reraise e, st
|
||||
end
|
||||
end
|
||||
|
||||
def enable_repo(url, _acc) when is_binary(url) do
|
||||
Logger.info "Enabling repo from: #{url}"
|
||||
@doc "Enable a repo from a url or struct."
|
||||
def sync_repo(url_or_repo_struct, acc \\ [])
|
||||
|
||||
def sync_repo(url, _acc) when is_binary(url) do
|
||||
Logger.info "Syncing repo from: #{url}"
|
||||
with {:ok, %{status_code: code, body: body}} when code > 199 and code < 300 <- HTTP.get(url),
|
||||
{:ok, json_map} <- Poison.decode(body),
|
||||
{:ok, repo} <- Repository.new(json_map)
|
||||
do
|
||||
case enable_repo(repo, []) do
|
||||
case sync_repo(repo, []) do
|
||||
[] ->
|
||||
Logger.info "Successfully enabled repo."
|
||||
Logger.info "Successfully synced repo."
|
||||
:ok
|
||||
list_of_entries ->
|
||||
Logger.error "Failed to enable some entries: #{inspect list_of_entries}"
|
||||
|
@ -45,14 +63,14 @@ defmodule Farmbot.Farmware.Installer do
|
|||
end
|
||||
end
|
||||
|
||||
def enable_repo(repo = %Repository{manifests: [entry = %Repository.Entry{manifest_url: manifest_url} | entries]}, acc) do
|
||||
def sync_repo(repo = %Repository{manifests: [entry = %Repository.Entry{manifest: manifest_url} | entries]}, acc) do
|
||||
case install(manifest_url) do
|
||||
:ok -> enable_repo(%{repo | manifests: entries}, acc)
|
||||
{:error, _err} -> enable_repo(%{repo | manifests: entries}, [entry | acc])
|
||||
:ok -> sync_repo(%{repo | manifests: entries}, acc)
|
||||
{:error, _err} -> sync_repo(%{repo | manifests: entries}, [entry | acc])
|
||||
end
|
||||
end
|
||||
|
||||
def enable_repo(%Repository{manifests: []}, acc), do: acc
|
||||
def sync_repo(%Repository{manifests: []}, acc), do: acc
|
||||
|
||||
@doc "Install a farmware from a URL."
|
||||
def install(url) do
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
defmodule Farmbot.Farmware.Installer.Repository do
|
||||
@moduledoc "A Repository is a way of enabling multiple farmware's at a time."
|
||||
|
||||
defmodule Entry do
|
||||
@moduledoc "An entry in the Repository."
|
||||
defstruct [:name, :manifest_url]
|
||||
end
|
||||
|
||||
defstruct [manifests: []]
|
||||
|
||||
@doc "Turn a list into a Repo."
|
||||
def new(list, acc \\ struct(__MODULE__))
|
||||
|
||||
def new([%{"name" => name, "manifest" => mani_url} | rest], %__MODULE__{manifests: manifests} = acc) do
|
||||
entry = struct(Entry, name: name, manifest_url: mani_url)
|
||||
new(rest, %{acc | manifests: [entry | manifests]})
|
||||
end
|
||||
|
||||
def new([], acc), do: {:ok, acc}
|
||||
|
||||
end
|
4
lib/farmbot/farmware/installer/repository/entry.ex
Normal file
4
lib/farmbot/farmware/installer/repository/entry.ex
Normal file
|
@ -0,0 +1,4 @@
|
|||
defmodule Farmbot.Farmware.Installer.Repository.Entry do
|
||||
@moduledoc "An entry in the Repository."
|
||||
defstruct [:name, :manifest]
|
||||
end
|
18
lib/farmbot/farmware/installer/repository/manifest_type.ex
Normal file
18
lib/farmbot/farmware/installer/repository/manifest_type.ex
Normal file
|
@ -0,0 +1,18 @@
|
|||
defmodule Farmbot.Farmware.Installer.Repository.ManifestType do
|
||||
@moduledoc false
|
||||
@behaviour Ecto.Type
|
||||
alias Farmbot.Farmware.Installer.Repository.Entry
|
||||
|
||||
def type, do: :text
|
||||
|
||||
# try to encode as json here.
|
||||
def cast(data) do
|
||||
Poison.encode(data)
|
||||
end
|
||||
|
||||
def load(text) do
|
||||
Poison.decode(text, as: [struct(Entry)])
|
||||
end
|
||||
|
||||
def dump(data), do: cast(data)
|
||||
end
|
33
lib/farmbot/farmware/installer/repository/repository.ex
Normal file
33
lib/farmbot/farmware/installer/repository/repository.ex
Normal file
|
@ -0,0 +1,33 @@
|
|||
defmodule Farmbot.Farmware.Installer.Repository do
|
||||
@moduledoc "A Repository is a way of enabling multiple farmware's at a time."
|
||||
|
||||
alias Farmbot.Farmware.Installer.Repository.{Entry, ManifestType}
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
|
||||
schema "farmware_repositories" do
|
||||
field :manifests, ManifestType
|
||||
field :url, :string
|
||||
end
|
||||
|
||||
@required_fields [:url, :manifests]
|
||||
|
||||
def changeset(%__MODULE__{} = repo, params \\ %{}) do
|
||||
repo
|
||||
|> cast(params, @required_fields)
|
||||
|> validate_required(@required_fields)
|
||||
|> unique_constraint(:url)
|
||||
end
|
||||
|
||||
@doc "Turn a list into a Repo."
|
||||
def new(list, acc \\ struct(__MODULE__))
|
||||
|
||||
def new([%{"name" => name, "manifest" => mani_url} | rest], %__MODULE__{manifests: manifests} = acc) do
|
||||
entry = struct(Entry, name: name, manifest: mani_url)
|
||||
new(rest, %{acc | manifests: [entry | manifests || []]})
|
||||
end
|
||||
|
||||
def new([], acc), do: {:ok, acc}
|
||||
|
||||
|
||||
end
|
28
lib/farmbot/farmware/installer/repository/sync_task.ex
Normal file
28
lib/farmbot/farmware/installer/repository/sync_task.ex
Normal file
|
@ -0,0 +1,28 @@
|
|||
defmodule Farmbot.Farmware.Installer.Repository.SyncTask do
|
||||
@moduledoc "Init module for installing first party farmware repo. Requires internet."
|
||||
use Task, restart: :transient
|
||||
require Logger
|
||||
alias Farmbot.System.ConfigStorage
|
||||
alias Farmbot.Farmware.Installer
|
||||
alias Farmbot.Farmware.Installer.Repository
|
||||
|
||||
@fpf_url Application.get_env(:farmbot, :farmware)[:first_part_farmware_manifest_url] || raise "First party farmware url needs to be configured"
|
||||
|
||||
@doc false
|
||||
def start_link(_) do
|
||||
Task.start_link(__MODULE__, :sync_all, [])
|
||||
end
|
||||
|
||||
def sync_all do
|
||||
Logger.debug "Syncing all repos. This may take a while."
|
||||
import Ecto.Query
|
||||
unless Farmbot.System.ConfigStorage.one(from r in Repository, where: r.url == @fpf_url) do
|
||||
Installer.add_repo(@fpf_url)
|
||||
end
|
||||
|
||||
repos = ConfigStorage.all(Repository)
|
||||
for repo <- repos do
|
||||
Installer.sync_repo(repo)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,3 +1,13 @@
|
|||
defmodule Farmbot.Farmware.Supervisor do
|
||||
@moduledoc false
|
||||
use Supervisor
|
||||
|
||||
@doc false
|
||||
def start_link do
|
||||
Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init([]) do
|
||||
Supervisor.init([Farmbot.Farmware.Installer.Repository.SyncTask], strategy: :one_for_one)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,11 +4,11 @@ defmodule Farmbot.HTTP.Supervisor do
|
|||
use Supervisor
|
||||
|
||||
@doc false
|
||||
def start_link(token, opts \\ []) do
|
||||
Supervisor.start_link(__MODULE__, token, opts)
|
||||
def start_link() do
|
||||
Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init(_token) do
|
||||
def init([]) do
|
||||
children = [
|
||||
worker(Farmbot.HTTP, [])
|
||||
]
|
||||
|
|
|
@ -3,9 +3,9 @@ defmodule Farmbot.Logger do
|
|||
use GenStage
|
||||
alias Farmbot.Log
|
||||
|
||||
@doc "Start Logging Services."
|
||||
def start_link(opts \\ []) do
|
||||
GenStage.start_link(__MODULE__, [], opts)
|
||||
@doc false
|
||||
def start_link() do
|
||||
GenStage.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init([]) do
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
defmodule Farmbot.Repo.Supervisor do
|
||||
@moduledoc "Hey!"
|
||||
@moduledoc false
|
||||
|
||||
@repos [Farmbot.Repo.A, Farmbot.Repo.B]
|
||||
|
||||
use Supervisor
|
||||
|
||||
def start_link(token, opts \\ []) do
|
||||
Supervisor.start_link(__MODULE__, token, opts)
|
||||
@doc false
|
||||
def start_link() do
|
||||
Supervisor.start_link(__MODULE__, [], [name: __MODULE__])
|
||||
end
|
||||
|
||||
def init(_token) do
|
||||
def init([]) do
|
||||
@repos
|
||||
|> Enum.map(fn repo ->
|
||||
supervisor(repo, [])
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
defmodule Farmbot.System.ConfigStorage.Migrations.AddDevicesTable do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
defmodule Farmbot.System.ConfigStorage.Migrations.AddDevicesTable do
|
||||
use Ecto.Migration
|
||||
|
||||
def change do
|
||||
create table("farmware_repositories") do
|
||||
add(:manifests, :text)
|
||||
add(:url, :string)
|
||||
end
|
||||
|
||||
create(unique_index("farmware_repositories", [:url]))
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue