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 }