예제 #1
0
func getContainerInfoRequest(body io.ReadCloser) (*info.ContainerInfoRequest, error) {
	var query info.ContainerInfoRequest

	// Default stats and samples is 64.
	query.NumStats = 64

	decoder := json.NewDecoder(body)
	err := decoder.Decode(&query)
	if err != nil && err != io.EOF {
		return nil, fmt.Errorf("unable to decode the json value: %s", err)
	}

	return &query, nil
}
예제 #2
0
// Get a container by name.
func (m *manager) GetContainerInfo(containerName string, query *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
	log.Printf("Get(%s); %+v", containerName, query)
	var cont *containerData
	var ok bool
	func() {
		m.containersLock.RLock()
		defer m.containersLock.RUnlock()

		// Ensure we have the container.
		cont, ok = m.containers[containerName]
	}()
	if !ok {
		return nil, fmt.Errorf("unknown container \"%s\"", containerName)
	}

	// Get the info from the container.
	cinfo, err := cont.GetInfo()
	if err != nil {
		return nil, err
	}

	var percentiles *info.ContainerStatsPercentiles
	var samples []*info.ContainerStatsSample
	var stats []*info.ContainerStats
	query = query.FillDefaults()
	percentiles, err = m.storageDriver.Percentiles(
		cinfo.Name,
		query.CpuUsagePercentiles,
		query.MemoryUsagePercentages,
	)
	if err != nil {
		return nil, err
	}
	samples, err = m.storageDriver.Samples(cinfo.Name, query.NumSamples)
	if err != nil {
		return nil, err
	}

	stats, err = m.storageDriver.RecentStats(cinfo.Name, query.NumStats)
	if err != nil {
		return nil, err
	}

	// Make a copy of the info for the user.
	ret := &info.ContainerInfo{
		ContainerReference: info.ContainerReference{
			Name:    cinfo.Name,
			Aliases: cinfo.Aliases,
		},
		Subcontainers:    cinfo.Subcontainers,
		Spec:             cinfo.Spec,
		StatsPercentiles: percentiles,
		Samples:          samples,
		Stats:            stats,
	}

	// Set default value to an actual value
	if ret.Spec.Memory != nil {
		// Memory.Limit is 0 means there's no limit
		if ret.Spec.Memory.Limit == 0 {
			ret.Spec.Memory.Limit = uint64(m.machineInfo.MemoryCapacity)
		}
	}
	return ret, nil
}
예제 #3
0
func TestGetContainerInfoWithDefaultValue(t *testing.T) {
	containers := []string{
		"/c1",
		"/c2",
	}

	var query *info.ContainerInfoRequest
	query = query.FillDefaults()

	infosMap := make(map[string]*info.ContainerInfo, len(containers))
	handlerMap := make(map[string]*ctest.MockContainerHandler, len(containers))

	for _, container := range containers {
		infosMap[container] = itest.GenerateRandomContainerInfo(container, 4, query, 1*time.Second)
	}

	driver := &stest.MockStorageDriver{}
	m := createManagerAndAddContainers(
		driver,
		containers,
		func(h *ctest.MockContainerHandler) {
			cinfo := infosMap[h.Name]
			stats := cinfo.Stats
			samples := cinfo.Samples
			percentiles := cinfo.StatsPercentiles
			spec := cinfo.Spec
			driver.On(
				"Percentiles",
				h.Name,
				query.CpuUsagePercentiles,
				query.MemoryUsagePercentages,
			).Return(
				percentiles,
				nil,
			)

			driver.On(
				"Samples",
				h.Name,
				query.NumSamples,
			).Return(
				samples,
				nil,
			)

			driver.On(
				"RecentStats",
				h.Name,
				query.NumStats,
			).Return(
				stats,
				nil,
			)

			h.On("ListContainers", container.LIST_SELF).Return(
				[]info.ContainerReference(nil),
				nil,
			)
			h.On("GetSpec").Return(
				spec,
				nil,
			)
			handlerMap[h.Name] = h
		},
		t,
	)

	returnedInfos := make(map[string]*info.ContainerInfo, len(containers))

	for _, container := range containers {
		// nil should give us default values
		cinfo, err := m.GetContainerInfo(container, nil)
		if err != nil {
			t.Fatalf("Unable to get info for container %v: %v", container, err)
		}
		returnedInfos[container] = cinfo
	}

	for container, handler := range handlerMap {
		handler.AssertExpectations(t)
		returned := returnedInfos[container]
		expected := infosMap[container]
		if !reflect.DeepEqual(returned, expected) {
			t.Errorf("returned unexpected info for container %v; returned %+v; expected %+v", container, returned, expected)
		}
	}

}
예제 #4
0
func HandleRequest(m manager.Manager, w http.ResponseWriter, r *http.Request) error {
	start := time.Now()

	u := r.URL

	// Get API request type.
	requestType := u.Path[len(ApiResource):]
	i := strings.Index(requestType, "/")
	requestArgs := ""
	if i != -1 {
		requestArgs = requestType[i:]
		requestType = requestType[:i]
	}

	switch {
	case requestType == MachineApi:
		log.Printf("Api - Machine")

		// Get the MachineInfo
		machineInfo, err := m.GetMachineInfo()
		if err != nil {
			return err
		}

		out, err := json.Marshal(machineInfo)
		if err != nil {
			fmt.Fprintf(w, "Failed to marshall MachineInfo with error: %s", err)
		}
		w.Write(out)
	case requestType == ContainersApi:
		// The container name is the path after the requestType
		containerName := requestArgs

		log.Printf("Api - Container(%s)", containerName)

		var query info.ContainerInfoRequest

		// If a user does not specify number of stats/samples he wants,
		// it's 64 by default
		query.NumStats = 64
		query.NumSamples = 64
		decoder := json.NewDecoder(r.Body)
		err := decoder.Decode(&query)
		if err != nil && err != io.EOF {
			return fmt.Errorf("unable to decode the json value: ", err)
		}
		// Get the container.
		cont, err := m.GetContainerInfo(containerName, &query)
		if err != nil {
			fmt.Fprintf(w, "Failed to get container \"%s\" with error: %s", containerName, err)
			return err
		}

		// Only output the container as JSON.
		out, err := json.Marshal(cont)
		if err != nil {
			fmt.Fprintf(w, "Failed to marshall container %q with error: %s", containerName, err)
		}
		w.Write(out)
	default:
		return fmt.Errorf("unknown API request type %q", requestType)
	}

	log.Printf("Request took %s", time.Since(start))
	return nil
}