The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Ixchel::Actions::xeno_build - Builds and installs stuff based on the supplied hash.

VERSION

Version 0.1.0

SYNOPSIS

OPTIONS

build_hash

A build hash containing the options to use for installing and building.

BUILD HASH

BUILD OPTIONS AND VALUES

options

    - .options.build_dir :: Build dir to use. If not defined, .config.xeno_options.build_dir
            is used. If that is undef, '/tmp/' is used.
        - Default :: undef

    . options.tmpdir :: The path for a automatically created tmpdir under .options.build_dir.
            This will be removed one once xeno_build has finished running. This allows for easy cleanup
            when using templating with fetch and exec when using templating. This is created via
            L<File::Temp>->newdir.

    - .options.$var :: Additional variable to define.

order

An array of the order it should process the steps in. The default is as below.

    fetch
    pkgs
    perl
    python
    exec

So lets say you have a .exec in the hash, but .order does not contain 'exec' any place in the array, then whatever is in .exec will not be processed.

If you want to run exec twice with different values, you can create .exec0 and .exec with the desired stuff and set the order like below.

    exec0
    pkgs
    exec

First .exec0, then pkgs, and then .exec will be ran. The type is determined via removing the end from it via the regexp s/[0-9]*$//. So .perl123 would be ran as perl type.

Unknown types will result in an error.

vars

This is a hash of variables to pass to the template as var.

templated_vars

These are vars that are to be templated. The output is copied to the matching name to under vars.

TYPES

    - .$type.for :: 'for' may be specified for any of the types. It is a
            array of OS families it is for.
        - Default :: undef

fetch

    - .fetch.items.$name.url :: URL to fetch.

    - .fetch.items.$name.dst :: Where to write it to.

    - .fetch.template :: If the url and dst should be treated as a template.
        - Default :: 0

.fetch.items is a hash for the purpose of allowing it to easily be referenced later in exec. If .fetch.items.$name.url or .fetch.items.$name.dst is templated, the template output is saved as that variable so it can easily be used in exec.

Variables for template are as below.

    - config :: Ixchel config.

    - options :: Stuff defined via .options.

    - os :: OS as per L<Rex::Commands::Gather>.

pkgs

    - .pkgs.present :: A hash of arrays. The keys are the OS seen by
            L<Rex::Commands::Gather> and values in the array will be ensured to be
            present via L<Rex::Commands::Pkg>.
        - Default :: undef

    - .pkgs.latest :: A hash of arrays. The keys are the OS seen by
            L<Rex::Commands::Gather> and values in the array will be ensured to be
            latest via L<Rex::Commands::Pkg>.
        - Default :: undef

    - .pkgs.absent :: A hash of arrays. The keys are the OS seen by
            L<Rex::Commands::Gather> and values in the array will be ensured to be
            absent via L<Rex::Commands::Pkg>.

So if you want to install apache24 and exa on FreeBSD and jq on Debian, it would be like below.

    {
        pkgs => {
            latest => {
                FreeBSD => [ 'apache24', 'exa' ],
                Debian => [ 'jq' ],
            },
        },
    }

perl

    - .perl.modules :: A array of modules to to install via cpanm.
        - Default :: []

    - .perl.reinstall :: A Perl boolean for if it should --reinstall should be passed.
        - Default :: 0

    - .perl.notest :: A Perl boolean for if it should --notest should be passed.
        - Default :: 0

    - .perl.force :: A Perl boolean for if it should --force should be passed.
        - Default :: 0

    - .perl.install :: Ensures that cpanm is installed, which will also ensure that Perl is installed.
            If undef or 0, then cpanm won't be installed and will be assumed to already be present. If
            set to true, it will be installed if anything is specificed in .perl.modules.
        - Default :: 1

    - .perl.cpanm_install :: Install cpanm even if .cpanm.modules does not contain any modules.
        - Default :: 0

    - .perl.pkgs :: A list of modules to install via packages if possible.
        - Default :: []

    - perl.pkgs_always_try :: A Perl boolean for if the array for .cpanm.modules should be appended to
            .cpanm.pkgs.
        - Default :: 1

    - perl.pkgs_require :: A list of modules to install via packages. Will fail if any of these fail.
        - Default :: []

For the packages, if you want to make sure the package DB is up to date, you will want to set .pkgs.update_package_db_force to "1".

python

