diff options
| author | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-02-28 19:16:14 -0500 | 
|---|---|---|
| committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2024-02-28 19:16:14 -0500 | 
| commit | d5010cdff912411faa41ab997019b7929030356c (patch) | |
| tree | b214bf1bc67d31060e72a7d1932f193def5e746f | |
| parent | a797d4faae5ed13fa8b3280a9566566040f0cece (diff) | |
| download | stasis-d5010cdff912411faa41ab997019b7929030356c.tar.gz | |
Document functions and usage
| -rw-r--r-- | include/artifactory.h | 252 | ||||
| -rw-r--r-- | include/conda.h | 154 | ||||
| -rw-r--r-- | include/omc.h | 19 | 
3 files changed, 376 insertions, 49 deletions
| diff --git a/include/artifactory.h b/include/artifactory.h index 0fcf073..c8ce6d3 100644 --- a/include/artifactory.h +++ b/include/artifactory.h @@ -1,3 +1,4 @@ +//! @file artifactory.h  #ifndef OMC_ARTIFACTORY_H  #define OMC_ARTIFACTORY_H @@ -5,46 +6,48 @@  #include <stdlib.h>  #include "omc.h" +//! JFrog Artifactory Authentication struct  struct JFRT_Auth { -    bool insecure_tls; -    char *access_token; -    char *password; -    char *client_cert_key_path; -    char *client_cert_path; -    char *ssh_key_path; -    char *ssh_passphrase; -    char *user; -    char *server_id; -    char *url; +    bool insecure_tls; //!< Disable TLS +    char *access_token; //!< Generated access token +    char *password; //!< Password +    char *client_cert_key_path; //!< Path to where SSL key is stored +    char *client_cert_path; //!< Path to where SSL cert is stored +    char *ssh_key_path; //!< Path to SSH private key +    char *ssh_passphrase; //!< Passphrase for SSH private key +    char *user; //!< Account to authenticate as +    char *server_id; //!< Artifactory server identification (unused) +    char *url; //!< Artifactory server address  }; +//! JFrog Artifactory Upload struct  struct JFRT_Upload { -    bool quiet; -    char *project; -    bool ant; -    bool archive; -    char *build_name; -    char *build_number; -    bool deb; -    bool detailed_summary; -    bool dry_run; -    char *exclusions; -    bool explode; -    bool fail_no_op; -    bool flat; -    bool include_dirs; -    char *module; -    bool recursive; -    bool regexp; -    int retries; -    int retry_wait_time; -    char *spec; +    bool quiet; //!< Enable quiet mode +    char *project; //!< Destination project name +    bool ant; //!< Enable Ant style regex +    bool archive; //!< Generate a ZIP archive of the uploaded file(s) +    char *build_name; //!< Build name +    char *build_number; //!< Build number +    bool deb; //!< Is Debian package? +    bool detailed_summary; //!< Enable upload summary +    bool dry_run; //!< Enable dry run (no-op) +    char *exclusions; //!< Exclude patterns (separated by semicolons) +    bool explode; //!< If uploaded file is an archive, extract it at the destination +    bool fail_no_op; //!< Exit 2 when no file are affected +    bool flat; //!< Upload with exact file system structure +    bool include_dirs; //!< Enable to upload empty directories +    char *module; //!< Build-info module name (optional) +    bool recursive; //!< Upload files recursively +    bool regexp; //!< Use regular expressions instead of wildcards +    int retries; //!< Number of retries before giving up +    int retry_wait_time; //!< Seconds between retries +    char *spec; //!< Path to JSON upload spec      char *spec_vars; -    bool symlinks; -    bool sync_deletes; -    char *target_props; -    int threads; -    bool workaround_parent_only; +    bool symlinks; //!< Preserve symbolic links +    bool sync_deletes; //!< Destination is replaced by uploaded files +    char *target_props; //!< Properties (separated by semicolons) +    int threads; //!< Thread count +    bool workaround_parent_only; //!< Change directory to local parent directory before uploading files  };  struct JFRT_Download { @@ -85,6 +88,34 @@ struct JFRT_Download {      bool validate_symlinks;  }; +/** + * Download the JFrog CLI tool from jfrog.com + * ```c + * if (artifactory_download_cli(".", + *         "https://releases.jfrog.io/artifactory", + *         "jfrog-cli", + *         "v2-jf", + *         "[RELEASE]", + *         "Linux", + *         "x86_64", + *         "jf") { + *     remove("./jf"); + *     fprintf(stderr, "Failed to download JFrog CLI\n"); + *     exit(1); + * } + * + * ``` + * + * @param dest Directory path + * @param jfrog_artifactory_base_url jfrog.com base URL + * @param jfrog_artifactory_product jfrog.com project (jfrog-cli) + * @param cli_major_ver Version series (v1, v2-jf, vX-jf) + * @param version Version to download. "[RELEASE]" will download the latest version available + * @param os Operating system name + * @param arch System CPU architecture + * @param remote_filename File to download (jf) + * @return + */  int artifactory_download_cli(char *dest,                               char *jfrog_artifactory_base_url,                               char *jfrog_artifactory_product, @@ -93,12 +124,161 @@ int artifactory_download_cli(char *dest,                               char *os,                               char *arch,                               char *remote_filename); + +/** + * JFrog CLI binding. Executes the "jf" tool with arguments. + * + * ```c + * struct JFRT_Auth auth_ctx; + * memset(auth_ctx, 0, sizeof(auth_context); + * auth_ctx.user = strdup("myuser"); + * auth_ctx.password = strdup("mypassword"); + * auth_ctx.url = strdup("https://myserver.tld/artifactory"); + * + * if (jfrog_cli(&auth_ctx, "ping") { + *     fprintf(stderr, "Failed to ping artifactory server: %s\n", auth_ctx.url); + *     exit(1); + * } + * ``` + * + * @param auth JFRT_Auth structure + * @param args Command line arguments to pass to "jf" tool + * @return exit code from "jf" + */  int jfrog_cli(struct JFRT_Auth *auth, char *args); + +/** + * Issue an Artifactory server ping + * + * ```c + * struct JFRT_Auth auth_ctx; + * memset(auth_ctx, 0, sizeof(auth_context); + * auth_ctx.user = strdup("myuser"); + * auth_ctx.password = strdup("mypassword"); + * auth_ctx.url = strdup("https://myserver.tld/artifactory"); + * + * if (jfrog_cli_ping(&auth_ctx)) { + *     fprintf(stderr, "Failed to ping artifactory server: %s\n", auth_ctx.url); + *     exit(1); + * } + * ``` + * + * @param auth JFRT_Auth structure + * @return exit code from "jf" + */  int jfrog_cli_rt_ping(struct JFRT_Auth *auth); + +/** + * Upload files to an Artifactory repository + * + * ```c + * struct JFRT_Auth auth_ctx; + * memset(auth_ctx, 0, sizeof(auth_context); + * auth_ctx.user = strdup("myuser"); + * auth_ctx.password = strdup("mypassword"); + * auth_ctx.url = strdup("https://myserver.tld/artifactory"); + * + * struct JFRT_Upload upload_ctx; + * jfrt_upload_set_defaults(&upload_ctx); + * + * if (jfrt_cli_rt_upload(&auth_ctx, &upload_ctx, + *     "local/files_*.ext", "repo_name/ext_files/")) { + *     fprintf(stderr, "Upload failed\n"); + *     exit(1); + * } + * ``` + * + * @param auth JFRT_Auth structure + * @param ctx JFRT_Upload structure + * @param src local pattern to upload + * @param repo_path remote Artifactory destination path + * @return exit code from "jf" + */  int jfrog_cli_rt_upload(struct JFRT_Auth *auth, struct JFRT_Upload *ctx, char *src, char *repo_path); + +/** + * Download a file from an Artifactory repository + * + * ```c + * struct JFRT_Auth auth_ctx; + * memset(auth_ctx, 0, sizeof(auth_context); + * auth_ctx.user = strdup("myuser"); + * auth_ctx.password = strdup("mypassword"); + * auth_ctx.url = strdup("https://myserver.tld/artifactory"); + * + * struct JFRT_Download download_ctx; + * memset(download_ctx, 0, sizeof(download_ctx)); + * + * if (jfrt_cli_rt_download(&auth_ctx, &download_ctx, + *     "repo_name/ext_files/", "local/files_*.ext")) { + *     fprintf(stderr, "Upload failed\n"); + *     exit(1); + * } + * ``` + * + * @param auth JFRT_Auth structure + * @param ctx  JFRT_Download structure + * @param repo_path Remote repository w/ file pattern + * @param dest Local destination path + * @return exit code from "jf" + */  int jfrog_cli_rt_download(struct JFRT_Auth *auth, struct JFRT_Download *ctx, char *repo_path, char *dest); + +/** + * Collect runtime data for Artifactory build object. + * + * ```c + * struct JFRT_Auth auth_ctx; + * memset(auth_ctx, 0, sizeof(auth_context); + * auth_ctx.user = strdup("myuser"); + * auth_ctx.password = strdup("mypassword"); + * auth_ctx.url = strdup("https://myserver.tld/artifactory"); + * + * if (jfrog_cli_rt_build_collect_env(&auth_ctx, "mybuildname", "1.2.3+gabcdef")) { + *     fprintf(stderr, "Failed to collect runtime data for Artifactory build object\n"); + *     exit(1); + * } + * ``` + * + * @param auth JFRT_Auth structure + * @param build_name Artifactory build name + * @param build_number Artifactory build number + * @return exit code from "jf" + */  int jfrog_cli_rt_build_collect_env(struct JFRT_Auth *auth, char *build_name, char *build_number); + +/** + * Publish build object to Artifactory server + * + * ```c + * struct JFRT_Auth auth_ctx; + * memset(auth_ctx, 0, sizeof(auth_context); + * auth_ctx.user = strdup("myuser"); + * auth_ctx.password = strdup("mypassword"); + * auth_ctx.url = strdup("https://myserver.tld/artifactory"); + * + * if (jfrog_cli_rt_build_collect_env(&auth_ctx, "mybuildname", "1.2.3+gabcdef")) { + *     fprintf(stderr, "Failed to collect runtime data for Artifactory build object\n"); + *     exit(1); + * } + * + * if (jfrog_cli_rt_build_publish(&auth_ctx, "mybuildname", "1.2.3+gabcdef")) { + *     fprintf(stderr, "Failed to publish Artifactory build object\n"); + *     exit(1); + * } + * ``` + * + * @param auth JFRT_Auth structure + * @param build_name Artifactory build name + * @param build_number Artifactory build number + * @return exit code from "jf" + */  int jfrog_cli_rt_build_publish(struct JFRT_Auth *auth, char *build_name, char *build_number); + +/** + * Zero-out and apply likely defaults to a JFRT_Upload structure + * @param ctx JFRT_Upload structure + */  void jfrt_upload_set_defaults(struct JFRT_Upload *ctx); -#endif //OMC_ARTIFACTORY_H +#endif //OMC_ARTIFACTORY_H
\ No newline at end of file diff --git a/include/conda.h b/include/conda.h index 3565bda..9cbbf9c 100644 --- a/include/conda.h +++ b/include/conda.h @@ -1,7 +1,4 @@ -// -// Created by jhunk on 5/14/23. -// - +//! @file conda.h  #ifndef OMC_CONDA_H  #define OMC_CONDA_H @@ -11,14 +8,163 @@  #define CONDA_INSTALL_PREFIX "conda" +/** + * Execute Python + * Python interpreter is determined by PATH + * + * ```c + * if (python_exec("-c 'printf(\"Hello world\")'")) { + *     fprintf(stderr, "Hello world failed\n"); + *     exit(1); + * } + * ``` + * + * @param args arguments to pass to interpreter + * @return exit code from python interpreter + */  int python_exec(const char *args); + +/** + * Execute Pip + * Pip is determined by PATH + * + * ```c + * if (pip_exec("freeze")) { + *     fprintf(stderr, "pip freeze failed\n"); + *     exit(1); + * } + * ``` + * + * @param args arguments to pass to Pip + * @return exit code from Pip + */  int pip_exec(const char *args); + +/** + * Execute conda (or if possible, mamba) + * Conda/Mamba is determined by PATH + * + * ```c + * if (conda_exec("env list")) { + *     fprintf(stderr, "Failed to list conda environments\n"); + *     exit(1); + * } + * ``` + * + * @param args arguments to pass to Conda + * @return exit code from Conda + */  int conda_exec(const char *args); + +/** + * Configure the runtime environment to use Conda/Mamba + * + * ```c + * if (conda_activate("/path/to/conda/installation", "base")) { + *     fprintf(stderr, "Failed to activate conda's base environment\n"); + *     exit(1); + * } + * ``` + * + * @param root directory where conda is installed + * @param env_name the conda environment to activate + * @return 0 on success, -1 on error + */  int conda_activate(const char *root, const char *env_name); + +/** + * Configure the active conda installation for headless operation + */  void conda_setup_headless(); + +/** + * Creates a Conda environment from a YAML config + * + * ```c + * if (conda_env_create_from_uri("myenv", "https://myserver.tld/environment.yml")) { + *     fprintf(stderr, "Environment creation failed\n"); + *     exit(1); + * } + * ``` + * + * @param name Name of new environment to create + * @param uri /path/to/environment.yml + * @param uri file:///path/to/environment.yml + * @param uri http://myserver.tld/environment.yml + * @param uri https://myserver.tld/environment.yml + * @param uri ftp://myserver.tld/environment.yml + * @return exit code from "conda" + */  int conda_env_create_from_uri(char *name, char *uri); + +/** + * Create a Conda environment using generic package specs + * + * ```c + * // Create a basic environment without any conda packages + * if (conda_env_create("myenv", "3.11", NULL)) { + *     fprintf(stderr, "Environment creation failed\n"); + *     exit(1); + * } + * + * // Create a basic environment and install conda packages + * if (conda_env_create("myenv", "3.11", "hstcal fitsverify")) { + *     fprintf(stderr, "Environment creation failed\n"); + *     exit(1); + * } + * ``` + * + * @param name Environment name + * @param python_version Desired version of Python + * @param packages Packages to install (or NULL) + * @return exit code from "conda" + */  int conda_env_create(char *name, char *python_version, char *packages); + +/** + * Remove a Conda environment + * + * ```c + * if (conda_env_remove("myenv")) { + *     fprintf(stderr, "Unable to remove conda environment\n"); + *     exit(1); + * } + * ``` + * + * @param name Environment name + * @return exit code from "conda" + */  int conda_env_remove(char *name); + +/** + * Export a Conda environment in YAML format + * + * ```c + * if (conda_env_export("myenv", "./", "myenv.yml")) { + *     fprintf(stderr, "Unable to export environment\n"); + *     exit(1); + * } + * ``` + * + * @param name Environment name to export + * @param output_dir Destination directory + * @param output_filename Destination file name + * @return exit code from "conda" + */  int conda_env_export(char *name, char *output_dir, char *output_filename); + +/** + * Run "conda index" on a local conda channel + * + * ```c + * if (conda_index("/path/to/channel")) { + *     fprintf(stderr, "Unable to index requested path\n"); + *     exit(1); + * } + * ``` + * + * @param path Top-level directory of conda channel + * @return exit code from "conda" + */  int conda_index(const char *path);  #endif //OMC_CONDA_H diff --git a/include/omc.h b/include/omc.h index 86add4e..99e2eba 100644 --- a/include/omc.h +++ b/include/omc.h @@ -1,3 +1,4 @@ +//! @file omc.h  #ifndef OMC_OMC_H  #define OMC_OMC_H @@ -46,15 +47,15 @@  }  struct OMC_GLOBAL { -    bool verbose; -    bool always_update_base_environment; -    bool continue_on_error; -    bool conda_fresh_start; -    struct StrList *conda_packages; -    struct StrList *pip_packages; -    char *tmpdir; -    char *conda_install_prefix; -    char *sysconfdir; +    bool verbose; //!< Enable verbose output +    bool always_update_base_environment; //!< Update base environment immediately after activation +    bool continue_on_error; //!< Do not stop on test failures +    bool conda_fresh_start; //!< Always install a new copy of Conda +    struct StrList *conda_packages; //!< Conda packages to install after initial activation +    struct StrList *pip_packages; //!< Pip packages to install after initial activation +    char *tmpdir; //!< Path to temporary storage directory +    char *conda_install_prefix; //!< Path to install conda +    char *sysconfdir; //!< Path where OMC reads its configuration files (mission directory, etc)      struct Jfrog {          char *jfrog_artifactory_base_url;          char *jfrog_artifactory_product; | 
