From ba9c61459594b1579452be40644df0e326554a10 Mon Sep 17 00:00:00 2001 From: michaeljguarino Date: Thu, 21 Mar 2024 15:54:00 -0400 Subject: [PATCH] Bump agent version and support airgapped compatibilities + deprecations (#788) --- AGENT_VERSION | 2 +- .../cd/pipelines/PipelineDetails.tsx | 23 ++--- .../deployments/compatibilities/schema.ex | 2 +- .../deployments/compatibilities/table.ex | 31 +++++-- lib/console/deployments/deprecations/table.ex | 17 +++- lib/console/deployments/static.ex | 13 +++ .../slack/service.update.json.eex | 88 ++++++++++++++----- rel/config/console.exs | 4 +- 8 files changed, 139 insertions(+), 41 deletions(-) create mode 100644 lib/console/deployments/static.ex diff --git a/AGENT_VERSION b/AGENT_VERSION index b10001ec61..93be66de36 100644 --- a/AGENT_VERSION +++ b/AGENT_VERSION @@ -1 +1 @@ -v0.4.13 \ No newline at end of file +v0.4.14 \ No newline at end of file diff --git a/assets/src/components/cd/pipelines/PipelineDetails.tsx b/assets/src/components/cd/pipelines/PipelineDetails.tsx index 09545b5ec4..6c3d8871bf 100644 --- a/assets/src/components/cd/pipelines/PipelineDetails.tsx +++ b/assets/src/components/cd/pipelines/PipelineDetails.tsx @@ -66,7 +66,7 @@ function PipelineHeading({ } const tabs = { - '': 'Split', + split: 'Split', graph: 'Graph', contexts: 'Contexts', } as const @@ -76,7 +76,7 @@ export function PipelineTabs() { const tabStateRef = useRef(null) const view = searchParams.get('view') - const tabKey = view && tabs[view] ? (view as keyof typeof tabs) : '' + const tabKey = view && tabs[view] ? (view as keyof typeof tabs) : 'graph' return ( ) + const contentContexts = ( ) - let content = ( - - ) + let content = contentGraph if (view === 'contexts') { content = ( @@ -251,8 +246,14 @@ function PipelineDetailsBase() { {contentContexts} ) - } else if (view === 'graph') { - content = contentGraph + } else if (view === 'split') { + content = ( + + ) } return ( diff --git a/lib/console/deployments/compatibilities/schema.ex b/lib/console/deployments/compatibilities/schema.ex index cecb1c80b7..faa3056b88 100644 --- a/lib/console/deployments/compatibilities/schema.ex +++ b/lib/console/deployments/compatibilities/schema.ex @@ -41,7 +41,7 @@ defmodule Console.Deployments.Compatibilities.AddOn do @type t :: %__MODULE__{versions: [%Compatibilities.Version{}]} - defstruct [:versions, :icon, :git_url, :release_url, :readme_url] + defstruct [:name, :versions, :icon, :git_url, :release_url, :readme_url] def spec() do %__MODULE__{ diff --git a/lib/console/deployments/compatibilities/table.ex b/lib/console/deployments/compatibilities/table.ex index 097dfb72ef..789d1d5739 100644 --- a/lib/console/deployments/compatibilities/table.ex +++ b/lib/console/deployments/compatibilities/table.ex @@ -1,7 +1,7 @@ defmodule Console.Deployments.Compatibilities.Table do use GenServer import Console.Deployments.Ecto.Validations, only: [clean_version: 1] - alias Console.Deployments.Compatibilities.AddOn + alias Console.Deployments.{Compatibilities.AddOn, Static} alias Console.Schema.{RuntimeService} alias ETS.KeyValueSet require Logger @@ -11,7 +11,7 @@ defmodule Console.Deployments.Compatibilities.Table do @url "/pluralsh/console/master/static/compatibilities/" defmodule State do - defstruct [:table, :url] + defstruct [:table, :url, :static] end def start_link(opt \\ :ok) do @@ -22,7 +22,7 @@ defmodule Console.Deployments.Compatibilities.Table do :timer.send_interval(@poll, :poll) send self(), :poll {:ok, table} = KeyValueSet.new(name: @table, read_concurrency: true, ordered: true) - {:ok, %State{table: table, url: Console.github_raw_url(@url)}} + {:ok, %State{table: table, url: Console.github_raw_url(@url), static: Console.conf(:airgap)}} end def fetch(%RuntimeService{name: name, version: vsn}) do @@ -38,6 +38,11 @@ defmodule Console.Deployments.Compatibilities.Table do end end + def handle_info(:poll, %State{table: table, static: true} = state) do + table = Enum.reduce(Static.compatibilities(), table, &KeyValueSet.put(&2, &1.name, &1)) + {:noreply, %{state | table: table}} + end + def handle_info(:poll, %State{table: table, url: url} = state) do with [_ | _] = addons <- fetch_manifest(url) do table = Enum.reduce(addons, table, fn name, table -> @@ -64,8 +69,24 @@ defmodule Console.Deployments.Compatibilities.Table do defp fetch_addon(url, addon) do with {:ok, %HTTPoison.Response{status_code: 200, body: body}} <- HTTPoison.get(url <> "#{addon}.yaml"), - {:ok, res} <- YamlElixir.read_from_string(body), + do: decode_addon(addon, body) + end + + defp decode_addon(name, yaml) do + with {:ok, res} <- YamlElixir.read_from_string(yaml), {:ok, encoded} <- Jason.encode(res), - do: Poison.decode(encoded, as: AddOn.spec()) + {:ok, addon} <- Poison.decode(encoded, as: AddOn.spec()), + do: {:ok, %{addon | name: name}} + end + + def static() do + base_path = "static/compatibilities" + {:ok, yaml} = File.read("#{base_path}/manifest.yaml") + {:ok, %{"names" => [_ | _] = addons}} = YamlElixir.read_from_string(yaml) + Enum.map(addons, fn name -> + {:ok, yaml} = File.read("#{base_path}/#{name}.yaml") + {:ok, addon} = decode_addon(name, yaml) + %{addon | name: name} + end) end end diff --git a/lib/console/deployments/deprecations/table.ex b/lib/console/deployments/deprecations/table.ex index 07efa4b779..45ad196d95 100644 --- a/lib/console/deployments/deprecations/table.ex +++ b/lib/console/deployments/deprecations/table.ex @@ -1,6 +1,7 @@ defmodule Console.Deployments.Deprecations.Table do use GenServer alias Console.Schema.ServiceComponent + alias Console.Deployments.Static alias ETS.KeyValueSet require Logger @@ -8,8 +9,9 @@ defmodule Console.Deployments.Deprecations.Table do @poll :timer.minutes(60) @url "/pluralsh/console/master/static/versions.yml" + defmodule State do - defstruct [:table, :url] + defstruct [:table, :url, :static] end defmodule Entry do @@ -26,7 +28,7 @@ defmodule Console.Deployments.Deprecations.Table do :timer.send_interval(@poll, :poll) send self(), :poll {:ok, table} = KeyValueSet.new(name: @table, read_concurrency: true, ordered: true) - {:ok, %State{table: table, url: Console.github_raw_url(@url)}} + {:ok, %State{table: table, url: Console.github_raw_url(@url), static: Console.conf(:airgap)}} end def fetch(%ServiceComponent{} = component) do @@ -36,6 +38,11 @@ defmodule Console.Deployments.Deprecations.Table do end end + def handle_info(:poll, %State{table: table, static: true} = state) do + table = Enum.reduce(Static.deprecations(), table, &KeyValueSet.put!(&2, name(&1), &1)) + {:noreply, %{state | table: table}} + end + def handle_info(:poll, %State{table: table, url: url} = state) do with [_ | _] = entries <- fetch_and_parse(url) do table = Enum.reduce(entries, table, &KeyValueSet.put!(&2, name(&1), &1)) @@ -74,4 +81,10 @@ defmodule Console.Deployments.Deprecations.Table do [v] -> {"core", v} end end + + def static() do + {:ok, yaml} = File.read("static/versions.yml") + {:ok, %{"deprecated-versions" => [_ | _] = deprecated}} = YamlElixir.read_from_string(yaml) + Enum.map(deprecated, &to_entry/1) + end end diff --git a/lib/console/deployments/static.ex b/lib/console/deployments/static.ex new file mode 100644 index 0000000000..9c3ca19953 --- /dev/null +++ b/lib/console/deployments/static.ex @@ -0,0 +1,13 @@ +defmodule Console.Deployments.Static do + @moduledoc """ + Static values needed to help airgap the deployment. We ping github for some important data that can + be embedded at compile time for orgs that do not permit egress there or run fully airgapped. + """ + alias Console.Deployments + + @compatibilities Deployments.Compatibilities.Table.static() + @deprecations Deployments.Deprecations.Table.static() + + def compatibilities(), do: @compatibilities + def deprecations(), do: @deprecations +end diff --git a/priv/notifications/slack/service.update.json.eex b/priv/notifications/slack/service.update.json.eex index 03cb518fb5..e521d9ba68 100644 --- a/priv/notifications/slack/service.update.json.eex +++ b/priv/notifications/slack/service.update.json.eex @@ -1,23 +1,71 @@ { - "text": "Service <%= @service.name %> for cluster <%= @service.cluster.name %> has a new revision", - "blocks": [ - { - "type": "section", - "text": { - "type": "mrkdwn", - "text": "Service <%= @service.name %> for cluster <%= @service.cluster.name %> has a new revision" - } - }, - { - "type": "divider" + "text": "🚀 Service <%= @service.name %> for cluster <%= @service.cluster.name %> has a new revision", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "🚀 *Service <%= @service.name %> for cluster <%= @service.cluster.name %> has a new revision*" + } }, - { - "type": "section", - "fields": [ - {"type": "mrkdwn", "text": "*Url*\n<%= Console.url("/cd/clusters/#{@service.cluster_id}/services/#{@service.id}/components") %>"}, - {"type": "mrkdwn", "text": "*Revision*\n<%= @service.sha %>"}, - {"type": "mrkdwn", "text": "*Source*\n<%= @source.url %> <%= @source.ref %>"} - ] - } - ] + { + "type": "rich_text", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "URL", + "style": { + "bold": true + } + }, + { + "type": "text", + "text": ": " + }, + { + "type": "link", + "url": "<%= Console.url("/cd/clusters/#{@service.cluster_id}/services/#{@service.id}/components") %>" + }, + { + "type": "text", + "text": "\n\n" + }, + { + "type": "text", + "text": "Revision", + "style": { + "bold": true + } + }, + { + "type": "text", + "text": ": <%= @service.sha %>\n\n" + }, + { + "type": "text", + "text": "Source", + "style": { + "bold": true + } + }, + { + "type": "text", + "text": ": " + }, + { + "type": "link", + "url": "<%= @source.url %>" + }, + { + "type": "text", + "text": " <%= @source.ref %>" + } + ] + } + ] + } + ] } diff --git a/rel/config/console.exs b/rel/config/console.exs index 9a2c3ea518..e414939b05 100644 --- a/rel/config/console.exs +++ b/rel/config/console.exs @@ -96,7 +96,8 @@ config :console, provider: provider, build_id: get_env("CONSOLE_BUILD_ID"), kas_dns: get_env("KAS_DNS"), - byok: get_env("CONSOLE_BYOK") == "true" + byok: get_env("CONSOLE_BYOK") == "true", + airgap: get_env("CONSOLE_AIRGAP") == "true" if git_url && String.starts_with?(git_url, "https") do config :console, @@ -119,6 +120,7 @@ if is_set("CONSOLE_ADMIN_EMAILS") do admin_emails: String.split(get_env("CONSOLE_ADMIN_EMAILS"), ~r/\s*,\s*/, trim: true) end + if is_set("BACKUP_ACCESS_KEY") and is_set("BACKUP_SECRET_ACCESS_KEY") do config :console, :backup_keys, s3_access_key_id: get_env("BACKUP_ACCESS_KEY"),