Beispiel #1
0
// AllServices returns all services matching the criteria; that is, in
// the namespace (or any namespace if that argument is empty), and not
// in the `ignore` set given.
func (c *Cluster) AllServices(namespace string, ignore flux.ServiceIDSet) (res []platform.Service, err error) {
	namespaces := []string{}
	if namespace == "" {
		list, err := c.client.Namespaces().List(api.ListOptions{})
		if err != nil {
			return nil, errors.Wrap(err, "getting namespaces")
		}
		for _, ns := range list.Items {
			namespaces = append(namespaces, ns.Name)
		}
	} else {
		namespaces = []string{namespace}
	}

	for _, ns := range namespaces {
		controllers, err := c.podControllersInNamespace(ns)
		if err != nil {
			return nil, errors.Wrapf(err, "getting pod controllers for namespace %s", ns)
		}

		list, err := c.client.Services(ns).List(api.ListOptions{})
		if err != nil {
			return nil, errors.Wrapf(err, "getting services for namespace %s", ns)
		}

		for _, service := range list.Items {
			if !ignore.Contains(flux.MakeServiceID(ns, service.Name)) {
				res = append(res, c.makeService(ns, &service, controllers))
			}
		}
	}
	return res, nil
}
Beispiel #2
0
func TestRPC(t *testing.T) {
	namespace := "space-of-names"
	serviceID := flux.ServiceID(namespace + "/service")
	serviceList := []flux.ServiceID{serviceID}
	services := flux.ServiceIDSet{}
	services.Add(serviceList)

	regrades := []platform.RegradeSpec{
		platform.RegradeSpec{
			ServiceID:     serviceID,
			NewDefinition: []byte("imagine a definition here"),
		},
	}

	serviceAnswer := []platform.Service{
		platform.Service{
			ID:       flux.ServiceID("foobar/hello"),
			IP:       "10.32.1.45",
			Metadata: map[string]string{},
			Status:   "ok",
			Containers: platform.ContainersOrExcuse{
				Containers: []platform.Container{
					platform.Container{
						Name:  "frobnicator",
						Image: "quay.io/example.com/frob:v0.4.5",
					},
				},
			},
		},
		platform.Service{},
	}

	mock := &platform.MockPlatform{
		AllServicesArgTest: func(ns string, ss flux.ServiceIDSet) error {
			if !(ns == namespace &&
				ss.Contains(serviceID)) {
				return fmt.Errorf("did not get expected args, got %q, %+v", ns, ss)
			}
			return nil
		},
		AllServicesAnswer: serviceAnswer,

		SomeServicesArgTest: func(ss []flux.ServiceID) error {
			if !reflect.DeepEqual(ss, serviceList) {
				return fmt.Errorf("did not get expected args, got %+v", ss)
			}
			return nil
		},
		SomeServicesAnswer: serviceAnswer,

		RegradeArgTest: func(specs []platform.RegradeSpec) error {
			if !reflect.DeepEqual(regrades, specs) {
				return fmt.Errorf("did not get expected args, got %+v", specs)
			}
			return nil
		},
		RegradeError: nil,
	}

	clientConn, serverConn := pipes()

	server, err := NewServer(mock)
	if err != nil {
		t.Fatal(err)
	}
	go server.ServeConn(serverConn)

	client := NewClient(clientConn)
	if err := client.Ping(); err != nil {
		t.Fatal(err)
	}

	ss, err := client.AllServices(namespace, services)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(ss, mock.AllServicesAnswer) {
		t.Error(fmt.Errorf("expected %d result(s), got %+v", len(mock.AllServicesAnswer), ss))
	}
	mock.AllServicesError = fmt.Errorf("all services query failure")
	ss, err = client.AllServices(namespace, services)
	if err == nil {
		t.Error("expected error, got nil")
	}

	ss, err = client.SomeServices(serviceList)
	if err != nil {
		t.Error(err)
	}
	if !reflect.DeepEqual(ss, mock.SomeServicesAnswer) {
		t.Error(fmt.Errorf("expected %d result(s), got %+v", len(mock.SomeServicesAnswer), ss))
	}
	mock.SomeServicesError = fmt.Errorf("fail for some reason")
	ss, err = client.SomeServices(serviceList)
	if err == nil {
		t.Error("expected error, got nil")
	}

	err = client.Regrade(regrades)
	if err != nil {
		t.Error(err)
	}

	regradeErrors := platform.RegradeError{
		serviceID: fmt.Errorf("it just failed"),
	}
	mock.RegradeError = regradeErrors
	err = client.Regrade(regrades)
	if !reflect.DeepEqual(err, regradeErrors) {
		t.Errorf("expected RegradeError, got %#v", err)
	}
}
Beispiel #3
0
func (r *Releaser) Handle(job *jobs.Job, updater jobs.JobUpdater) (err error) {
	spec := job.Params.(jobs.ReleaseJobParams)
	releaseType := "unknown"
	defer func(begin time.Time) {
		r.metrics.ReleaseDuration.With(
			"release_type", releaseType,
			"release_kind", fmt.Sprint(spec.Kind),
			"success", fmt.Sprint(err == nil),
		).Observe(time.Since(begin).Seconds())
	}(time.Now())

	inst, err := r.instancer.Get(job.Instance)
	if err != nil {
		return err
	}

	inst.Logger = log.NewContext(inst.Logger).With("job", job.ID)

	updateJob := func(format string, args ...interface{}) {
		status := fmt.Sprintf(format, args...)
		job.Status = status
		job.Log = append(job.Log, status)
		updater.UpdateJob(*job)
	}

	exclude := flux.ServiceIDSet{}
	exclude.Add(spec.Excludes)

	locked, err := lockedServices(inst)
	if err != nil {
		return err
	}
	exclude.Add(locked)

	updateJob("Calculating release actions.")

	switch {
	case spec.ServiceSpec == flux.ServiceSpecAll && spec.ImageSpec == flux.ImageSpecLatest:
		releaseType = "release_all_to_latest"
		return r.releaseImages(releaseType, "Release latest images to all services", inst, spec.Kind, allServicesExcept(exclude), allLatestImages, updateJob)

	case spec.ServiceSpec == flux.ServiceSpecAll && spec.ImageSpec == flux.ImageSpecNone:
		releaseType = "release_all_without_update"
		return r.releaseWithoutUpdate(releaseType, "Apply latest config to all services", inst, spec.Kind, allServicesExcept(exclude), updateJob)

	case spec.ServiceSpec == flux.ServiceSpecAll:
		releaseType = "release_all_for_image"
		imageID := flux.ParseImageID(string(spec.ImageSpec))
		return r.releaseImages(releaseType, fmt.Sprintf("Release %s to all services", imageID), inst, spec.Kind, allServicesExcept(exclude), exactlyTheseImages([]flux.ImageID{imageID}), updateJob)

	case spec.ImageSpec == flux.ImageSpecLatest:
		releaseType = "release_one_to_latest"
		serviceID, err := flux.ParseServiceID(string(spec.ServiceSpec))
		if err != nil {
			return errors.Wrapf(err, "parsing service ID from spec %s", spec.ServiceSpec)
		}
		services := flux.ServiceIDs([]flux.ServiceID{serviceID}).Without(exclude)
		return r.releaseImages(releaseType, fmt.Sprintf("Release latest images to %s", serviceID), inst, spec.Kind, exactlyTheseServices(services), allLatestImages, updateJob)

	case spec.ImageSpec == flux.ImageSpecNone:
		releaseType = "release_one_without_update"
		serviceID, err := flux.ParseServiceID(string(spec.ServiceSpec))
		if err != nil {
			return errors.Wrapf(err, "parsing service ID from spec %s", spec.ServiceSpec)
		}
		services := flux.ServiceIDs([]flux.ServiceID{serviceID}).Without(exclude)
		return r.releaseWithoutUpdate(releaseType, fmt.Sprintf("Apply latest config to %s", serviceID), inst, spec.Kind, exactlyTheseServices(services), updateJob)

	default:
		releaseType = "release_one"
		serviceID, err := flux.ParseServiceID(string(spec.ServiceSpec))
		if err != nil {
			return errors.Wrapf(err, "parsing service ID from spec %s", spec.ServiceSpec)
		}
		services := flux.ServiceIDs([]flux.ServiceID{serviceID}).Without(exclude)
		imageID := flux.ParseImageID(string(spec.ImageSpec))
		return r.releaseImages(releaseType, fmt.Sprintf("Release %s to %s", imageID, serviceID), inst, spec.Kind, exactlyTheseServices(services), exactlyTheseImages([]flux.ImageID{imageID}), updateJob)
	}
}