예제 #1
0
// 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
}
예제 #2
0
// 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()
}
예제 #3
0
// 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
}
예제 #4
0
// 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))
	}
}