2019-03-28 03:28:51 +03:00
#!/usr/bin/python3
2019-04-19 02:04:22 +03:00
from typing import Dict , List
2019-03-28 03:28:51 +03:00
2019-09-04 04:45:39 +03:00
from pathlib import Path
2019-03-28 03:28:51 +03:00
import argparse
import contextlib
import datetime
2019-05-23 15:48:06 +03:00
import fcntl
2019-03-28 03:28:51 +03:00
import glob
import logging
import os
import re
import subprocess
import sys
import yaml
2019-11-01 15:30:53 +03:00
import cloud_build . image_tests
2019-07-08 02:14:01 +03:00
2019-03-28 03:28:51 +03:00
PROG = ' cloud-build '
class CB :
""" class for building cloud images """
2019-11-01 16:44:46 +03:00
def __init__ ( self , args : Dict ) - > None :
self . parse_config ( args . config )
self . args = args
2019-03-28 03:28:51 +03:00
2019-09-04 04:45:39 +03:00
data_dir = ( Path ( os . getenv ( ' XDG_DATA_HOME ' ,
' ~/.local/share ' ) ) . expanduser ( )
/ f ' { PROG } ' )
2019-05-23 15:48:06 +03:00
self . data_dir = data_dir
2019-09-07 00:34:55 +03:00
self . checksum_command = ' sha256sum '
2019-09-04 04:45:39 +03:00
self . images_dir = data_dir / ' images '
self . work_dir = data_dir / ' work '
self . out_dir = data_dir / ' out '
2019-11-01 16:44:46 +03:00
self . system_datadir = args . data_dir
2019-03-28 03:28:51 +03:00
self . date = datetime . date . today ( ) . strftime ( ' % Y % m %d ' )
2019-04-11 01:17:56 +03:00
self . service_default_state = ' enabled '
2019-09-04 04:45:39 +03:00
self . created_scripts : List [ Path ] = [ ]
2019-03-28 03:28:51 +03:00
self . ensure_dirs ( )
2019-11-04 21:18:33 +03:00
self . ensure_run_once ( )
2019-03-28 03:28:51 +03:00
logging . basicConfig (
2019-09-04 04:45:39 +03:00
filename = f ' { data_dir } / { PROG } .log ' ,
2019-03-28 03:28:51 +03:00
format = ' %(levelname)s : %(asctime)s - %(message)s ' ,
)
self . log = logging . getLogger ( PROG )
2019-04-04 00:07:40 +03:00
self . log . setLevel ( self . log_level )
2019-03-28 03:28:51 +03:00
self . info ( f ' Start { PROG } ' )
2019-06-25 20:59:26 +03:00
def __del__ ( self ) - > None :
def unlink ( path ) :
try :
os . unlink ( path )
except FileNotFoundError :
pass
for name in self . created_scripts :
unlink ( name )
2019-09-04 04:45:39 +03:00
unlink ( self . work_dir / f ' mkimage-profiles/conf.d/ { PROG } .mk ' )
2019-06-25 20:59:26 +03:00
self . info ( f ' Finish { PROG } ' )
2019-05-23 15:48:06 +03:00
def ensure_run_once ( self ) :
2019-09-04 04:45:39 +03:00
self . lock_file = open ( self . data_dir / f ' { PROG } .lock ' , ' w ' )
2019-05-23 15:48:06 +03:00
try :
fcntl . flock ( self . lock_file . fileno ( ) , fcntl . LOCK_EX | fcntl . LOCK_NB )
2019-06-20 15:53:06 +03:00
except OSError : # already locked
2019-05-23 15:48:06 +03:00
print ( f ' { PROG } already running ' , file = sys . stderr )
exit ( 3 )
2019-03-28 03:28:51 +03:00
@contextlib.contextmanager
def pushd ( self , new_dir ) :
previous_dir = os . getcwd ( )
self . debug ( f ' Pushd to { new_dir } ' )
os . chdir ( new_dir )
yield
self . debug ( f ' Popd from { new_dir } ' )
os . chdir ( previous_dir )
def parse_config ( self , config : str ) - > None :
with open ( config ) as f :
cfg = yaml . safe_load ( f )
self . mkimage_profiles_git = os . path . expanduser (
2019-04-19 01:51:41 +03:00
cfg . get ( ' mkimage_profiles_git ' , ' ' )
2019-03-28 03:28:51 +03:00
)
2019-04-04 00:07:40 +03:00
self . log_level = getattr ( logging , cfg . get ( ' log_level ' , ' INFO ' ) . upper ( ) )
2019-04-19 01:59:31 +03:00
self . _repository_url = cfg . get ( ' repository_url ' ,
' file:///space/ALT/ {branch} ' )
self . bad_arches = cfg . get ( ' bad_arches ' , [ ] )
2019-04-11 21:41:07 +03:00
2019-09-07 01:18:04 +03:00
self . external_images = cfg . get ( ' external_images ' )
if self . external_images :
self . external_images = Path ( self . external_images ) . expanduser ( )
2019-04-08 14:19:40 +03:00
self . _packages = cfg . get ( ' packages ' , { } )
2019-04-11 01:17:56 +03:00
self . _services = cfg . get ( ' services ' , { } )
2019-06-25 20:59:26 +03:00
self . _scripts = cfg . get ( ' scripts ' , { } )
2019-04-08 14:19:40 +03:00
2019-03-28 03:28:51 +03:00
try :
self . _remote = os . path . expanduser ( cfg [ ' remote ' ] )
self . key = cfg [ ' key ' ]
2019-04-18 22:53:33 +03:00
if isinstance ( self . key , int ) :
self . key = ' {:X} ' . format ( self . key )
2019-03-28 03:28:51 +03:00
self . _images = cfg [ ' images ' ]
self . _branches = cfg [ ' branches ' ]
2019-04-19 01:59:31 +03:00
for _ , branch in self . _branches . items ( ) :
branch [ ' arches ' ] = { k : { } if v is None else v
for k , v in branch [ ' arches ' ] . items ( ) }
2019-03-28 03:28:51 +03:00
except KeyError as e :
msg = f ' Required parameter { e } does not set in config '
print ( msg , file = sys . stderr )
raise Exception ( msg )
def info ( self , msg : str ) - > None :
self . log . info ( msg )
def debug ( self , msg : str ) - > None :
self . log . debug ( msg )
def error ( self , msg : str ) - > None :
self . log . error ( msg )
raise Exception ( msg )
def remote ( self , branch : str ) - > str :
return self . _remote . format ( branch = branch )
2019-04-19 01:59:31 +03:00
def repository_url ( self , branch : str , arch : str ) - > str :
url = self . _branches [ branch ] [ ' arches ' ] [ arch ] . get ( ' repository_url ' )
if url is None :
url = self . _branches [ branch ] . get ( ' repository_url ' ,
self . _repository_url )
return url . format ( branch = branch , arch = arch )
2019-04-11 21:41:07 +03:00
2019-03-28 03:28:51 +03:00
def call (
self ,
cmd : List [ str ] ,
* ,
stdout_to_file : str = ' ' ,
fail_on_error : bool = True ,
) - > None :
def maybe_fail ( string : str , rc : int ) - > None :
if fail_on_error :
if rc != 0 :
msg = ' Command ` {} ` failed with {} return code ' . format (
string ,
rc ,
)
self . error ( msg )
# just_print = True
just_print = False
string = ' ' . join ( cmd )
self . debug ( f ' Call ` { string } ` ' )
if just_print :
print ( string )
else :
if stdout_to_file :
p = subprocess . Popen ( cmd , stdout = subprocess . PIPE )
rc = p . wait ( )
maybe_fail ( string , rc )
with open ( stdout_to_file , ' w ' ) as f :
f . write ( p . stdout . read ( ) . decode ( ) )
else :
rc = subprocess . call ( cmd )
maybe_fail ( string , rc )
def ensure_dirs ( self ) - > None :
for attr in dir ( self ) :
if attr . endswith ( ' _dir ' ) :
value = getattr ( self , attr )
if isinstance ( value , str ) :
os . makedirs ( value , exist_ok = True )
for branch in self . branches :
2019-09-04 04:45:39 +03:00
os . makedirs ( self . images_dir / branch , exist_ok = True )
2019-03-28 03:28:51 +03:00
2019-04-11 21:41:07 +03:00
def generate_apt_files ( self ) - > None :
2019-09-04 04:45:39 +03:00
apt_dir = self . work_dir / ' apt '
2019-04-11 21:41:07 +03:00
os . makedirs ( apt_dir , exist_ok = True )
for branch in self . branches :
for arch in self . arches_by_branch ( branch ) :
2019-04-19 01:59:31 +03:00
repo = self . repository_url ( branch , arch )
2019-04-11 21:41:07 +03:00
with open ( f ' { apt_dir } /apt.conf. { branch } . { arch } ' , ' w ' ) as f :
apt_conf = f '''
Dir : : Etc : : main " /dev/null " ;
Dir : : Etc : : parts " /var/empty " ;
Dir : : Etc : : SourceList " {apt_dir} /sources.list. {branch} . {arch} " ;
Dir : : Etc : : SourceParts " /var/empty " ;
Dir : : Etc : : preferences " /dev/null " ;
Dir : : Etc : : preferencesparts " /var/empty " ;
'''
f . write ( apt_conf )
with open ( f ' { apt_dir } /sources.list. { branch } . { arch } ' , ' w ' ) as f :
2019-04-19 17:01:56 +03:00
sources_list = f ' rpm { repo } { arch } classic \n '
2019-04-19 01:59:31 +03:00
if arch not in self . bad_arches :
2019-04-19 17:01:56 +03:00
sources_list + = f ' rpm { repo } noarch classic \n '
2019-04-11 21:41:07 +03:00
f . write ( sources_list )
2019-04-08 00:30:28 +03:00
def escape_branch ( self , branch : str ) - > str :
return re . sub ( r ' \ . ' , ' _ ' , branch )
2019-03-28 03:28:51 +03:00
def ensure_mkimage_profiles ( self , update : bool = False ) - > None :
""" Checks that mkimage-profiles exists or clones it """
2019-06-20 15:53:34 +03:00
def add_recipe ( variable : str , value : str ) - > str :
2019-04-11 01:17:56 +03:00
return f ' \n \t @$(call add, { variable } , { value } ) '
2019-03-28 03:28:51 +03:00
url = self . mkimage_profiles_git
2019-04-19 01:51:41 +03:00
if url == ' ' :
2019-03-28 03:28:51 +03:00
url = (
' git:// '
+ ' git.altlinux.org/ '
+ ' people/mike/packages/mkimage-profiles.git '
)
os . chdir ( self . work_dir )
if os . path . isdir ( ' mkimage-profiles ' ) :
if update :
with self . pushd ( ' mkimage-profiles ' ) :
self . info ( ' Updating mkimage-profiles ' )
self . call ( [ ' git ' , ' pull ' ] , fail_on_error = False )
else :
self . info ( ' Downloading mkimage-profiles ' )
self . call ( [ ' git ' , ' clone ' , url , ' mkimage-profiles ' ] )
2019-04-04 00:14:39 +03:00
# create file with proper brandings
with self . pushd ( ' mkimage-profiles ' ) :
with open ( f ' conf.d/ { PROG } .mk ' , ' w ' ) as f :
for image in self . images :
target = self . target_by_image ( image )
for branch in self . branches :
2019-04-08 00:30:28 +03:00
ebranch = self . escape_branch ( branch )
2019-04-08 01:16:29 +03:00
2019-06-20 15:53:34 +03:00
prerequisites = [ target ]
prerequisites . extend (
self . prerequisites_by_branch ( branch )
)
2019-06-20 16:34:43 +03:00
prerequisites . extend (
self . prerequisites_by_image ( image )
)
2019-06-20 15:53:34 +03:00
prerequisites_s = ' ' . join ( prerequisites )
2019-04-08 01:16:29 +03:00
branding = self . branding_by_branch ( branch )
if branding :
branding = f ' \n \t @$(call set,BRANDING, { branding } ) '
2019-06-20 15:53:34 +03:00
recipes = [ branding ]
2019-04-08 01:16:29 +03:00
2019-04-08 14:19:40 +03:00
for package in self . packages ( image , branch ) :
2019-06-20 15:53:34 +03:00
recipes . append (
add_recipe (
' BASE_PACKAGES ' ,
package ) )
2019-04-11 01:17:56 +03:00
for service in self . enabled_services ( image , branch ) :
2019-06-20 15:53:34 +03:00
recipes . append (
add_recipe (
' DEFAULT_SERVICES_ENABLE ' ,
service ) )
2019-04-11 01:17:56 +03:00
for service in self . disabled_services ( image , branch ) :
2019-06-20 15:53:34 +03:00
recipes . append (
add_recipe (
' DEFAULT_SERVICES_DISABLE ' ,
service ) )
2019-04-11 01:17:56 +03:00
2019-06-20 15:53:34 +03:00
recipes_s = ' ' . join ( recipes )
2019-04-08 01:16:29 +03:00
2019-06-20 15:53:34 +03:00
rule = f '''
{ target } _ { ebranch } : { prerequisites_s } ; @ : { recipes_s }
''' .strip()
print ( rule , file = f )
2019-04-04 00:14:39 +03:00
2019-04-11 21:41:07 +03:00
self . generate_apt_files ( )
2019-03-28 03:28:51 +03:00
@property
def branches ( self ) - > List [ str ] :
return list ( self . _branches . keys ( ) )
def arches_by_branch ( self , branch : str ) - > List [ str ] :
2019-04-19 01:59:31 +03:00
return list ( self . _branches [ branch ] [ ' arches ' ] . keys ( ) )
2019-04-08 01:16:29 +03:00
def branding_by_branch ( self , branch : str ) - > str :
return self . _branches [ branch ] . get ( ' branding ' , ' ' )
2019-06-20 15:53:34 +03:00
def prerequisites_by_branch ( self , branch : str ) - > List [ str ] :
return self . _branches [ branch ] . get ( ' prerequisites ' , [ ] )
2019-03-28 03:28:51 +03:00
@property
def images ( self ) - > List [ str ] :
return list ( self . _images . keys ( ) )
def kinds_by_image ( self , image : str ) - > List [ str ] :
2019-04-08 01:21:09 +03:00
return self . _images [ image ] [ ' kinds ' ]
2019-03-28 03:28:51 +03:00
def target_by_image ( self , image : str ) - > str :
return self . _images [ image ] [ ' target ' ]
2019-06-20 16:34:43 +03:00
def prerequisites_by_image ( self , image : str ) - > List [ str ] :
return self . _images [ image ] . get ( ' prerequisites ' , [ ] )
2019-07-08 02:14:01 +03:00
def tests_by_image ( self , image : str ) - > List [ Dict ] :
return self . _images [ image ] . get ( ' tests ' , [ ] )
2019-06-25 20:59:26 +03:00
def scripts_by_image ( self , image : str ) - > Dict [ str , str ] :
scripts = { }
2019-06-27 01:37:25 +03:00
for name , value in self . _scripts . items ( ) :
number = value . get ( ' number ' )
if (
value . get ( ' global ' , False )
and name not in self . _images [ image ] . get ( ' no_scripts ' , [ ] )
or name in self . _images [ image ] . get ( ' scripts ' , [ ] )
) :
if number is not None :
if isinstance ( number , int ) :
number = f ' { number : 02 } '
name = f ' { number } - { name } '
scripts [ name ] = value [ ' contents ' ]
2019-06-25 20:59:26 +03:00
return scripts
2019-03-28 03:28:51 +03:00
def skip_arch ( self , image : str , arch : str ) - > bool :
2019-04-19 15:59:27 +03:00
return arch in self . _images [ image ] . get ( ' exclude_arches ' , [ ] )
2019-03-28 03:28:51 +03:00
2019-04-11 01:17:56 +03:00
def get_items (
self ,
data : Dict ,
image : str ,
branch : str ,
state_re : str = None ,
default_state : str = None ,
) - > List [ str ] :
items = [ ]
if state_re is None :
state_re = ' '
if default_state is None :
default_state = state_re
for item , constraints in data . items ( ) :
if (
image in constraints . get ( ' exclude_images ' , [ ] )
or branch in constraints . get ( ' exclude_branches ' , [ ] )
) :
2019-04-08 14:19:40 +03:00
continue
# Empty means no constraint: e.g. all images
images = constraints . get ( ' images ' , [ image ] )
branches = constraints . get ( ' branch ' , [ branch ] )
2019-04-11 01:17:56 +03:00
state = constraints . get ( ' state ' , default_state )
if (
image in images
and branch in branches
and re . match ( state_re , state )
) :
items . append ( item )
2019-04-08 14:19:40 +03:00
2019-04-11 01:17:56 +03:00
return items
def packages ( self , image : str , branch : str ) - > List [ str ] :
return self . get_items ( self . _packages , image , branch )
def enabled_services ( self , image : str , branch : str ) - > List [ str ] :
return self . get_items (
self . _services ,
image ,
branch ,
' enabled? ' ,
self . service_default_state ,
)
def disabled_services ( self , image : str , branch : str ) - > List [ str ] :
return self . get_items (
self . _services ,
image ,
branch ,
' disabled? ' ,
self . service_default_state ,
)
2019-04-08 01:16:29 +03:00
2019-03-28 03:28:51 +03:00
def build_tarball (
self ,
target : str ,
branch : str ,
arch : str ,
kind : str
2019-09-04 04:45:39 +03:00
) - > Path :
2019-03-28 03:28:51 +03:00
self . ensure_mkimage_profiles ( )
2019-04-08 00:30:28 +03:00
target = f ' { target } _ { self . escape_branch ( branch ) } '
2019-03-28 03:28:51 +03:00
image = re . sub ( r ' .*/ ' , ' ' , target )
full_target = f ' { target } . { kind } '
2019-09-04 04:45:39 +03:00
tarball = self . out_dir / f ' { image } - { self . date } - { arch } . { kind } '
apt_dir = self . work_dir / ' apt '
with self . pushd ( self . work_dir / ' mkimage-profiles ' ) :
if tarball . exists ( ) :
2019-04-04 00:14:39 +03:00
self . info ( f ' Skip building of { full_target } { arch } ' )
2019-03-28 03:28:51 +03:00
else :
cmd = [
' make ' ,
f ' APTCONF= { apt_dir } /apt.conf. { branch } . { arch } ' ,
f ' ARCH= { arch } ' ,
2019-09-04 04:45:39 +03:00
f ' IMAGE_OUTDIR= { self . out_dir } ' ,
2019-03-28 03:28:51 +03:00
full_target ,
]
2019-04-04 00:14:39 +03:00
self . info ( f ' Begin building of { full_target } { arch } ' )
2019-03-28 03:28:51 +03:00
self . call ( cmd )
if os . path . exists ( tarball ) :
2019-04-04 00:14:39 +03:00
self . info ( f ' End building of { full_target } { arch } ' )
2019-03-28 03:28:51 +03:00
else :
2019-04-04 00:14:39 +03:00
self . error ( f ' Fail building of { full_target } { arch } ' )
2019-03-28 03:28:51 +03:00
return tarball
2019-09-04 04:45:39 +03:00
def image_path (
self ,
image : str ,
branch : str ,
arch : str ,
kind : str
) - > Path :
path = (
self . images_dir
/ branch
/ f ' alt- { branch . lower ( ) } - { image } - { arch } . { kind } '
2019-03-28 03:28:51 +03:00
)
return path
2019-09-04 04:45:39 +03:00
def copy_image ( self , src : Path , dst : Path ) - > None :
2019-03-28 03:28:51 +03:00
os . link ( src , dst )
2019-04-04 00:09:26 +03:00
def clear_imager_dir ( self ) :
for branch in self . branches :
2019-09-04 04:45:39 +03:00
directory = self . images_dir / branch
2019-09-07 01:10:16 +03:00
for path in directory . iterdir ( ) :
2019-09-04 04:45:39 +03:00
os . unlink ( path )
2019-04-04 00:09:26 +03:00
2019-05-30 00:21:31 +03:00
def remove_old_tarballs ( self ) :
with self . pushd ( self . out_dir ) :
for tb in os . listdir ( ) :
if not re . search ( f ' - { self . date } - ' , tb ) :
os . unlink ( tb )
2019-06-25 20:59:26 +03:00
def ensure_scripts ( self , image ) :
for name in self . created_scripts :
os . unlink ( name )
self . created_scripts = [ ]
target_type = re . sub ( r ' (?:( \ w+)/)?.* ' , r ' \ 1 ' ,
self . target_by_image ( image ) )
if not target_type :
target_type = ' distro '
2019-09-04 04:45:39 +03:00
scripts_path = (
self . work_dir
/ ' mkimage-profiles '
/ ' features.in '
/ f ' build- { target_type } '
/ ' image-scripts.d '
)
2019-06-25 20:59:26 +03:00
for name , content in self . scripts_by_image ( image ) . items ( ) :
2019-09-04 04:45:39 +03:00
script = scripts_path / name
self . created_scripts . append ( script )
script . write_text ( content )
os . chmod ( script , 0o755 )
2019-06-25 20:59:26 +03:00
2019-03-28 03:28:51 +03:00
def create_images ( self ) - > None :
2019-04-04 00:09:26 +03:00
self . clear_imager_dir ( )
2019-03-28 03:28:51 +03:00
for branch in self . branches :
for image in self . images :
2019-06-25 20:59:26 +03:00
self . ensure_scripts ( image )
2019-03-28 03:28:51 +03:00
target = self . target_by_image ( image )
for arch in self . arches_by_branch ( branch ) :
if self . skip_arch ( image , arch ) :
continue
for kind in self . kinds_by_image ( image ) :
tarball = self . build_tarball (
target , branch , arch , kind ,
)
image_path = self . image_path ( image , branch , arch , kind )
self . copy_image ( tarball , image_path )
2019-11-01 16:44:46 +03:00
if not self . args . no_tests :
for test in self . tests_by_image ( image ) :
self . info ( f ' Test { image } { branch } { arch } ' )
if not cloud_build . image_tests . test (
image = image_path ,
branch = branch ,
arch = arch ,
* * test ,
) :
self . error ( f ' Test for { image } failed ' )
2019-03-28 03:28:51 +03:00
2019-05-30 00:21:31 +03:00
self . remove_old_tarballs ( )
2019-09-07 01:18:04 +03:00
def copy_external_images ( self ) :
if self . external_images :
for branch in os . listdir ( self . external_images ) :
if branch not in self . branches :
self . error ( f ' Unknown branch { branch } in external_images ' )
with self . pushd ( self . external_images / branch ) :
for image in os . listdir ( ) :
2019-11-04 19:35:54 +03:00
self . info ( f ' Copy external image { image } in { branch } ' )
2019-09-07 01:18:04 +03:00
self . copy_image ( image ,
self . images_dir / branch / image )
2019-09-07 00:34:55 +03:00
def sign ( self ) :
sum_file = self . checksum_command . upper ( )
2019-11-01 14:22:56 +03:00
for branch in self . branches :
2019-09-07 00:34:55 +03:00
with self . pushd ( self . images_dir / branch ) :
files = [ f
for f in os . listdir ( )
if not f . startswith ( sum_file ) ]
string = ' , ' . join ( files )
2019-03-28 03:28:51 +03:00
2019-09-07 00:34:55 +03:00
cmd = [ self . checksum_command ] + files
self . info ( f ' Calculate checksum of { string } ' )
self . call ( cmd , stdout_to_file = sum_file )
2019-03-28 03:28:51 +03:00
2019-09-07 00:34:55 +03:00
self . info ( f ' Sign checksum of { string } ' )
self . call ( [ ' gpg2 ' , ' --yes ' , ' -basu ' , self . key , sum_file ] )
2019-03-28 03:28:51 +03:00
2019-04-04 03:37:19 +03:00
def kick ( self ) :
remote = self . _remote
colon = remote . find ( ' : ' )
if colon != - 1 :
host = remote [ : colon ]
self . call ( [ ' ssh ' , host , ' kick ' ] )
2019-03-28 03:28:51 +03:00
def sync ( self ) - > None :
for branch in self . branches :
remote = self . remote ( branch )
2019-09-04 04:45:39 +03:00
files = glob . glob ( f ' { self . images_dir } / { branch } /* ' )
2019-09-09 20:43:35 +03:00
cmd = [ ' rsync ' , ' -v ' ] + files + [ remote ]
self . call ( cmd )
2019-03-28 03:28:51 +03:00
2019-04-04 03:37:19 +03:00
self . kick ( )
2019-03-28 03:28:51 +03:00
def get_data_dir ( ) - > str :
data_dir = ( os . getenv ( ' XDG_DATA_HOME ' ,
os . path . expanduser ( ' ~/.local/share ' ) )
+ f ' / { PROG } / ' )
return data_dir
def parse_args ( ) :
parser = argparse . ArgumentParser (
formatter_class = argparse . ArgumentDefaultsHelpFormatter ,
)
parser . add_argument (
' -c ' ,
' --config ' ,
default = f ' /etc/ { PROG } /config.yaml ' ,
help = ' path to config ' ,
)
parser . add_argument (
' -d ' ,
' --data-dir ' ,
default = f ' /usr/share/ { PROG } ' ,
help = ' system data directory ' ,
)
2019-11-01 16:44:46 +03:00
parser . add_argument (
' --no-tests ' ,
action = ' store_true ' ,
help = ' disable running tests ' ,
)
2019-03-28 03:28:51 +03:00
args = parser . parse_args ( )
if not args . data_dir . endswith ( ' / ' ) :
args . data_dir + = ' / '
return args
def main ( ) :
args = parse_args ( )
2019-11-01 16:44:46 +03:00
cloud_build = CB ( args )
2019-09-07 00:34:55 +03:00
cloud_build . create_images ( )
2019-11-04 19:35:54 +03:00
cloud_build . copy_external_images ( )
2019-09-07 00:34:55 +03:00
cloud_build . sign ( )
2019-03-28 03:28:51 +03:00
cloud_build . sync ( )
if __name__ == ' __main__ ' :
main ( )