github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/orchestrator/service.go (about)

     1  package orchestrator
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/docker/swarmkit/api"
     7  	"github.com/docker/swarmkit/log"
     8  	"github.com/docker/swarmkit/manager/state/store"
     9  )
    10  
    11  // IsReplicatedService checks if a service is a replicated service.
    12  func IsReplicatedService(service *api.Service) bool {
    13  	// service nil validation is required as there are scenarios
    14  	// where service is removed from store
    15  	if service == nil {
    16  		return false
    17  	}
    18  	_, ok := service.Spec.GetMode().(*api.ServiceSpec_Replicated)
    19  	return ok
    20  }
    21  
    22  // IsGlobalService checks if the service is a global service.
    23  func IsGlobalService(service *api.Service) bool {
    24  	if service == nil {
    25  		return false
    26  	}
    27  	_, ok := service.Spec.GetMode().(*api.ServiceSpec_Global)
    28  	return ok
    29  }
    30  
    31  // IsReplicatedJob returns true if the service is a replicated job.
    32  func IsReplicatedJob(service *api.Service) bool {
    33  	if service == nil {
    34  		return false
    35  	}
    36  
    37  	_, ok := service.Spec.GetMode().(*api.ServiceSpec_ReplicatedJob)
    38  	return ok
    39  }
    40  
    41  // IsGlobalJob returns true if the service is a global job.
    42  func IsGlobalJob(service *api.Service) bool {
    43  	if service == nil {
    44  		return false
    45  	}
    46  
    47  	_, ok := service.Spec.GetMode().(*api.ServiceSpec_GlobalJob)
    48  	return ok
    49  }
    50  
    51  // SetServiceTasksRemove sets the desired state of tasks associated with a service
    52  // to REMOVE, so that they can be properly shut down by the agent and later removed
    53  // by the task reaper.
    54  func SetServiceTasksRemove(ctx context.Context, s *store.MemoryStore, service *api.Service) {
    55  	var (
    56  		tasks []*api.Task
    57  		err   error
    58  	)
    59  	s.View(func(tx store.ReadTx) {
    60  		tasks, err = store.FindTasks(tx, store.ByServiceID(service.ID))
    61  	})
    62  	if err != nil {
    63  		log.G(ctx).WithError(err).Errorf("failed to list tasks")
    64  		return
    65  	}
    66  
    67  	err = s.Batch(func(batch *store.Batch) error {
    68  		for _, t := range tasks {
    69  			err := batch.Update(func(tx store.Tx) error {
    70  				// the task may have changed for some reason in the meantime
    71  				// since we read it out, so we need to get from the store again
    72  				// within the boundaries of a transaction
    73  				latestTask := store.GetTask(tx, t.ID)
    74  
    75  				// time travel is not allowed. if the current desired state is
    76  				// above the one we're trying to go to we can't go backwards.
    77  				// we have nothing to do and we should skip to the next task
    78  				if latestTask.DesiredState > api.TaskStateRemove {
    79  					// log a warning, though. we shouln't be trying to rewrite
    80  					// a state to an earlier state
    81  					log.G(ctx).Warnf(
    82  						"cannot update task %v in desired state %v to an earlier desired state %v",
    83  						latestTask.ID, latestTask.DesiredState, api.TaskStateRemove,
    84  					)
    85  					return nil
    86  				}
    87  				// update desired state to REMOVE
    88  				latestTask.DesiredState = api.TaskStateRemove
    89  
    90  				if err := store.UpdateTask(tx, latestTask); err != nil {
    91  					log.G(ctx).WithError(err).Errorf("failed transaction: update task desired state to REMOVE")
    92  				}
    93  				return nil
    94  			})
    95  			if err != nil {
    96  				return err
    97  			}
    98  		}
    99  		return nil
   100  	})
   101  	if err != nil {
   102  		log.G(ctx).WithError(err).Errorf("task search transaction failed")
   103  	}
   104  }