@@ -625,7 +625,7 @@ def describe(self):
625
625
626
626
627
627
class _LocalPipeline (object ):
628
- """Placeholder docstring """
628
+ """Class representing a local SageMaker Pipeline """
629
629
630
630
_executions = {}
631
631
@@ -645,7 +645,7 @@ def __init__(
645
645
self .last_modified_time = now_time
646
646
647
647
def describe (self ):
648
- """Placeholder docstring """
648
+ """Describe Pipeline """
649
649
response = {
650
650
"PipelineArn" : self .pipeline .name ,
651
651
"PipelineDefinition" : self .pipeline .definition (),
@@ -659,7 +659,7 @@ def describe(self):
659
659
return response
660
660
661
661
def start (self , ** kwargs ):
662
- """Placeholder docstring """
662
+ """Start a pipeline execution. Returns a _LocalPipelineExecution object. """
663
663
from sagemaker .local .pipeline import LocalPipelineExecutor
664
664
665
665
execution_id = str (uuid4 ())
@@ -670,7 +670,7 @@ def start(self, **kwargs):
670
670
671
671
672
672
class _LocalPipelineExecution (object ):
673
- """Placeholder docstring """
673
+ """Class representing a local SageMaker pipeline execution. """
674
674
675
675
def __init__ (
676
676
self ,
@@ -693,7 +693,7 @@ def __init__(
693
693
self .blockout_steps = {}
694
694
695
695
def describe (self ):
696
- """Placeholder docstring """
696
+ """Describe Pipeline Execution. """
697
697
response = {
698
698
"CreationTime" : self .creation_time ,
699
699
"LastModifiedTime" : self .creation_time ,
@@ -708,8 +708,14 @@ def describe(self):
708
708
return filtered_response
709
709
710
710
def list_steps (self ):
711
- """Placeholder docstring"""
712
- # TODO
711
+ """List pipeline execution steps."""
712
+ return {
713
+ "PipelineExecutionSteps" : [
714
+ step .to_list_steps_response ()
715
+ for step in self .step_execution .values ()
716
+ if step .status is not None
717
+ ]
718
+ }
713
719
714
720
def update_execution_success (self ):
715
721
"""Mark execution as succeeded."""
@@ -730,8 +736,8 @@ def update_step_failure(self, step_name, failure_message):
730
736
self .step_execution .get (step_name ).update_step_failure (failure_message )
731
737
732
738
def mark_step_executing (self , step_name ):
733
- """Update step's status to EXECUTING"""
734
- self .step_execution .get (step_name ).status = _LocalExecutionStatus . EXECUTING . value
739
+ """Update pipelines step's status to EXECUTING and start_time to now. """
740
+ self .step_execution .get (step_name ).mark_step_executing ()
735
741
736
742
def _initialize_step_execution (self , steps ):
737
743
"""Initialize step_execution dict."""
@@ -751,7 +757,9 @@ def _initialize_step_execution(self, steps):
751
757
"Step type {} is not supported in local mode." .format (step .step_type .value )
752
758
)
753
759
raise ClientError (error_msg , "start_pipeline_execution" )
754
- self .step_execution [step .name ] = _LocalPipelineStepExecution (step .name , step .step_type )
760
+ self .step_execution [step .name ] = _LocalPipelineExecutionStep (
761
+ step .name , step .step_type , step .description , step .display_name
762
+ )
755
763
if step .step_type == StepTypeEnum .CONDITION :
756
764
self ._initialize_step_execution (step .if_steps + step .else_steps )
757
765
@@ -790,44 +798,105 @@ def _construct_validation_exception_message(exception_msg):
790
798
return {"Error" : {"Code" : "ValidationException" , "Message" : exception_msg }}
791
799
792
800
793
- class _LocalPipelineStepExecution (object ):
794
- """Placeholder docstring """
801
+ class _LocalPipelineExecutionStep (object ):
802
+ """Class representing a local pipeline execution step. """
795
803
796
804
def __init__ (
797
805
self ,
798
- step_name ,
806
+ name ,
799
807
step_type ,
800
- last_modified_time = None ,
808
+ description ,
809
+ display_name = None ,
810
+ start_time = None ,
811
+ end_time = None ,
801
812
status = None ,
802
813
properties = None ,
803
814
failure_reason = None ,
804
815
):
805
- self .step_name = step_name
806
- self .step_type = step_type
807
- self .status = status or _LocalExecutionStatus .STARTING .value
816
+ from sagemaker .workflow .steps import StepTypeEnum
817
+
818
+ self .name = name
819
+ self .type = step_type
820
+ self .description = description
821
+ self .display_name = display_name
822
+ self .status = status
808
823
self .failure_reason = failure_reason
809
824
self .properties = properties or {}
810
- self .creation_time = datetime .datetime .now ()
811
- self .last_modified_time = last_modified_time or self .creation_time
825
+ self .start_time = start_time
826
+ self .end_time = end_time
827
+ self ._step_type_to_output_format_map = {
828
+ StepTypeEnum .TRAINING : self ._construct_training_metadata ,
829
+ StepTypeEnum .PROCESSING : self ._construct_processing_metadata ,
830
+ StepTypeEnum .TRANSFORM : self ._construct_transform_metadata ,
831
+ StepTypeEnum .CONDITION : self ._construct_condition_metadata ,
832
+ StepTypeEnum .FAIL : self ._construct_fail_metadata ,
833
+ }
812
834
813
835
def update_step_properties (self , properties ):
814
836
"""Update pipeline step execution output properties."""
815
- logger .info ("Successfully completed step %s." , self .step_name )
837
+ logger .info ("Successfully completed step %s." , self .name )
816
838
self .properties = deepcopy (properties )
817
839
self .status = _LocalExecutionStatus .SUCCEEDED .value
840
+ self .end_time = datetime .datetime .now ()
818
841
819
842
def update_step_failure (self , failure_message ):
820
843
"""Update pipeline step execution failure status and message."""
821
844
logger .error (failure_message )
822
845
self .failure_reason = failure_message
823
846
self .status = _LocalExecutionStatus .FAILED .value
824
- raise StepExecutionException (self .step_name , failure_message )
847
+ self .end_time = datetime .datetime .now ()
848
+ raise StepExecutionException (self .name , failure_message )
849
+
850
+ def mark_step_executing (self ):
851
+ """Update pipelines step's status to EXECUTING and start_time to now"""
852
+ self .status = _LocalExecutionStatus .EXECUTING .value
853
+ self .start_time = datetime .datetime .now ()
854
+
855
+ def to_list_steps_response (self ):
856
+ """Convert to response dict for list_steps calls."""
857
+ response = {
858
+ "EndTime" : self .end_time ,
859
+ "FailureReason" : self .failure_reason ,
860
+ "Metadata" : self ._construct_metadata (),
861
+ "StartTime" : self .start_time ,
862
+ "StepDescription" : self .description ,
863
+ "StepDisplayName" : self .display_name ,
864
+ "StepName" : self .name ,
865
+ "StepStatus" : self .status ,
866
+ }
867
+ filtered_response = {k : v for k , v in response .items () if v is not None }
868
+ return filtered_response
869
+
870
+ def _construct_metadata (self ):
871
+ """Constructs the metadata shape for the list_steps_response."""
872
+ if self .properties :
873
+ return self ._step_type_to_output_format_map [self .type ]()
874
+ return None
875
+
876
+ def _construct_training_metadata (self ):
877
+ """Construct training job metadata response."""
878
+ return {"TrainingJob" : {"Arn" : self .properties .TrainingJobArn }}
879
+
880
+ def _construct_processing_metadata (self ):
881
+ """Construct processing job metadata response."""
882
+ return {"ProcessingJob" : {"Arn" : self .properties .ProcessingJobArn }}
883
+
884
+ def _construct_transform_metadata (self ):
885
+ """Construct transform job metadata response."""
886
+ return {"TransformJob" : {"Arn" : self .properties .TransformJobArn }}
887
+
888
+ def _construct_condition_metadata (self ):
889
+ """Construct condition step metadata response."""
890
+ return {"Condition" : {"Outcome" : self .properties .Outcome }}
891
+
892
+ def _construct_fail_metadata (self ):
893
+ """Construct fail step metadata response."""
894
+ return {"Fail" : {"ErrorMessage" : self .properties .ErrorMessage }}
825
895
826
896
827
897
class _LocalExecutionStatus (enum .Enum ):
828
- """Placeholder docstring """
898
+ """Pipeline execution status. """
829
899
830
- STARTING = "Starting"
831
900
EXECUTING = "Executing"
832
901
SUCCEEDED = "Succeeded"
833
902
FAILED = "Failed"
0 commit comments