// List ... func (t *TargetAPI) List() { name := t.GetString("name") targets, err := dao.FilterRepTargets(name) if err != nil { log.Errorf("failed to filter targets %s: %v", name, err) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } for _, target := range targets { if len(target.Password) == 0 { continue } str, err := utils.ReversibleDecrypt(target.Password) if err != nil { log.Errorf("failed to decrypt password: %v", err) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } target.Password = str } t.Data["json"] = targets t.ServeJSON() return }
// Get ... func (t *TargetAPI) Get() { id := t.GetIDFromURL() target, err := dao.GetRepTarget(id) if err != nil { log.Errorf("failed to get target %d: %v", id, err) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } if target == nil { t.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound)) } // The reason why the password is returned is that when user just wants to // modify other fields of target he does not need to input the password again. // The security issue can be fixed by enable https. if len(target.Password) != 0 { pwd, err := utils.ReversibleDecrypt(target.Password) if err != nil { log.Errorf("failed to decrypt password: %v", err) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } target.Password = pwd } t.Data["json"] = target t.ServeJSON() }
// Reset resets the state machine so it will start handling another job. func (sm *SM) Reset(jid int64) error { //To ensure the new jobID is visible to the thread to stop the SM sm.lock.Lock() sm.JobID = jid sm.desiredState = "" sm.lock.Unlock() sm.Logger = utils.NewLogger(sm.JobID) //init parms job, err := dao.GetRepJob(sm.JobID) if err != nil { return fmt.Errorf("Failed to get job, error: %v", err) } if job == nil { return fmt.Errorf("The job doesn't exist in DB, job id: %d", sm.JobID) } policy, err := dao.GetRepPolicy(job.PolicyID) if err != nil { return fmt.Errorf("Failed to get policy, error: %v", err) } if policy == nil { return fmt.Errorf("The policy doesn't exist in DB, policy id:%d", job.PolicyID) } sm.Parms = &RepJobParm{ LocalRegURL: config.LocalRegURL(), Repository: job.Repository, Tags: job.TagList, Enabled: policy.Enabled, Operation: job.Operation, Insecure: !config.VerifyRemoteCert(), } if policy.Enabled == 0 { //worker will cancel this job return nil } target, err := dao.GetRepTarget(policy.TargetID) if err != nil { return fmt.Errorf("Failed to get target, error: %v", err) } if target == nil { return fmt.Errorf("The target doesn't exist in DB, target id: %d", policy.TargetID) } sm.Parms.TargetURL = target.URL sm.Parms.TargetUsername = target.Username pwd := target.Password if len(pwd) != 0 { pwd, err = uti.ReversibleDecrypt(pwd) if err != nil { return fmt.Errorf("failed to decrypt password: %v", err) } } sm.Parms.TargetPassword = pwd //init states handlers sm.Handlers = make(map[string]StateHandler) sm.Transitions = make(map[string]map[string]struct{}) sm.CurrentState = models.JobPending sm.AddTransition(models.JobPending, models.JobRunning, StatusUpdater{sm.JobID, models.JobRunning}) sm.AddTransition(models.JobRetrying, models.JobRunning, StatusUpdater{sm.JobID, models.JobRunning}) sm.Handlers[models.JobError] = StatusUpdater{sm.JobID, models.JobError} sm.Handlers[models.JobStopped] = StatusUpdater{sm.JobID, models.JobStopped} sm.Handlers[models.JobRetrying] = Retry{sm.JobID} switch sm.Parms.Operation { case models.RepOpTransfer: addImgTransferTransition(sm) case models.RepOpDelete: addImgDeleteTransition(sm) default: err = fmt.Errorf("unsupported operation: %s", sm.Parms.Operation) } return err }
// Ping validates whether the target is reachable and whether the credential is valid func (t *TargetAPI) Ping() { var endpoint, username, password string idStr := t.GetString("id") if len(idStr) != 0 { id, err := strconv.ParseInt(idStr, 10, 64) if err != nil { t.CustomAbort(http.StatusBadRequest, fmt.Sprintf("id %s is invalid", idStr)) } target, err := dao.GetRepTarget(id) if err != nil { log.Errorf("failed to get target %d: %v", id, err) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } if target == nil { t.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound)) } endpoint = target.URL username = target.Username password = target.Password if len(password) != 0 { password, err = utils.ReversibleDecrypt(password) if err != nil { log.Errorf("failed to decrypt password: %v", err) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } } } else { endpoint = t.GetString("endpoint") if len(endpoint) == 0 { t.CustomAbort(http.StatusBadRequest, "id or endpoint is needed") } username = t.GetString("username") password = t.GetString("password") } registry, err := newRegistryClient(endpoint, getIsInsecure(), username, password, "", "", "") if err != nil { // timeout, dns resolve error, connection refused, etc. if urlErr, ok := err.(*url.Error); ok { if netErr, ok := urlErr.Err.(net.Error); ok { t.CustomAbort(http.StatusBadRequest, netErr.Error()) } t.CustomAbort(http.StatusBadRequest, urlErr.Error()) } log.Errorf("failed to create registry client: %#v", err) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } if err = registry.Ping(); err != nil { if regErr, ok := err.(*registry_error.Error); ok { t.CustomAbort(regErr.StatusCode, regErr.Detail) } log.Errorf("failed to ping registry %s: %v", registry.Endpoint.String(), err) t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) } }