@@ -270,7 +270,7 @@ def restart(self, **kwargs): # noqa
270270 def scale (self , user , structure ):
271271 err_msg = None
272272 release = Release .latest (self )
273- if (PTYPE_RUN in structure or release .build is None ):
273+ if (PTYPE_RUN in structure or release is None or release .build is None ):
274274 if PTYPE_RUN in structure :
275275 err_msg = 'Cannot set scale for reserved types, procfile type is: run'
276276 else :
@@ -283,7 +283,7 @@ def scale(self, user, structure):
283283 def pipeline (self , release , ptypes , force_deploy = False ):
284284 prefix = f"[pipeline] release { release .version_name } "
285285 try :
286- if release .build is not None :
286+ if release is not None and release .build is not None :
287287 if release .build .dryccfile :
288288 for run in release .get_runners (ptypes ):
289289 self .log (f"{ prefix } starts running pipeline.run { run ['image' ]} " )
@@ -323,7 +323,7 @@ def deploy(self, release, ptypes=None, force_deploy=False, rollback_on_failure=T
323323
324324 force_deploy can be used when a deployment is broken, such as for Rollback
325325 """
326- if release .build is None :
326+ if release is None or release .build is None :
327327 raise DryccException ('No build associated with this release' )
328328 # use create to make sure minimum resources are created
329329 self .create ()
@@ -352,7 +352,7 @@ def mount(self, user, volume, structure=None):
352352 if release is None or release .build is None :
353353 raise DryccException ('No build associated with this release' )
354354 app_settings = self .appsettings_set .latest ()
355- self ._mount (user , volume , release , app_settings , structure = structure )
355+ self ._mount (user , volume , app_settings , structure = structure )
356356
357357 def clean (self , release = None , ptypes = None ):
358358 release = release if release else self .release_set .latest ()
@@ -431,17 +431,21 @@ def get_command_and_args(pod, container_name):
431431 result = []
432432 try :
433433 pod = self .scheduler ().pod .get (self .id , pod_name ).json ()
434- for status in pod ["status" ]["containerStatuses" ]:
434+ if pod ["status" ]['phase' ] == 'Pending' :
435+ statuses = pod ["spec" ]["containers" ]
436+ else :
437+ statuses = pod ["status" ]["containerStatuses" ]
438+ for status in statuses :
435439 command , args = get_command_and_args (pod , status ["name" ])
436440 result .append ({
437441 "container" : status ["name" ],
438442 "image" : status ["image" ],
439443 "command" : command ,
440444 "args" : args ,
441- "state" : status [ "state" ] ,
442- "lastState" : status [ "lastState" ] ,
443- "ready" : status [ "ready" ] ,
444- "restartCount" : status [ "restartCount" ] ,
445+ "state" : status . get ( "state" , {}) ,
446+ "lastState" : status . get ( "lastState" , {}) ,
447+ "ready" : status . get ( "ready" , False ) ,
448+ "restartCount" : status . get ( "restartCount" , 0 ) ,
445449 "status" : pod ["status" ].get ("phase" , "" ),
446450 "reason" : pod ["status" ].get ("reason" , "" ),
447451 "message" : pod ["status" ].get ("message" , "" )
@@ -470,15 +474,22 @@ def list_pods(self, *args, **kwargs):
470474 else :
471475 started = str (
472476 datetime .now (timezone .utc ).strftime (settings .DRYCC_DATETIME_FORMAT ))
477+ state = str (self .scheduler ().pod .state (p ))
478+ if p ['status' ]['phase' ] != 'Pending' :
479+ ready = len ([1 for s in p ["status" ]["containerStatuses" ] if s ['ready' ]])
480+ restarts = sum ([s ['restartCount' ] for s in p ["status" ]["containerStatuses" ]])
481+ else :
482+ restarts = 0
483+ ready = 0
473484 item = {
474- 'name' : p ['metadata' ]['name' ], 'state' : str (self .scheduler ().pod .state (p )),
485+ 'name' : p ['metadata' ]['name' ],
486+ 'state' : state ,
475487 'release' : labels ['version' ], 'type' : labels ['type' ], 'started' : started ,
476488 'ready' : "%s/%s" % (
477- len ([ 1 for s in p [ "status" ][ "containerStatuses" ] if s [ ' ready' ]]) ,
478- len (p ["status " ]["containerStatuses " ]),
489+ ready ,
490+ len (p ["spec " ]["containers " ]),
479491 ),
480- 'restarts' : sum (
481- [s ['restartCount' ] for s in p ["status" ]["containerStatuses" ]]),
492+ 'restarts' : restarts
482493 }
483494 data .append (item )
484495 # sorting so latest start date is first
@@ -626,12 +637,12 @@ def autoscale(self, proc_type, autoscale):
626637 # let the user know about any other errors
627638 raise ServiceUnavailable (str (e )) from e
628639
629- def image_pull_secret (self , namespace , registry , image ):
640+ def image_pull_secret (self , namespace , ptype , registry , image ):
630641 """
631642 Take registry information and set as an imagePullSecret for an RC / Deployment
632643 http://kubernetes.io/docs/user-guide/images/#specifying-imagepullsecrets-on-a-pod
633644 """
634- docker_config , name , create = self ._get_private_registry_config (image , registry )
645+ docker_config , name , create = self ._get_private_registry_config (ptype , image , registry )
635646 if create is None :
636647 return
637648 elif create :
@@ -741,11 +752,14 @@ def _clean_app_logs(self):
741752 err = 'Error deleting existing application logs: {}' .format (e )
742753 self .log (err , logging .WARNING )
743754
744- def _mount (self , user , volume , release , app_settings , structure = None ):
755+ def _mount (self , user , volume , app_settings , structure = None ):
745756 volumes = Volume .objects .filter (app = self )
746757 tasks = []
747758 for scale_type , replicas in structure .items () if structure else self .structure .items ():
748759 if scale_type != PTYPE_RUN :
760+ release = self .release_set .filter (
761+ deployed_ptypes__contains = scale_type ,
762+ failed = False ).latest ()
749763 replicas = self .structure .get (scale_type , 0 )
750764 scale_type_volumes = [
751765 volume for volume in volumes if scale_type in volume .path .keys ()]
@@ -810,7 +824,7 @@ def _deploy(self, deploys, ptypes, prev_release,
810824 except KubeException as e :
811825 # Don't rollback if the previous release doesn't have a build which means
812826 # this is the first build and all the previous releases are just config changes.
813- if ( rollback_on_failure and prev_release .build is not None ):
827+ if rollback_on_failure and prev_release is not None and prev_release .build is not None : # noqa
814828 err = 'There was a problem deploying {}. Rolling back to release {}.' .format (
815829 release .version_name , prev_release .version_name )
816830 # This goes in the log before the rollback starts
@@ -1098,7 +1112,7 @@ def _build_env_vars(self, release, ptype):
10981112 Build a dict of env vars, setting default vars based on app type
10991113 and then combining with the user set ones
11001114 """
1101- if release .build is None :
1115+ if release is None or release .build is None :
11021116 raise DryccException ('No build associated with this release to run this command' )
11031117
11041118 # mix in default environment information drycc may require
@@ -1119,8 +1133,8 @@ def _build_env_vars(self, release, ptype):
11191133 default_env ['PORT' ] = port
11201134 return default_env
11211135
1122- def _get_private_registry_config (self , image , registry = None ):
1123- name = settings .REGISTRY_SECRET_PREFIX
1136+ def _get_private_registry_config (self , ptype , image , registry = None ):
1137+ name = settings .REGISTRY_SECRET_PREFIX + '-' + ptype
11241138 if registry :
11251139 # try to get the hostname information
11261140 hostname = registry .get ('hostname' , None )
@@ -1206,7 +1220,7 @@ def _gather_app_settings(self, release, app_settings, ptype, replicas, volumes=N
12061220 registry = config .registry .get (ptype , {})
12071221 # create image pull secret if needed
12081222 image_pull_secret_name = self .image_pull_secret (
1209- self .id , registry , release .get_deploy_image (ptype ))
1223+ self .id , ptype , registry , release .get_deploy_image (ptype ))
12101224
12111225 # only web is routable
12121226 # https://www.drycc.cc/applications/managing-app-processes/#default-process-types
0 commit comments