Install python stuff.

    - .python.pip_install :: A Perl boolean for if it should install python. By default only installs
            python and pip if .python.pip[0] or .python.pkgs[0] is defined.
        - Default :: 1

    - .python.modules :: A array items to install via pip.
        - Default :: []

    - .python.pkgs :: A array items to install via packages if possible.
        - Default :: []

    - .python.pkgs_require :: A array items that must be install via pkgs.
        - Default :: []

    - python.pkgs_always_try :: If pkgs should always be tried first prior to pip.
        - Default :: 1

exec

    - .exec.commands :: A array of hash to use for running commands.
        - Default :: []

    - .exec.command :: A command to run.
        - Default :: undef

    . exec.dir :: Directory to use. If undef, this will use .options.tmpdir .
        - Default :: undef

   - .exec.exits :: A array of acceptable exit values. May start with >, >=, <, or <= .
       - Default :: [0]

   - .exec.template :: If the command in question should be treated as a TT template.
       - Default :: [0]

Either .exec.commands or .exec.command must be used. If .exec.commands is used, each value in the array is a hash using the same keys, minus .commands, as .exec. So if .exec.commands[0].exits is undef, then .exec.exits is used as the default.

If .exec.commands[0] or .exec.command is undef, then nothing will be ran and even if .exec exists. Similarly if .command for a hash under .exec.commands, then nothing will be ran for that hash, it will be skipped.

TEMPLATES

Template is done via Template with the base variables being available.

    - config :: The Ixchel config.

    - env :: Enviromental variables.

    - os :: The OS or OS family.

    - vars :: Variables as set in .vars in the build hash.

    - templated_vars :: Templates used for crreating some vars under vars.

    - is_systemd :: If the system looks like it is systemd or not. The value is a boolean
        of 0 or 1.

    - tmpdir :: The path of the tmpdir.

    - options :: The contents of .options .

    - $type_items :: .fetch.items if it exists. $type will be the name of the fetch type entry.
        so 'fetch' will result in 'fetch_items' and 'fetch1' will result in 'fetch1_items'. If
        any of the items were templated, the value here will be the results of the templating.

The following functions are available.

    - shell_quote :: shell_quote from String::ShellQuote

Determining OS

Rex::Commands::Gather is used for this.

First the module get_operating_system is used. Then the following is ran.

    if (is_freebsd) {
        $self->{os}='FreeBSD';
    }elsif (is_debian) {
        $self->{os}='Debian';
    }elsif (is_redhat) {
        $self->{os}='Redhat';
    }elsif (is_arch) {
        $self->{os}='Arch';
    }elsif (is_suse) {
        $self->{os}='Suse';
    }elsif (is_alt) {
        $self->{os}='Alt';
    }elsif (is_netbsd) {
        $self->{os}='NetBSD';
    }elsif (is_openbsd) {
        $self->{os}='OpenBSD';
    }elsif (is_mageia) {
        $self->{os}='Mageia';
    }elsif (is_void) {
        $self->{os}='Void';
    }else{
        $self->{os}=get_operating_system;
    }

Which will set it to that if one of those matches.

EXAMPLE

Below is a example for installing Sagan on Debian and FreeBSD.

    ---
    templated_vars:
      github_ref: '[% IF env.sagan_github_ref %][% env.sagan_github_ref %][% ELSE %]main[% END %]'
    fetch:
      items:
        sagan:
          url: '[% IF env.sagan_url  %][% env.sagan_url %][% ELSE %]https://api.github.com/repos/quadrantsec/sagan/tarball/[% vars.github_ref %][% END %]'
          dst: 'sagan.tgz'
      template: 1
    exec:
      commands:
        - command: 'tar -zxvf sagan.tgz'
        - command: 'mv `ls -d *sagan-*` sagan'
        - command: autoreconf -vfi -I m4
          dir: sagan
        - command: ./configure --enable-bluedot --enable-geoip --enable-redis --enable-esmtp --enable-gzip
        - command: make -j5
        - command: make install
        - command: make -j5
          dir: cd tools
        - command: make install
        - command: '[% IF env.sagan_restart %]killall SaganMain[% ELSE %]echo not restarting[% END %]'
      template: 1
    pkgs:
      present:
        FreeBSD:
          - liblognorm
          - pcre
          - libesmtp
          - hiredis
          - json-c
          - libmaxminddb
        Debian:
          - liblognrom-dev
          - libpcre3-dev
          - build-eesential
          - libesmtp-dev
          - libhiredis-dev
          - libjson-c-dev
          - libmaxminddb-dev

RESULT HASH REF

    .errors :: A array of errors encountered.
    .status :: A string description of what was done and the results.
    .ok :: True if everyting okay.