mirror of
				https://github.com/k3s-io/kubernetes.git
				synced 2025-11-04 07:49:35 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			244 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
/*
 | 
						|
Copyright 2016 The Kubernetes Authors.
 | 
						|
 | 
						|
Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
you may not use this file except in compliance with the License.
 | 
						|
You may obtain a copy of the License at
 | 
						|
 | 
						|
    http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
 | 
						|
Unless required by applicable law or agreed to in writing, software
 | 
						|
distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
See the License for the specific language governing permissions and
 | 
						|
limitations under the License.
 | 
						|
*/
 | 
						|
 | 
						|
package main
 | 
						|
 | 
						|
import (
 | 
						|
	"flag"
 | 
						|
	"fmt"
 | 
						|
	"log"
 | 
						|
	"net/http"
 | 
						|
	"net/url"
 | 
						|
	"strconv"
 | 
						|
	"sync"
 | 
						|
 | 
						|
	. "k8s.io/kubernetes/test/images/resource-consumer/common"
 | 
						|
)
 | 
						|
 | 
						|
var port = flag.Int("port", 8080, "Port number.")
 | 
						|
var consumerPort = flag.Int("consumer-port", 8080, "Port number of consumers.")
 | 
						|
var consumerServiceName = flag.String("consumer-service-name", "resource-consumer", "Name of service containing resource consumers.")
 | 
						|
var consumerServiceNamespace = flag.String("consumer-service-namespace", "default", "Namespace of service containing resource consumers.")
 | 
						|
 | 
						|
func main() {
 | 
						|
	flag.Parse()
 | 
						|
	mgr := NewController()
 | 
						|
	log.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", *port), mgr))
 | 
						|
}
 | 
						|
 | 
						|
type Controller struct {
 | 
						|
	responseWriterLock sync.Mutex
 | 
						|
	waitGroup          sync.WaitGroup
 | 
						|
}
 | 
						|
 | 
						|
func NewController() *Controller {
 | 
						|
	c := &Controller{}
 | 
						|
	return c
 | 
						|
}
 | 
						|
 | 
						|
