github.com/leg100/ots@v0.0.7-0.20210919080622-034055ced4bd/sqlite/plan_model.go (about)

     1  package sqlite
     2  
     3  import (
     4  	"database/sql"
     5  
     6  	"github.com/leg100/go-tfe"
     7  	"github.com/leg100/ots"
     8  	"gorm.io/gorm"
     9  )
    10  
    11  // Plan models a row in a runs table.
    12  type Plan struct {
    13  	gorm.Model
    14  
    15  	ExternalID string `gorm:"uniqueIndex"`
    16  
    17  	ResourceAdditions    int
    18  	ResourceChanges      int
    19  	ResourceDestructions int
    20  	Status               tfe.PlanStatus
    21  	StatusTimestamps     *PlanStatusTimestamps `gorm:"embedded;embeddedPrefix:timestamp_"`
    22  
    23  	// The blob ID of the logs
    24  	LogsBlobID string
    25  
    26  	// The blob ID of the execution plan file
    27  	PlanFileBlobID string
    28  
    29  	// The blob ID of the execution plan file in json format
    30  	PlanJSONBlobID string
    31  
    32  	// Plan belongs to a run
    33  	RunID uint
    34  }
    35  
    36  // PlanStatusTimestamps holds the timestamps for individual plan statuses.
    37  type PlanStatusTimestamps struct {
    38  	CanceledAt      sql.NullTime
    39  	ErroredAt       sql.NullTime
    40  	FinishedAt      sql.NullTime
    41  	ForceCanceledAt sql.NullTime
    42  	QueuedAt        sql.NullTime
    43  	StartedAt       sql.NullTime
    44  }
    45  
    46  // PlanList is a list of run models
    47  type PlanList []Plan
    48  
    49  // Update updates the model with the supplied fn. The fn operates on the domain
    50  // obj, so Update handles converting to and from a domain obj.
    51  func (model *Plan) Update(fn func(*ots.Plan) error) error {
    52  	// model -> domain
    53  	domain := model.ToDomain()
    54  
    55  	// invoke user fn
    56  	if err := fn(domain); err != nil {
    57  		return err
    58  	}
    59  
    60  	// domain -> model
    61  	model.FromDomain(domain)
    62  
    63  	return nil
    64  }
    65  
    66  func (model *Plan) ToDomain() *ots.Plan {
    67  	domain := ots.Plan{
    68  		ID:                   model.ExternalID,
    69  		Model:                model.Model,
    70  		ResourceAdditions:    model.ResourceAdditions,
    71  		ResourceChanges:      model.ResourceChanges,
    72  		ResourceDestructions: model.ResourceDestructions,
    73  		Status:               model.Status,
    74  		StatusTimestamps:     &tfe.PlanStatusTimestamps{},
    75  		LogsBlobID:           model.LogsBlobID,
    76  		PlanFileBlobID:       model.PlanFileBlobID,
    77  		PlanJSONBlobID:       model.PlanJSONBlobID,
    78  	}
    79  
    80  	if model.StatusTimestamps.CanceledAt.Valid {
    81  		domain.StatusTimestamps.CanceledAt = &model.StatusTimestamps.CanceledAt.Time
    82  	}
    83  
    84  	if model.StatusTimestamps.ErroredAt.Valid {
    85  		domain.StatusTimestamps.ErroredAt = &model.StatusTimestamps.ErroredAt.Time
    86  	}
    87  
    88  	if model.StatusTimestamps.FinishedAt.Valid {
    89  		domain.StatusTimestamps.FinishedAt = &model.StatusTimestamps.FinishedAt.Time
    90  	}
    91  
    92  	if model.StatusTimestamps.ForceCanceledAt.Valid {
    93  		domain.StatusTimestamps.ForceCanceledAt = &model.StatusTimestamps.ForceCanceledAt.Time
    94  	}
    95  
    96  	if model.StatusTimestamps.QueuedAt.Valid {
    97  		domain.StatusTimestamps.QueuedAt = &model.StatusTimestamps.QueuedAt.Time
    98  	}
    99  
   100  	if model.StatusTimestamps.StartedAt.Valid {
   101  		domain.StatusTimestamps.StartedAt = &model.StatusTimestamps.StartedAt.Time
   102  	}
   103  
   104  	return &domain
   105  }
   106  
   107  // FromDomain updates run model fields with a run domain object's fields
   108  func (model *Plan) FromDomain(domain *ots.Plan) {
   109  	model.ExternalID = domain.ID
   110  	model.Model = domain.Model
   111  	model.ResourceAdditions = domain.ResourceAdditions
   112  	model.ResourceChanges = domain.ResourceChanges
   113  	model.ResourceDestructions = domain.ResourceDestructions
   114  	model.Status = domain.Status
   115  	model.LogsBlobID = domain.LogsBlobID
   116  	model.PlanFileBlobID = domain.PlanFileBlobID
   117  	model.PlanJSONBlobID = domain.PlanJSONBlobID
   118  
   119  	if domain.StatusTimestamps.CanceledAt != nil {
   120  		model.StatusTimestamps.CanceledAt.Time = *domain.StatusTimestamps.CanceledAt
   121  		model.StatusTimestamps.CanceledAt.Valid = true
   122  	}
   123  
   124  	if domain.StatusTimestamps.ErroredAt != nil {
   125  		model.StatusTimestamps.ErroredAt.Time = *domain.StatusTimestamps.ErroredAt
   126  		model.StatusTimestamps.ErroredAt.Valid = true
   127  	}
   128  
   129  	if domain.StatusTimestamps.FinishedAt != nil {
   130  		model.StatusTimestamps.FinishedAt.Time = *domain.StatusTimestamps.FinishedAt
   131  		model.StatusTimestamps.FinishedAt.Valid = true
   132  	}
   133  
   134  	if domain.StatusTimestamps.ForceCanceledAt != nil {
   135  		model.StatusTimestamps.ForceCanceledAt.Time = *domain.StatusTimestamps.ForceCanceledAt
   136  		model.StatusTimestamps.ForceCanceledAt.Valid = true
   137  	}
   138  
   139  	if domain.StatusTimestamps.QueuedAt != nil {
   140  		model.StatusTimestamps.QueuedAt.Time = *domain.StatusTimestamps.QueuedAt
   141  		model.StatusTimestamps.QueuedAt.Valid = true
   142  	}
   143  
   144  	if domain.StatusTimestamps.StartedAt != nil {
   145  		model.StatusTimestamps.StartedAt.Time = *domain.StatusTimestamps.StartedAt
   146  		model.StatusTimestamps.StartedAt.Valid = true
   147  	}
   148  }
   149  
   150  func (l PlanList) ToDomain() (dl []*ots.Plan) {
   151  	for _, i := range l {
   152  		dl = append(dl, i.ToDomain())
   153  	}
   154  	return
   155  }