github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/api/containerserver/list.go (about)

     1  package containerserver
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"strconv"
     8  	"time"
     9  
    10  	"code.cloudfoundry.org/lager"
    11  	"github.com/pf-qiu/concourse/v6/atc"
    12  	"github.com/pf-qiu/concourse/v6/atc/api/present"
    13  	"github.com/pf-qiu/concourse/v6/atc/creds"
    14  	"github.com/pf-qiu/concourse/v6/atc/db"
    15  )
    16  
    17  func (s *Server) ListContainers(team db.Team) http.Handler {
    18  	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    19  		params := r.URL.RawQuery
    20  		hLog := s.logger.Session("list-containers", lager.Data{
    21  			"params": params,
    22  		})
    23  
    24  		containerLocator, err := createContainerLocatorFromRequest(team, r, s.secretManager, s.varSourcePool)
    25  		if err != nil {
    26  			hLog.Error("failed-to-parse-request", err)
    27  			http.Error(w, err.Error(), http.StatusBadRequest)
    28  			return
    29  		}
    30  
    31  		w.Header().Set("Content-Type", "application/json")
    32  
    33  		hLog.Debug("listing-containers")
    34  
    35  		containers, checkContainersExpiresAt, err := containerLocator.Locate(hLog)
    36  		if err != nil {
    37  			hLog.Error("failed-to-find-containers", err)
    38  			w.WriteHeader(http.StatusInternalServerError)
    39  			return
    40  		}
    41  
    42  		hLog.Debug("listed", lager.Data{"container-count": len(containers)})
    43  
    44  		presentedContainers := make([]atc.Container, len(containers))
    45  		for i := 0; i < len(containers); i++ {
    46  			container := containers[i]
    47  			presentedContainers[i] = present.Container(container, checkContainersExpiresAt[container.ID()])
    48  		}
    49  
    50  		err = json.NewEncoder(w).Encode(presentedContainers)
    51  		if err != nil {
    52  			hLog.Error("failed-to-encode-containers", err)
    53  			w.WriteHeader(http.StatusInternalServerError)
    54  		}
    55  	})
    56  }
    57  
    58  type containerLocator interface {
    59  	Locate(lager.Logger) ([]db.Container, map[int]time.Time, error)
    60  }
    61  
    62  func createContainerLocatorFromRequest(team db.Team, r *http.Request, secretManager creds.Secrets, varSourcePool creds.VarSourcePool) (containerLocator, error) {
    63  	query := r.URL.Query()
    64  	delete(query, ":team_name")
    65  
    66  	if len(query) == 0 {
    67  		return &allContainersLocator{
    68  			team: team,
    69  		}, nil
    70  	}
    71  
    72  	var err error
    73  	pipelineRef := atc.PipelineRef{Name: query.Get("pipeline_name")}
    74  	if instanceVars := query.Get("instance_vars"); instanceVars != "" {
    75  		err := json.Unmarshal([]byte(instanceVars), &pipelineRef.InstanceVars)
    76  		if err != nil {
    77  			return nil, err
    78  		}
    79  	}
    80  
    81  	if query.Get("type") == "check" {
    82  		return &checkContainerLocator{
    83  			team:          team,
    84  			pipelineRef:   pipelineRef,
    85  			resourceName:  query.Get("resource_name"),
    86  			secretManager: secretManager,
    87  			varSourcePool: varSourcePool,
    88  		}, nil
    89  	}
    90  
    91  	var containerType db.ContainerType
    92  	if query.Get("type") != "" {
    93  		containerType, err = db.ContainerTypeFromString(query.Get("type"))
    94  		if err != nil {
    95  			return nil, err
    96  		}
    97  	}
    98  
    99  	pipelineID, err := parseIntParam(r, "pipeline_id")
   100  	if err != nil {
   101  		return nil, err
   102  	}
   103  
   104  	jobID, err := parseIntParam(r, "job_id")
   105  	if err != nil {
   106  		return nil, err
   107  	}
   108  
   109  	buildID, err := parseIntParam(r, "build_id")
   110  	if err != nil {
   111  		return nil, err
   112  	}
   113  
   114  	return &stepContainerLocator{
   115  		team: team,
   116  
   117  		metadata: db.ContainerMetadata{
   118  			Type: containerType,
   119  
   120  			StepName: query.Get("step_name"),
   121  			Attempt:  query.Get("attempt"),
   122  
   123  			PipelineID: pipelineID,
   124  			JobID:      jobID,
   125  			BuildID:    buildID,
   126  
   127  			PipelineName:         query.Get("pipeline_name"),
   128  			PipelineInstanceVars: query.Get("pipeline_instance_vars"),
   129  			JobName:              query.Get("job_name"),
   130  			BuildName:            query.Get("build_name"),
   131  		},
   132  	}, nil
   133  }
   134  
   135  type allContainersLocator struct {
   136  	team db.Team
   137  }
   138  
   139  func (l *allContainersLocator) Locate(logger lager.Logger) ([]db.Container, map[int]time.Time, error) {
   140  	containers, err := l.team.Containers()
   141  	return containers, nil, err
   142  }
   143  
   144  type checkContainerLocator struct {
   145  	team          db.Team
   146  	pipelineRef   atc.PipelineRef
   147  	resourceName  string
   148  	secretManager creds.Secrets
   149  	varSourcePool creds.VarSourcePool
   150  }
   151  
   152  func (l *checkContainerLocator) Locate(logger lager.Logger) ([]db.Container, map[int]time.Time, error) {
   153  	return l.team.FindCheckContainers(logger, l.pipelineRef, l.resourceName, l.secretManager, l.varSourcePool)
   154  }
   155  
   156  type stepContainerLocator struct {
   157  	team     db.Team
   158  	metadata db.ContainerMetadata
   159  }
   160  
   161  func (l *stepContainerLocator) Locate(logger lager.Logger) ([]db.Container, map[int]time.Time, error) {
   162  	containers, err := l.team.FindContainersByMetadata(l.metadata)
   163  	return containers, nil, err
   164  }
   165  
   166  func parseIntParam(r *http.Request, name string) (int, error) {
   167  	var val int
   168  	param := r.URL.Query().Get(name)
   169  	if len(param) != 0 {
   170  		var err error
   171  		val, err = strconv.Atoi(param)
   172  		if err != nil {
   173  			return 0, fmt.Errorf("non-numeric '%s' param (%s): %s", name, param, err)
   174  		}
   175  	}
   176  
   177  	return val, nil
   178  }