func (handler *Controller) ServeHTTP(w http.ResponseWriter, req *http.Request) {
 | 
						|
	if req.Method != "POST" {
 | 
						|
		http.Error(w, BadRequest, http.StatusBadRequest)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	// parsing POST request data and URL data
 | 
						|
	if err := req.ParseForm(); err != nil {
 | 
						|
		http.Error(w, err.Error(), http.StatusBadRequest)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	// handle consumeCPU
 | 
						|
	if req.URL.Path == ConsumeCPUAddress {
 | 
						|
		handler.handleConsumeCPU(w, req.Form)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	// handle consumeMem
 | 
						|
	if req.URL.Path == ConsumeMemAddress {
 | 
						|
		handler.handleConsumeMem(w, req.Form)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	// handle bumpMetric
 | 
						|
	if req.URL.Path == BumpMetricAddress {
 | 
						|
		handler.handleBumpMetric(w, req.Form)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	http.Error(w, UnknownFunction, http.StatusNotFound)
 | 
						|
}
 | 
						|
 | 
						|
func (handler *Controller) handleConsumeCPU(w http.ResponseWriter, query url.Values) {
 | 
						|
	// getting string data for consumeCPU
 | 
						|
	durationSecString := query.Get(DurationSecQuery)
 | 
						|
	millicoresString := query.Get(MillicoresQuery)
 | 
						|
	requestSizeInMillicoresString := query.Get(RequestSizeInMillicoresQuery)
 | 
						|
	if durationSecString == "" || millicoresString == "" || requestSizeInMillicoresString == "" {
 | 
						|
		http.Error(w, NotGivenFunctionArgument, http.StatusBadRequest)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// convert data (strings to ints) for consumeCPU
 | 
						|
	durationSec, durationSecError := strconv.Atoi(durationSecString)
 | 
						|
	millicores, millicoresError := strconv.Atoi(millicoresString)
 | 
						|
	requestSizeInMillicores, requestSizeInMillicoresError := strconv.Atoi(requestSizeInMillicoresString)
 | 
						|
	if durationSecError != nil || millicoresError != nil || requestSizeInMillicoresError != nil || requestSizeInMillicores <= 0 {
 | 
						|
		http.Error(w, IncorrectFunctionArgument, http.StatusBadRequest)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	count := millicores / requestSizeInMillicores
 | 
						|
	rest := millicores - count*requestSizeInMillicores
 | 
						|
	fmt.Fprintf(w, "RC manager: sending %v requests to consume %v millicores each and 1 request to consume %v millicores\n", count, requestSizeInMillicores, rest)
 | 
						|
	if count > 0 {
 | 
						|
		handler.waitGroup.Add(count)
 | 
						|
		handler.sendConsumeCPURequests(w, count, requestSizeInMillicores, durationSec)
 | 
						|
	}
 | 
						|
	if rest > 0 {
 | 
						|
		handler.waitGroup.Add(1)
 | 
						|
		go handler.sendOneConsumeCPURequest(w, rest, durationSec)
 | 
						|
	}
 | 
						|
	handler.waitGroup.Wait()
 | 
						|
}
 | 
						|
 | 
						|
func (handler *Controller) handleConsumeMem(w http.ResponseWriter, query url.Values) {
 | 
						|
	// getting string data for consumeMem
 | 
						|
	durationSecString := query.Get(DurationSecQuery)
 | 
						|
	megabytesString := query.Get(MegabytesQuery)
 | 
						|
	requestSizeInMegabytesString := query.Get(RequestSizeInMegabytesQuery)
 | 
						|
	if durationSecString == "" || megabytesString == "" || requestSizeInMegabytesString == "" {
 | 
						|
		http.Error(w, NotGivenFunctionArgument, http.StatusBadRequest)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// convert data (strings to ints) for consumeMem
 | 
						|
	durationSec, durationSecError := strconv.Atoi(durationSecString)
 | 
						|
	megabytes, megabytesError := strconv.Atoi(megabytesString)
 | 
						|
	requestSizeInMegabytes, requestSizeInMegabytesError := strconv.Atoi(requestSizeInMegabytesString)
 | 
						|
	if durationSecError != nil || megabytesError != nil || requestSizeInMegabytesError != nil || requestSizeInMegabytes <= 0 {
 | 
						|
		http.Error(w, IncorrectFunctionArgument, http.StatusBadRequest)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	count := megabytes / requestSizeInMegabytes
 | 
						|
	rest := megabytes - count*requestSizeInMegabytes
 | 
						|
	fmt.Fprintf(w, "RC manager: sending %v requests to consume %v MB each and 1 request to consume %v MB\n", count, requestSizeInMegabytes, rest)
 | 
						|
	if count > 0 {
 | 
						|
		handler.waitGroup.Add(count)
 | 
						|
		handler.sendConsumeMemRequests(w, count, requestSizeInMegabytes, durationSec)
 | 
						|
	}
 | 
						|
	if rest > 0 {
 | 
						|
		handler.waitGroup.Add(1)
 | 
						|
		go handler.sendOneConsumeMemRequest(w, rest, durationSec)
 | 
						|
	}
 | 
						|
	handler.waitGroup.Wait()
 | 
						|
}
 | 
						|
 | 
						|
func (handler *Controller) handleBumpMetric(w http.ResponseWriter, query url.Values) {
 | 
						|
	// getting string data for handleBumpMetric
 | 
						|
	metric := query.Get(MetricNameQuery)
 | 
						|
	deltaString := query.Get(DeltaQuery)
 | 
						|
	durationSecString := query.Get(DurationSecQuery)
 | 
						|
	requestSizeCustomMetricString := query.Get(RequestSizeCustomMetricQuery)
 | 
						|
	if durationSecString == "" || metric == "" || deltaString == "" || requestSizeCustomMetricString == "" {
 | 
						|
		http.Error(w, NotGivenFunctionArgument, http.StatusBadRequest)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	// convert data (strings to ints/floats) for handleBumpMetric
 | 
						|
	durationSec, durationSecError := strconv.Atoi(durationSecString)
 | 
						|
	delta, deltaError := strconv.Atoi(deltaString)
 | 
						|
	requestSizeCustomMetric, requestSizeCustomMetricError := strconv.Atoi(requestSizeCustomMetricString)
 | 
						|
	if durationSecError != nil || deltaError != nil || requestSizeCustomMetricError != nil || requestSizeCustomMetric <= 0 {
 | 
						|
		http.Error(w, IncorrectFunctionArgument, http.StatusBadRequest)
 | 
						|
		return
 | 
						|
	}
 | 
						|
 | 
						|
	count := delta / requestSizeCustomMetric
 | 
						|
	rest := delta - count*requestSizeCustomMetric
 | 
						|
	fmt.Fprintf(w, "RC manager: sending %v requests to bump custom metric by %v each and 1 request to bump by %v\n", count, requestSizeCustomMetric, rest)
 | 
						|
	if count > 0 {
 | 
						|
		handler.waitGroup.Add(count)
 | 
						|
		handler.sendConsumeCustomMetric(w, metric, count, requestSizeCustomMetric, durationSec)
 | 
						|
	}
 | 
						|
	if rest > 0 {
 | 
						|
		handler.waitGroup.Add(1)
 | 
						|
		go handler.sendOneConsumeCustomMetric(w, metric, rest, durationSec)
 | 
						|
	}
 | 
						|
	handler.waitGroup.Wait()
 | 
						|
}
 | 
						|
 | 
						|
func (manager *Controller) sendConsumeCPURequests(w http.ResponseWriter, requests, millicores, durationSec int) {
 | 
						|
	for i := 0; i < requests; i++ {
 | 
						|
		go manager.sendOneConsumeCPURequest(w, millicores, durationSec)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (manager *Controller) sendConsumeMemRequests(w http.ResponseWriter, requests, megabytes, durationSec int) {
 | 
						|
	for i := 0; i < requests; i++ {
 | 
						|
		go manager.sendOneConsumeMemRequest(w, megabytes, durationSec)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func (manager *Controller) sendConsumeCustomMetric(w http.ResponseWriter, metric string, requests, delta, durationSec int) {
 | 
						|
	for i := 0; i < requests; i++ {
 | 
						|
		go manager.sendOneConsumeCustomMetric(w, metric, delta, durationSec)
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func createConsumerURL(suffix string) string {
 | 
						|
	return fmt.Sprintf("http://%s.%s.svc.cluster.local:%d%s", *consumerServiceName, *consumerServiceNamespace, *consumerPort, suffix)
 | 
						|
}
 | 
						|
 | 
						|
// sendOneConsumeCPURequest sends POST request for cpu consumption
 | 
						|
func (c *Controller) sendOneConsumeCPURequest(w http.ResponseWriter, millicores int, durationSec int) {
 | 
						|
	defer c.waitGroup.Done()
 | 
						|
	query := createConsumerURL(ConsumeCPUAddress)
 | 
						|
	_, err := http.PostForm(query, url.Values{MillicoresQuery: {strconv.Itoa(millicores)}, DurationSecQuery: {strconv.Itoa(durationSec)}})
 | 
						|
	c.responseWriterLock.Lock()
 | 
						|
	defer c.responseWriterLock.Unlock()
 | 
						|
	if err != nil {
 | 
						|
		fmt.Fprintf(w, "Failed to connect to consumer: %v\n", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	fmt.Fprintf(w, "Consumed %d millicores\n", millicores)
 | 
						|
}
 | 
						|
 | 
						|
// sendOneConsumeMemRequest sends POST request for memory consumption
 | 
						|
func (c *Controller) sendOneConsumeMemRequest(w http.ResponseWriter, megabytes int, durationSec int) {
 | 
						|
	defer c.waitGroup.Done()
 | 
						|
	query := createConsumerURL(ConsumeMemAddress)
 | 
						|
	_, err := http.PostForm(query, url.Values{MegabytesQuery: {strconv.Itoa(megabytes)}, DurationSecQuery: {strconv.Itoa(durationSec)}})
 | 
						|
	c.responseWriterLock.Lock()
 | 
						|
	defer c.responseWriterLock.Unlock()
 | 
						|
	if err != nil {
 | 
						|
		fmt.Fprintf(w, "Failed to connect to consumer: %v\n", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	fmt.Fprintf(w, "Consumed %d megabytes\n", megabytes)
 | 
						|
}
 | 
						|
 | 
						|
// sendOneConsumeCustomMetric sends POST request for custom metric consumption
 | 
						|
func (c *Controller) sendOneConsumeCustomMetric(w http.ResponseWriter, customMetricName string, delta int, durationSec int) {
 | 
						|
	defer c.waitGroup.Done()
 | 
						|
	query := createConsumerURL(BumpMetricAddress)
 | 
						|
	_, err := http.PostForm(query,
 | 
						|
		url.Values{MetricNameQuery: {customMetricName}, DurationSecQuery: {strconv.Itoa(durationSec)}, DeltaQuery: {strconv.Itoa(delta)}})
 | 
						|
	c.responseWriterLock.Lock()
 | 
						|
	defer c.responseWriterLock.Unlock()
 | 
						|
	if err != nil {
 | 
						|
		fmt.Fprintf(w, "Failed to connect to consumer: %v\n", err)
 | 
						|
		return
 | 
						|
	}
 | 
						|
	fmt.Fprintf(w, "Bumped metric %s by %d\n", customMetricName, delta)
 | 
						|
}
 |