Help with choosing data structures for template project

I have a templating system designed along this lines

It is a templating system where template values of the kind

param1=value2
param2=value2

go into templates of the type

do this with {{param1}}, do that with {{param2}}

etc.

Currently the params are in a database structured along the lines

param : the actual param as above
description: some description of what it does
default: default value
label: Label to use when values are entered in a form
required: required

the templates are also stored in a database

template: text of template
executeable: is it meant to be executed
destination: where it will be stored, includes remote locations
delete_after: it will be deleted

The templates have a number of other attributes but I have excluded them here

Note that destination can contain template parameters as well.

I am looking for way to restructure it so that it could all be included in a single file, ie the templates and their associated parameters could be elements of a struct (which I assume would be similar to records or structs in other languages) and once the params had been set, the templates would be filled out and ready to be delivered and/or executed as desired. A key part is wanting to use heredocs to set the body of the templates, making the heredoc values one the elements of the structures.

In the finished item the parameters would be entered from a form with the option of persisting some of them into a database.

So I am looking at 2 lists. The list of params and a list of templates. I would like to use iex initially and a web form later to enter the parameters and apply them to the templates, which will result in the template outputs with can go into temporary files, which a bash script can copy to the destinations and execute them via ssh commands or locally.

Another thing I want to consider is if some of the parameters can be generated via code, such as temporary files names where the templates will be saved before being copied to the final destinations.

Any ideas?

Thanks!

First, it looks like you are building a mustache template system, there are lots of those already out there, are you making it to learn how to make it or are you making it to use it (if to use it then should use one of the existing ones).

Thanks for the tip. I have heard mustache templates mentioned in Object Pascal land, but never cared to look it up.
Any how in this questions the data structures used are my interest and not so much the templates. Those should be a straight forward search and replace of the param values.

So mostly to learn? Cool. I’m short on time but I’ll try to give some info, maybe others can help with more. :slight_smile:

All of that is doable, but that begs the question, what would you like the code to look like and what would you like that pseudo-code to actually do as its output? That might be the best way to figure out a good interface for you. :slight_smile:

Also, erlang has a built in SSH system, so no need to bash scripts, you can execute remote SSH commands directly.

This is the first stage of the code. The params struct sets the defaults for the particulars of certificate. The intention is for a form to be created from this structure and for the user to change them. I thought the executeable: false and delete_after: false were wrong but it turns out they are atoms :true and :false

defmodule ParamStruct do
  defstruct key: "", value: "", default: "", description: "description of parameter", label: "label on web form", required: false
end

defmodule TemplateStruct do
  defstruct key: "must be unique", name: "descriptive name", code: "", executable: false, destination: "", delete_after: false,
  perms: "644"
end

defmodule ProcessList do
  def parse_list([]), do: []

  def parse_list([%{"key" => ky,"value" => val,"default" => dft, "description" => desc,"label" => lbl} | tail]) do
    [%ParamStruct{key: ky, value: val, description: desc, label: lbl, default: dft } | parse_list(tail) ]
  end

  def create_recommend_list(%{"itemScores" => score_list})  do
    parse_list(score_list)
  end

  params = [ 
%{"key" => "ca_cert_subj_state","value" => "","default" => "Greater London","description" => "Region","label" => "State/County"},
  %{"key" => "key-file","value" => "","default" => "cacert_001","description" => "","label" => "Key File (without password)"},
  %{"key" => "key-file-pass","value" => "","default" => "cacert_pass_001","description" => "","label" => "Key File (with password)"},
  %{"key" => "ca_cert_email","value" => "","default" => "admin@domain.net","description" => "","label" => "Email"},
  %{"key" => "ca_cert_subj_common_name","value" => "","default" => "domain.net","description" => "","label" => "Common Name"},
  %{"key" => "ca_cert_subj_country","value" => "","default" => "UK","description" => "Country","label" => "Country"},
  %{"key" => "ca_cert_subj_location","value" => "","default" => "Westchester","description" => "","label" => "Location"},
  %{"key" => "ca_cert_subj_organization","value" => "","default" => "Big Company","description" => "","label" => "Organisation"},
  %{"key" => "ca_cert_subj_org_unit","value" => "","default" => "Infosystems and Communications","description" => "","label" => "Organisational Unit"}
  ]


end

They will be applied to these templates:

# key generation - openssl genrsa
openssl genrsa -out {{key-file}}.key 2048  # generate key, command is 'openssl genrsa'
openssl genrsa -des3 -out {{key-file-pass}}.key 2048 # generate passworded key, will prompt for password

# self sign root certificate

openssl req -x509 -new -nodes -sha256 \
 -key {{key-file-pass}}.key \
 -days 3650 \
 -out {{key-file-pass}}.pem \
 -subj "\
/C={{ca_cert_subj_country}}\
/ST={{ca_cert_subj_state}}\
/L={{ca_cert_subj_location}}\
/O={{ca_cert_subj_organization}}\
/OU={{ca_cert_subj_org_unit}}\
/CN={{ca_cert_subj_common_name}}\
/emailAddress={{ca_cert_email}}\
" 


# create client certificate signing with existing key
# -nodes implies key will not be encrypted
# -
openssl req -nodes \
 -newkey rsa:2048 \
 -key {{client_cert_existing_key}}.key \
 -out {{client_cert_csr}}.csr \
 -extensions server_cert \
 -subj "\
/C={{client_cert_subj_country}}\
/ST={{client_cert_subj_state}}\
/L={{client_cert_subj_location}}\
/O={{client_cert_subj_organization}}\
/OU={{client_cert_subj_org_unit}}\
/CN={{client_cert_subj_common_name}}\
/emailAddress={{client_cert_email}}\
/subjectAltName={{client_cert_san}}
"

The openssl commands are what will go will be assigned to the code key of the template structs. The destination is the server where the scripts will be copied to, and executed where necessary.

My intention is to generate a form to prompt for them and even change the code value for the templates on the forms when necessary, but for the mean time I am happy to loop over the params structs values and generate prompts in iex or the command line for them.

The code you have now seems like a great starting point for that then. :slight_smile:

I am not so clever. I borrowed the code from - elixir - How To Enumerate Over A Map To Produce A List of Structs - Stack Overflow, and I am now analyzing how it works.

1 Like