defmodule Carny.Identifier do alias __MODULE__ @moduledoc """ Identifiers are the objects that represent a given resource. i.e. bulwark:my-company:deployments """ defstruct organization: "", domain: "", resource: "" @doc """ Parse an arn into an identifier struct ## Examples iex> Carny.Identifier.parse("bulwark:my-company:deployments") %Carny.Identifier{domain: "my-company", organization: "bulwark", resource: "deployments"} """ def parse(str) when is_binary(str), do: String.split(str, ":") |> parse() def parse([organization, domain, resource]), do: %Identifier{ organization: organization, domain: domain, resource: resource } def parse(_), do: {:error, :badmatch} @doc """ Takes an identifier and creates a list of each component. Useful when you're trying to build a string to represent the Identifier. """ def parts(%Identifier{} = i), do: [i.organization, i.domain, i.resource] @doc ~S""" Returns a global identifier, aka "*" """ def global(), do: %Identifier{organization: "*", domain: "*", resource: "*"} @doc """ Given two identifiers see if the first matches the second """ def validate_against(%Identifier{} = identifier, %Identifier{} = resource) do identifier = replace_wildcards(identifier, resource) # Do a pattern match match?(^identifier, resource) end @doc ~S""" Replaces all the variables in a given resource with "*" if the compared to resource has a "*" in that field """ def replace_wildcards(a, b) do a = if b.organization == "*", do: Map.put(a, :organization, "*"), else: a a = if b.domain == "*", do: Map.put(a, :domain, "*"), else: a if b.resource == "*", do: Map.put(a, :resource, "*"), else: a end def from_map(identifier), do: struct(Identifier, identifier) end