@@ -13,6 +13,19 @@ mod expander;
1313mod hippo_notifier;
1414mod hippofacts;
1515
16+ /// Indicate which flags are required for bindle builds
17+ #[ allow( dead_code) ]
18+ enum BindleBuildRequirements {
19+ /// A Bindle server URL is required
20+ RequireBindleServer ,
21+ /// An explicit stage directory is required
22+ RequireStageDirectory ,
23+ /// Both the Bindle server and the stage directory are required
24+ RequireBindleServerAndStageDirectory ,
25+ /// There are no required arguments for the bindle builds
26+ NoRequirements ,
27+ }
28+
1629const ARG_HIPPOFACTS : & str = "hippofacts_path" ;
1730const ARG_STAGING_DIR : & str = "output_dir" ;
1831const ARG_OUTPUT : & str = "output_format" ;
@@ -35,49 +48,6 @@ in which you are running the 'hippo' command.
3548
3649#[ tokio:: main]
3750async fn main ( ) -> anyhow:: Result < ( ) > {
38- // Arguments necessary to build a bindle (but not push it)
39- // - ARG_HIPPOFACTS
40- // - ARG_VERSIONING
41- // - ARG_OUTPUT
42- // - ARG_BINDLE_URL
43- // - ARG_STAGING_DIR
44- let bindle_build_args = vec ! [
45- Arg :: new( ARG_HIPPOFACTS )
46- . required( true )
47- . index( 1 )
48- . about( "The artifacts spec (file or directory containing HIPPOFACTS file)" ) ,
49- Arg :: new( ARG_VERSIONING )
50- . possible_values( & [ "dev" , "production" ] )
51- . default_value( "dev" )
52- . required( false )
53- . short( 'v' )
54- . long( "invoice-version" )
55- . about( "How to version the generated invoice" ) ,
56- Arg :: new( ARG_OUTPUT )
57- . possible_values( & [ "id" , "message" , "none" ] )
58- . default_value( "message" )
59- . required( false )
60- . short( 'o' )
61- . long( "output" )
62- . about( "What to print on success" ) ,
63- Arg :: new( ARG_BINDLE_URL )
64- . short( 's' )
65- . long( "server" )
66- . env( "BINDLE_URL" )
67- . about( "The Bindle server to push the artifacts to" ) ,
68- Arg :: new( ARG_INSECURE )
69- . required( false )
70- . takes_value( false )
71- . short( 'k' )
72- . long( "insecure" )
73- . about( "If set, ignore server certificate errors" ) ,
74- Arg :: new( ARG_STAGING_DIR )
75- . takes_value( true )
76- . short( 'd' )
77- . long( "dir" )
78- . about( "The path to output the artifacts to. Required when doing a `hippo prepare`. Other commands will use a temp dir if this is not specified." ) ,
79- ] ;
80-
8151 let matches = App :: new ( env ! ( "CARGO_PKG_NAME" ) )
8252 . version ( env ! ( "CARGO_PKG_VERSION" ) )
8353 . author ( "Deis Labs" )
@@ -86,21 +56,24 @@ async fn main() -> anyhow::Result<()> {
8656 . subcommand (
8757 App :: new ( "push" )
8858 . about ( "Packages and uploads Hippo artifacts, notifying Hippo" )
89- . args ( & bindle_build_args)
59+ . args ( bindle_build_args ( BindleBuildRequirements :: RequireBindleServer ) )
9060 . arg (
9161 Arg :: new ( ARG_HIPPO_URL )
62+ . required ( true )
9263 . long ( "hippo-url" )
9364 . env ( "HIPPO_URL" )
9465 . about ( "The Hippo service to push the artifacts to" ) ,
9566 )
9667 . arg (
9768 Arg :: new ( ARG_HIPPO_USERNAME )
69+ . required ( true )
9870 . long ( "hippo-username" )
9971 . env ( "HIPPO_USERNAME" )
10072 . about ( "The username for connecting to Hippo" ) ,
10173 )
10274 . arg (
10375 Arg :: new ( ARG_HIPPO_PASSWORD )
76+ . required ( true )
10477 . long ( "hippo-password" )
10578 . env ( "HIPPO_PASSWORD" )
10679 . about ( "The username for connecting to Hippo" ) ,
@@ -109,12 +82,12 @@ async fn main() -> anyhow::Result<()> {
10982 . subcommand (
11083 App :: new ( "prepare" )
11184 . about ( "Reads a HIPPOFACTS file and prepares a Bindle, caching it locally." )
112- . args ( & bindle_build_args) ,
85+ . args ( bindle_build_args ( BindleBuildRequirements :: RequireStageDirectory ) ) ,
11386 )
11487 . subcommand (
11588 App :: new ( "bindle" )
11689 . about ( "Creates a bindle and pushes it to the Bindle server, but does not notify Hippo" )
117- . args ( & bindle_build_args) ,
90+ . args ( bindle_build_args ( BindleBuildRequirements :: RequireBindleServer ) ) ,
11891 )
11992 . get_matches ( ) ;
12093
@@ -127,6 +100,65 @@ async fn main() -> anyhow::Result<()> {
127100 }
128101}
129102
103+ /// Constructs arguments used to do a Bindle build.
104+ /// Arguments necessary to build a bindle (but not push it)
105+ /// - ARG_HIPPOFACTS
106+ /// - ARG_VERSIONING
107+ /// - ARG_OUTPUT
108+ /// - ARG_BINDLE_URL
109+ /// - ARG_STAGING_DIR
110+ fn bindle_build_args < ' a > ( requirements : BindleBuildRequirements ) -> Vec < Arg < ' a > > {
111+ let require_bindle_server = matches ! (
112+ requirements,
113+ BindleBuildRequirements :: RequireBindleServer
114+ | BindleBuildRequirements :: RequireBindleServerAndStageDirectory
115+ ) ;
116+ let require_stage_dir = matches ! (
117+ requirements,
118+ BindleBuildRequirements :: RequireStageDirectory
119+ | BindleBuildRequirements :: RequireBindleServerAndStageDirectory
120+ ) ;
121+
122+ vec ! [
123+ Arg :: new( ARG_HIPPOFACTS )
124+ . required( true )
125+ . index( 1 )
126+ . about( "The artifacts spec (file or directory containing HIPPOFACTS file)" ) ,
127+ Arg :: new( ARG_VERSIONING )
128+ . possible_values( & [ "dev" , "production" ] )
129+ . default_value( "dev" )
130+ . required( false )
131+ . short( 'v' )
132+ . long( "invoice-version" )
133+ . about( "How to version the generated invoice" ) ,
134+ Arg :: new( ARG_OUTPUT )
135+ . possible_values( & [ "id" , "message" , "none" ] )
136+ . default_value( "message" )
137+ . required( false )
138+ . short( 'o' )
139+ . long( "output" )
140+ . about( "What to print on success" ) ,
141+ Arg :: new( ARG_BINDLE_URL )
142+ . short( 's' )
143+ . long( "server" )
144+ . env( "BINDLE_URL" )
145+ . about( "The Bindle server to push the artifacts to" )
146+ . required( require_bindle_server) ,
147+ Arg :: new( ARG_INSECURE )
148+ . required( false )
149+ . takes_value( false )
150+ . short( 'k' )
151+ . long( "insecure" )
152+ . about( "If set, ignore server certificate errors" ) ,
153+ Arg :: new( ARG_STAGING_DIR )
154+ . takes_value( true )
155+ . short( 'd' )
156+ . long( "dir" )
157+ . about( "The path to output the artifacts to. Required when doing a `hippo prepare`. Other commands will use a temp dir if this is not specified." )
158+ . required( require_stage_dir) ,
159+ ]
160+ }
161+
130162/// Run the prepare command
131163///
132164/// Args:
@@ -231,13 +263,16 @@ async fn push(args: &ArgMatches) -> anyhow::Result<()> {
231263 } ) ?) ;
232264
233265 // Hippo configuration
234- let hippo_url = args. value_of ( ARG_HIPPO_URL ) . map ( |s| s. to_owned ( ) ) ;
266+ let hippo_url = args
267+ . value_of ( ARG_HIPPO_URL )
268+ . map ( |s| s. to_owned ( ) )
269+ . ok_or_else ( || anyhow:: anyhow!( "A Hippo url is required. Use --hippo-url or $HIPPO_URL" ) ) ?;
235270 let hippo_username = args. value_of ( ARG_HIPPO_USERNAME ) ;
236271 let hippo_password = args. value_of ( ARG_HIPPO_PASSWORD ) ;
237272
238273 // Notification configuration
239- let notify_to = hippo_url . map ( |url| hippo_notifier:: ConnectionInfo {
240- url,
274+ let notify_to = Some ( hippo_notifier:: ConnectionInfo {
275+ url : hippo_url ,
241276 danger_accept_invalid_certs : args. is_present ( ARG_INSECURE ) ,
242277 username : hippo_username. unwrap ( ) . to_owned ( ) , // Known to be set if the URL is
243278 password : hippo_password. unwrap ( ) . to_owned ( ) ,
0 commit comments