nereond/lib.rs
1// Copyright (c) 2018, [Ribose Inc](https://www.ribose.com).
2//
3// Redistribution and use in source and binary forms, with or without
4// modification, are permitted provided that the following conditions
5// are met:
6// 1. Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// 2. Redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution.
11//
12// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
13// ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
14// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
15// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
16// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
17// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
18// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23
24extern crate base64;
25extern crate libc;
26extern crate nereon;
27
28#[macro_use]
29extern crate nereon_derive;
30
31#[macro_use]
32extern crate log;
33
34mod file;
35mod distro;
36
37use nereon::{FromValue, Value};
38use std::env;
39use std::fs;
40
41const VERSION: &str = env!("CARGO_PKG_VERSION");
42const AUTHORS: &str = env!("CARGO_PKG_AUTHORS");
43const LICENSE: &str = "BSD-2-Clause";
44const APPNAME: &str = env!("CARGO_PKG_NAME");
45
46#[derive(Debug, FromValue)]
47struct Config {
48 packages: Vec<String>,
49 fileset_file: Option<String>,
50 fileset_env: Option<String>,
51}
52
53pub fn nereond() -> Result<(), String> {
54 let nos = format!(
55 r#"
56 authors ["{}"]
57 license "{}"
58 name "{}"
59 version {}
60 option fileset_file {{
61 flags [takesvalue]
62 short f
63 long fileset
64 env NEREON_FILESET_FILE
65 hint FILE
66 usage "File containing a nereon fileset"
67 key [fileset_file]
68 }},
69 option fileset {{
70 flags [takesvalue]
71 long fileset-env
72 env NEREON_FILESET
73 hint FILESET
74 usage "Fileset as environment variable"
75 key [fileset_env]
76 }},
77 option packages {{
78 flags [takesvalue, multiple]
79 long package
80 short p
81 hint PACKAGE
82 usage "Install package using apt, yum etc."
83 key [packages]
84 }}"#,
85 AUTHORS, LICENSE, APPNAME, VERSION
86 );
87
88 let config = nereon::configure::<Config, _, _>(&nos, env::args()).unwrap();
89
90 // install packages
91 distro::install_packages(&config.packages)?;
92
93 // get the fileset from file/env
94 config
95 .fileset_file
96 .as_ref()
97 .map_or_else(
98 || {
99 config.fileset_env.as_ref().map_or_else(
100 || Err("No fileset from args or environment.".to_owned()),
101 |s| {
102 base64::decode(&s)
103 .map_err(|_| "Invalid base64 data in env[NEREON_FILESET]".to_owned())
104 .and_then(|bs| {
105 String::from_utf8(bs).map_err(|_| {
106 "Invalid utf8 data in env[NEREON_FILESET]".to_owned()
107 })
108 })
109 },
110 )
111 },
112 |file| {
113 fs::read_to_string(&file)
114 .map_err(|e| format!("Failed to read fileset file {}: {:?}.", file, e))
115 },
116 ).and_then(|fileset| file::parse_fileset(&mut fileset.as_bytes()))
117 .map(|fileset| {
118 fileset.iter().for_each(|(id, (f, decoded_content))| {
119 f.update(decoded_content)
120 .map_err(|e| warn!("Failed to update {}: {}", id, e))
121 .ok();
122 })
123 })
124
125 // At this point we're initialized: ie written an initial set of configs.
126 // To signal this we either fork and continue to listen for configuration updates
127 // or simply exit.
128
129 // Either way, control should return to the process spawner which now can start
130 // any processes dependent on nereond for configuration.
131}